<commit_before>use atom::*;
use env::Env;
use errors::*;
use funcs::*;
use eval::*;
use opcodes::*;
use opcodes::Opcode::*;
use compiler;

#[derive (Debug, Clone)]
struct Frame {
    program: CompiledFunction,
    pc: usize,
}

impl Frame {
    fn new(f: CompiledFunction) -> Frame {
        Frame {
            program: f,
            pc: 0,
        }
    }

    fn current_instruction(&self) -> Option<&Opcode> {
        self.program.body.get(self.pc)
    }
}

#[derive (Debug)]
pub struct VirtualMachine {
    stack: Vec<Atom>,
    frames: Vec<Frame>,
    fp: usize,
    sp: usize,
    root: Env,
}

impl Default for VirtualMachine {
    fn default() -> VirtualMachine {
        use base_lib;
        let mut vm = VirtualMachine {
            stack: vec![],
            frames: vec![],
            fp: 0,
            sp: 0,
            root: Env::default(),
        };
        base_lib::library()
            .and_then(|n| vm.run_node(n))
            .expect("base library should always compile and run!");

        vm
    }
}

fn eval_native_borrow(v: &mut VirtualMachine, n: Native, len: usize) -> AtomResult {
    let &mut VirtualMachine { ref mut stack, ref mut frames, fp, .. } = v;
    eval_native(n, &stack[len..], &mut frames[fp].program.env)
}

fn recur_borrow(v: &mut VirtualMachine, len: usize) {
    let &mut VirtualMachine { ref mut stack, ref mut frames, fp, sp, .. } = v;
    let frame = &mut frames[fp];
    frame.program.env.bind_mut(&frame.program.params, &stack[sp - len..]);
    frame.pc = 0;
}

impl VirtualMachine {
    pub fn run_node(&mut self, node: Atom) -> AtomResult {
        let mut out = vec![];
        let source = try!(node.as_list()).clone();
        let mut e = self.root.clone();
        try!(compiler::compile(node, &mut out, &mut e));

        let frame = Frame::new(CompiledFunction {
            body: out,
            source: source,
            params: empty_list(),
            env: e,
        });
        self.frames.push(frame);
        self.run()
    }

    pub fn print_stack(&self) {
        for (i, item) in self.stack.iter().rev().enumerate() {
            println!("{}: {}", -(i as i32), item);
        }
    }

    pub fn eval_string(&mut self, s: &str) -> AtomResult {
        use parser;
        parser::tokenize(s).and_then(|a| self.run_node(a))
    }

    fn next_instruction(&self) -> Option<Opcode> {
        self.frames[self.fp].current_instruction().cloned()
    }

    fn current_frame(&mut self) -> &mut Frame {
        &mut self.frames[self.fp]
    }

    fn current_env(&mut self) -> &mut Env {
        &mut self.current_frame().program.env
    }

    pub fn run(&mut self) -> AtomResult {
        while let Some(instruction) = self.next_instruction() {
            trace!("{} - {}", self.current_frame().pc, instruction);
            match instruction {
                JUMP_IFNOT(addr) => {
                    if !try!(self.pop()).as_bool() {
                        self.current_frame().pc = addr;
                        continue;
                    }
                }
                JUMP(addr) => {
                    self.current_frame().pc = addr;
                    continue;
                }
                POP => {
                    try!(self.pop());
                }
                RETURN => {
                    self.frames.pop();
                    if self.fp > 0 {
                        self.fp -= 1;
                    } else {
                        return self.pop();
                    }
                }
                LOAD(sym) => {
                    let value =
                        self.current_frame().program.env.get(sym.as_ref()).unwrap_or(Atom::Nil);
                    self.push(value);
                }
                CONST(ref atom) => self.push(atom.clone()),
                DEFINE(sym) => {
                    let v = try!(self.pop());
                    let a = try!(self.current_env().define(sym, v));
                    self.push(a);
                }
                STORE(sym) => {
                    let v = try!(self.pop());
                    let a = try!(self.current_env().set(sym, v));
                    self.push(a);
                }
                RECUR(arity) => {
                    recur_borrow(self, arity);
                    for _ in 0..arity {
                        try!(self.pop());
                    }
                    continue;
                }
                APPLY => {
                    let args = try!(self.pop());
                    let func = try!(self.pop());
                    let arg_list = try!(args.as_list());
                    match func {
                        Atom::Function(Function::Compiled(mut f)) => {
                            f.env.bind_mut(&f.params, arg_list);
                            self.frames.push(Frame::new(f.clone()));
                            self.fp += 1;
                            continue; // don't advance PC of the new frame
                        }
                        Atom::Function(Function::Native(f)) => {
                            let x = try!(eval_native(f,
                                                     arg_list,
                                                     &mut self.frames[self.fp].program.env));
                            self.push(x);
                        }
                        Atom::Function(Function::Proc(ref f)) => {
                            println!("compiled functions only!");
                            println!("{}", print_list(&f.body));
                            return Err(Error::NotImplemented);
                        }
                        _ => {
                            println!("attempted to call: {}", func);
                            return Err(Error::NotAFunction);
                        }
                    }
                }
                DCALL(arity) => {
                    let func = try!(self.pop());
                    match func {
                        Atom::Function(Function::Compiled(mut f)) => {
                            f.env.bind_mut(&f.params, &self.stack[self.sp - arity..]);
                            for _ in 0..arity {
                                try!(self.pop());
                            }
                            self.frames.push(Frame::new(f.clone()));
                            self.fp += 1;
                            continue; // don't advance PC of the new frame
                        }
                        Atom::Function(Function::Proc(ref f)) => {
                            println!("compiled functions only!");
                            println!("{}", print_list(&f.body));
                            return Err(Error::NotImplemented);
                        }
                        _ => {
                            println!("attempted to call: {}", func);
                            return Err(Error::NotAFunction);
                        }
                    }
                }
                CALL(func, arity) => {
                    match func {
                        Function::Native(n) => {
                            let len = self.stack.len();
                            let r = try!(eval_native_borrow(self, n, len - arity));
                            for _ in 0..arity {
                                try!(self.pop());
                            }
                            self.push(r);
                        }
                        _ => return Err(Error::NotImplemented),
                    }
                }
            }
            self.current_frame().pc += 1;
        }
        self.frames.pop().unwrap();
        self.pop()
    }

    fn push(&mut self, a: Atom) {
        self.stack.push(a);
        self.sp += 1
    }

    fn pop(&mut self) -> AtomResult {
        if self.sp > 0 {
            self.sp -= 1;
            self.stack.pop().ok_or(Error::RuntimeAssertion)
        } else {
            println!("StackUnderflow!");
            Err(Error::RuntimeAssertion)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use atom::*;
    fn run_expr(s: &str) -> Atom {
        let p = tokenize(s).unwrap();
        let mut vm = VirtualMachine::default();
        vm.run_node(p).unwrap()
    }

    #[test]
    fn test() {
        assert_eq!(Atom::from(6), run_expr("(+ (+ 2 2) 2)"));
        assert_eq!(Atom::symbol("a"), run_expr("(def a 1)"));
        assert_eq!(Atom::from(3),
                   run_expr("(do (def foo (fn (x) (+ x 2))) (foo 1))"));
    }

    #[test]
    fn test_invoke_fn_inline() {
        assert_eq!(Atom::from(1), run_expr("((fn (x) 1) 0)"));
    }

    #[test]
    fn test_closure() {
        assert_eq!(Atom::from(2),
                   run_expr("(do (def foo (fn (x) (fn () (* 2 x)))) (def foo2 (foo 1)) (foo2))"))
    }

    #[test]
    fn let_binding() {
        assert_eq!(Atom::from(-1), run_expr("(let* ((x 2) (y 3)) (- x y))"));
    }

    #[test]
    fn nested_let() {
        assert_eq!(Atom::from(0),
                   run_expr("(do (let* ((x 1)) (let* ((x 0)) x)))"))
    }

    #[test]
    fn if_test() {
        assert_eq!(Atom::from(0), run_expr("(if false 1 0)"));
        assert_eq!(Atom::from(1), run_expr("(if true 1 0)"));
    }

    #[test]
    fn quote_test() {
        assert_eq!(Atom::list(vec![Atom::from(0), Atom::from(1)]),
                   run_expr("'(0 1)"));
    }

    #[test]
    fn filter_test() {
        assert_eq!(Atom::list(vec![Atom::from(0)]),
                   run_expr("(filter (fn (x) (= 0 x)) '(1 1 1 1 0 1))"));
    }

    #[test]
    fn recur_test() {
        let s = include_str!("../test/recur.lisp");
        assert_eq!(Atom::from(0), run_expr(s));
    }

    #[test]
    fn map_test() {
        assert_eq!(run_expr("'(1 2)"),
                   run_expr("(map (fn (x) (+ x 1)) '(0 1))"));

    }

    #[test]
    fn map_leak_test() {
        let mut vm = VirtualMachine::default();
        let l = Atom::list(vec![Atom::from(1), Atom::from(2)]);
        assert_eq!(l, vm.eval_string("(map (fn (x) (+ x 1)) '(0 1))").unwrap());
        assert_eq!(l, vm.eval_string("(map (fn (x) (+ x 1)) '(0 1))").unwrap());
    }

    #[test]
    fn reduce_test() {
        assert_eq!(Atom::from(0),
                   run_expr("(reduce (fn (acc i) (- acc i)) 5 '(1 1 1 1 1))"));
    }

    #[test]
    fn apply_test() {
        assert_eq!(Atom::from(0), run_expr("(apply (fn (x) 0) '())"));
        assert_eq!(Atom::from(3),
                   run_expr("(apply (fn (x y) (+ x y 1)) '(1 1))"));
        assert_eq!(Atom::from(1),
                   run_expr("(apply (fn (x & y) (count y)) '(1 1))"));
    }

    #[test]
    fn get_test() {
        assert_eq!(Atom::from(0), run_expr("(get '(0 2) 0)"));
        assert_eq!(Atom::from(0), run_expr("(get '(2 0) 1)"));
    }

    #[test]
    fn cond_test() {
        assert_eq!(Atom::from(0), run_expr("(cond (true 0))"));
        assert_eq!(Atom::from(0), run_expr("(cond (false 1) (true 0))"));
        assert_eq!(Atom::from(0),
                   run_expr("(cond (false 1) ((= 0 1) 2) (true 0))"));
    }

    #[test]
    fn run_suite() {
        let suite = include_str!("../test/suite.lisp");
        assert_eq!(Atom::from(true), run_expr(suite));
    }
}
<commit_msg>add native dyn call<commit_after>use atom::*;
use env::Env;
use errors::*;
use funcs::*;
use eval::*;
use opcodes::*;
use opcodes::Opcode::*;
use compiler;

#[derive (Debug, Clone)]
struct Frame {
    program: CompiledFunction,
    pc: usize,
}

impl Frame {
    fn new(f: CompiledFunction) -> Frame {
        Frame {
            program: f,
            pc: 0,
        }
    }

    fn current_instruction(&self) -> Option<&Opcode> {
        self.program.body.get(self.pc)
    }
}

#[derive (Debug)]
pub struct VirtualMachine {
    stack: Vec<Atom>,
    frames: Vec<Frame>,
    fp: usize,
    sp: usize,
    root: Env,
}

impl Default for VirtualMachine {
    fn default() -> VirtualMachine {
        use base_lib;
        let mut vm = VirtualMachine {
            stack: vec![],
            frames: vec![],
            fp: 0,
            sp: 0,
            root: Env::default(),
        };
        base_lib::library()
            .and_then(|n| vm.run_node(n))
            .expect("base library should always compile and run!");

        vm
    }
}

fn eval_native_borrow(v: &mut VirtualMachine, n: Native, len: usize) -> AtomResult {
    let &mut VirtualMachine { ref mut stack, ref mut frames, fp, .. } = v;
    eval_native(n, &stack[len..], &mut frames[fp].program.env)
}

fn recur_borrow(v: &mut VirtualMachine, len: usize) {
    let &mut VirtualMachine { ref mut stack, ref mut frames, fp, sp, .. } = v;
    let frame = &mut frames[fp];
    frame.program.env.bind_mut(&frame.program.params, &stack[sp - len..]);
    frame.pc = 0;
}

impl VirtualMachine {
    pub fn run_node(&mut self, node: Atom) -> AtomResult {
        let mut out = vec![];
        let source = try!(node.as_list()).clone();
        let mut e = self.root.clone();
        try!(compiler::compile(node, &mut out, &mut e));

        let frame = Frame::new(CompiledFunction {
            body: out,
            source: source,
            params: empty_list(),
            env: e,
        });
        self.frames.push(frame);
        self.run()
    }

    pub fn print_stack(&self) {
        for (i, item) in self.stack.iter().rev().enumerate() {
            println!("{}: {}", -(i as i32), item);
        }
    }

    pub fn eval_string(&mut self, s: &str) -> AtomResult {
        use parser;
        parser::tokenize(s).and_then(|a| self.run_node(a))
    }

    fn next_instruction(&self) -> Option<Opcode> {
        self.frames[self.fp].current_instruction().cloned()
    }

    fn current_frame(&mut self) -> &mut Frame {
        &mut self.frames[self.fp]
    }

    fn current_env(&mut self) -> &mut Env {
        &mut self.current_frame().program.env
    }

    pub fn run(&mut self) -> AtomResult {
        while let Some(instruction) = self.next_instruction() {
            trace!("{} - {}", self.current_frame().pc, instruction);
            match instruction {
                JUMP_IFNOT(addr) => {
                    if !try!(self.pop()).as_bool() {
                        self.current_frame().pc = addr;
                        continue;
                    }
                }
                JUMP(addr) => {
                    self.current_frame().pc = addr;
                    continue;
                }
                POP => {
                    try!(self.pop());
                }
                RETURN => {
                    self.frames.pop();
                    if self.fp > 0 {
                        self.fp -= 1;
                    } else {
                        return self.pop();
                    }
                }
                LOAD(sym) => {
                    let value =
                        self.current_frame().program.env.get(sym.as_ref()).unwrap_or(Atom::Nil);
                    self.push(value);
                }
                CONST(ref atom) => self.push(atom.clone()),
                DEFINE(sym) => {
                    let v = try!(self.pop());
                    let a = try!(self.current_env().define(sym, v));
                    self.push(a);
                }
                STORE(sym) => {
                    let v = try!(self.pop());
                    let a = try!(self.current_env().set(sym, v));
                    self.push(a);
                }
                RECUR(arity) => {
                    recur_borrow(self, arity);
                    for _ in 0..arity {
                        try!(self.pop());
                    }
                    continue;
                }
                APPLY => {
                    let args = try!(self.pop());
                    let func = try!(self.pop());
                    let arg_list = try!(args.as_list());
                    match func {
                        Atom::Function(Function::Compiled(mut f)) => {
                            f.env.bind_mut(&f.params, arg_list);
                            self.frames.push(Frame::new(f.clone()));
                            self.fp += 1;
                            continue; // don't advance PC of the new frame
                        }
                        Atom::Function(Function::Native(f)) => {
                            let x = try!(eval_native(f,
                                                     arg_list,
                                                     &mut self.frames[self.fp].program.env));
                            self.push(x);
                        }
                        Atom::Function(Function::Proc(ref f)) => {
                            println!("compiled functions only!");
                            println!("{}", print_list(&f.body));
                            return Err(Error::NotImplemented);
                        }
                        _ => {
                            println!("attempted to call: {}", func);
                            return Err(Error::NotAFunction);
                        }
                    }
                }
                DCALL(arity) => {
                    let func = try!(self.pop());
                    match func {
                        Atom::Function(Function::Compiled(mut f)) => {
                            f.env.bind_mut(&f.params, &self.stack[self.sp - arity..]);
                            for _ in 0..arity {
                                try!(self.pop());
                            }
                            self.frames.push(Frame::new(f.clone()));
                            self.fp += 1;
                            continue; // don't advance PC of the new frame
                        }
                        Atom::Function(Function::Proc(ref f)) => {
                            println!("compiled functions only!");
                            println!("{}", print_list(&f.body));
                            return Err(Error::NotImplemented);
                        }
                        Atom::Function(Function::Native(n)) => {
                            let len = self.stack.len();
                            let r = try!(eval_native_borrow(self, n, len - arity));
                            for _ in 0..arity {
                                try!(self.pop());
                            }
                            self.push(r);
                        }
                        _ => {
                            println!("attempted to call: {}", func);
                            return Err(Error::NotAFunction);
                        }
                    }
                }
                CALL(func, arity) => {
                    match func {
                        Function::Native(n) => {
                            let len = self.stack.len();
                            let r = try!(eval_native_borrow(self, n, len - arity));
                            for _ in 0..arity {
                                try!(self.pop());
                            }
                            self.push(r);
                        }
                        _ => return Err(Error::NotImplemented),
                    }
                }
            }
            self.current_frame().pc += 1;
        }
        self.frames.pop().unwrap();
        self.pop()
    }

    fn push(&mut self, a: Atom) {
        self.stack.push(a);
        self.sp += 1
    }

    fn pop(&mut self) -> AtomResult {
        if self.sp > 0 {
            self.sp -= 1;
            self.stack.pop().ok_or(Error::RuntimeAssertion)
        } else {
            println!("StackUnderflow!");
            Err(Error::RuntimeAssertion)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use atom::*;
    fn run_expr(s: &str) -> Atom {
        let p = tokenize(s).unwrap();
        let mut vm = VirtualMachine::default();
        vm.run_node(p).unwrap()
    }

    #[test]
    fn test() {
        assert_eq!(Atom::from(6), run_expr("(+ (+ 2 2) 2)"));
        assert_eq!(Atom::symbol("a"), run_expr("(def a 1)"));
        assert_eq!(Atom::from(3),
                   run_expr("(do (def foo (fn (x) (+ x 2))) (foo 1))"));
    }

    #[test]
    fn test_invoke_fn_inline() {
        assert_eq!(Atom::from(1), run_expr("((fn (x) 1) 0)"));
    }

    #[test]
    fn test_closure() {
        assert_eq!(Atom::from(2),
                   run_expr("(do (def foo (fn (x) (fn () (* 2 x)))) (def foo2 (foo 1)) (foo2))"))
    }

    #[test]
    fn let_binding() {
        assert_eq!(Atom::from(-1), run_expr("(let* ((x 2) (y 3)) (- x y))"));
    }

    #[test]
    fn nested_let() {
        assert_eq!(Atom::from(0),
                   run_expr("(do (let* ((x 1)) (let* ((x 0)) x)))"))
    }

    #[test]
    fn if_test() {
        assert_eq!(Atom::from(0), run_expr("(if false 1 0)"));
        assert_eq!(Atom::from(1), run_expr("(if true 1 0)"));
    }

    #[test]
    fn quote_test() {
        assert_eq!(Atom::list(vec![Atom::from(0), Atom::from(1)]),
                   run_expr("'(0 1)"));
    }

    #[test]
    fn filter_test() {
        assert_eq!(Atom::list(vec![Atom::from(0)]),
                   run_expr("(filter (fn (x) (= 0 x)) '(1 1 1 1 0 1))"));
    }

    #[test]
    fn recur_test() {
        let s = include_str!("../test/recur.lisp");
        assert_eq!(Atom::from(0), run_expr(s));
    }

    #[test]
    fn map_test() {
        assert_eq!(run_expr("'(1 2)"),
                   run_expr("(map (fn (x) (+ x 1)) '(0 1))"));

    }

    #[test]
    fn map_leak_test() {
        let mut vm = VirtualMachine::default();
        let l = Atom::list(vec![Atom::from(1), Atom::from(2)]);
        assert_eq!(l, vm.eval_string("(map (fn (x) (+ x 1)) '(0 1))").unwrap());
        assert_eq!(l, vm.eval_string("(map (fn (x) (+ x 1)) '(0 1))").unwrap());
    }

    #[test]
    fn reduce_test() {
        assert_eq!(Atom::from(0),
                   run_expr("(reduce (fn (acc i) (- acc i)) 5 '(1 1 1 1 1))"));
    }

    #[test]
    fn apply_test() {
        assert_eq!(Atom::from(0), run_expr("(apply (fn (x) 0) '())"));
        assert_eq!(Atom::from(3),
                   run_expr("(apply (fn (x y) (+ x y 1)) '(1 1))"));
        assert_eq!(Atom::from(1),
                   run_expr("(apply (fn (x & y) (count y)) '(1 1))"));
    }

    #[test]
    fn get_test() {
        assert_eq!(Atom::from(0), run_expr("(get '(0 2) 0)"));
        assert_eq!(Atom::from(0), run_expr("(get '(2 0) 1)"));
    }

    #[test]
    fn cond_test() {
        assert_eq!(Atom::from(0), run_expr("(cond (true 0))"));
        assert_eq!(Atom::from(0), run_expr("(cond (false 1) (true 0))"));
        assert_eq!(Atom::from(0),
                   run_expr("(cond (false 1) ((= 0 1) 2) (true 0))"));
    }

    #[test]
    fn map_native_test() {
        assert_eq!(Atom::list(vec![Atom::from(1), Atom::from(2)]),
                   run_expr("(map + '(1 2))"));
    }

    #[test]
    fn run_suite() {
        let suite = include_str!("../test/suite.lisp");
        assert_eq!(Atom::from(true), run_expr(suite));
    }
}
<|endoftext|>


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

pub mod vec {
    use ::{Transducer, Reducing};

    pub trait Ref {
        type Input;

        fn transduce_ref<'a, T, O, RO, E>(&'a self, transducer: T) -> Result<Vec<O>, E>
            where RO: Reducing<&'a Self::Input, Vec<O>, E>,
                  T: Transducer<RefReducer<O>, RO=RO>;
    }

    struct RefReducer<O>(Vec<O>);

    impl<'a, O> Reducing<O, Vec<O>, ()> for RefReducer<O> {
        type Item = O;

        #[inline]
        fn step(&mut self, value: O) -> Result<(), ()> {
            self.0.push(value);
            Ok(())
        }

        fn complete(self) -> Vec<O> {
            self.0
        }
    }

    impl<X> Ref for Vec<X> {
        type Input = X;

        fn transduce_ref<'a, T, O, RO, E>(&'a self, mut transducer: T) -> Result<Vec<O>, E>
            where RO: Reducing<&'a Self::Input, Vec<O>, E>,
                  T: Transducer<RefReducer<O>, RO=RO> {
            let rr = RefReducer(Vec::with_capacity(self.len()));
            let mut reducing = transducer.new(rr);
            reducing.init();
            for val in self.iter() {
                try!(reducing.step(val));
            }
            Ok(reducing.complete())
        }
    }

    // pub trait Drain {
    //     type Input;

    //     fn transduce_drain<T, O>(mut self, transducer: T) -> Vec<O>
    //         where T: Transducer<Self::Input, O>;
    // }

    // impl<X> Drain for Vec<X> {
    //     type Input = X;

    //     fn transduce_drain<T, O>(mut self, mut transducer: T) -> Vec<O>
    //         where T: Transducer<Self::Input, O> {

    //         let mut result = Vec::with_capacity(self.len());
    //         for val in self.drain(..) {
    //             match transducer.accept(Some(val)) {
    //                 TransductionResult::End => { return result; },
    //                 TransductionResult::None => (),
    //                 TransductionResult::Some(r) => { result.push(r); }
    //             }
    //         }
    //         loop {
    //             match transducer.accept(None) {
    //                 TransductionResult::End => { return result; },
    //                 TransductionResult::None => (),
    //                 TransductionResult::Some(r) => { result.push(r); }
    //             }
    //         }
    //     }
    // }
}

// pub mod iter {
//     use std::marker::PhantomData;

//     use ::{Transducer, TransductionResult};

//     pub trait TransduceIter {
//         type UnderlyingIterator;

//         fn transduce<T, F, O>(self, transducer: T) -> TransduceIterator<Self::UnderlyingIterator, T, F, O>
//             where T: Transducer<F, O>;
//     }

//     impl<I> TransduceIter for I
//         where I: Iterator {

//         type UnderlyingIterator = I;

//         fn transduce<T, F, O>(self, transducer: T) -> TransduceIterator<Self::UnderlyingIterator, T, F, O>
//             where T: Transducer<F, O> {

//             TransduceIterator {
//                 underlying: self,
//                 finished: false,
//                 transducer: transducer,
//                 from: PhantomData,
//                 out: PhantomData
//             }
//         }
//     }

//     pub struct TransduceIterator<I, T, F, O> {
//         underlying: I,
//         finished: bool,
//         transducer: T,
//         from: PhantomData<F>,
//         out: PhantomData<O>
//     }

//     impl<I, T, F, O> TransduceIterator<I, T, F, O>
//         where T: Transducer<F, O> {
//     }

//     impl<I, T, F, O> Iterator for TransduceIterator<I, T, F, O>
//         where I: Iterator<Item=F>,
//               T: Transducer<F, O> {

//         type Item = O;

//         #[inline]
//         fn next(&mut self) -> Option<Self::Item> {
//             loop {
//                 let next_val = if self.finished {
//                     None
//                 } else {
//                     let interim = self.underlying.next();
//                     if interim.is_none() {
//                         self.finished = true
//                     }
//                     interim
//                 };
//                 match self.transducer.accept(next_val) {
//                     TransductionResult::End => return None,
//                     TransductionResult::None => (),
//                     TransductionResult::Some(value) => return Some(value)
//                 }
//             }
//         }
//     }
// }

pub mod channels {
    use std::marker::PhantomData;
    use std::sync::mpsc::{Receiver, Sender, SendError, channel};

    use ::{Transducer, Reducing};

    pub struct TransducingSender<O, SR>
        where SR: Reducing<O, (), SendError<O>> {

        rf: SR,
        o_type: PhantomData<O>
    }

    pub struct SenderReducer<T>(Sender<T>);

    impl<O> Reducing<O, (), SendError<O>> for SenderReducer<O> {
        type Item = O;

        #[inline]
        fn step(&mut self, value: O) -> Result<(), SendError<O>> {
            self.0.send(value)
        }

        fn complete(self) -> () {
            ()
        }
    }

    impl<O, SR> TransducingSender<O, SR>
        where SR: Reducing<O, (), SendError<O>> {

        pub fn send(&mut self, f: O) -> Result<(), SendError<O>> {
            self.rf.step(f)
        }

        pub fn close(self) -> Result<(), SendError<O>> {
            Ok(self.rf.complete())
        }
    }

    pub fn transducing_channel<I, O, T, RO>(transducer: T) -> (TransducingSender<I, RO>,
                                                               Receiver<O>)
        where RO: Reducing<I, (), SendError<I>, Item=O>,
              T: Transducer<SenderReducer<O>, RO=RO> {
        let (tx, rx) = channel();
        let sender = TransducingSender {
            rf: transducer.new(SenderReducer(tx)),
            o_type: PhantomData
        };
        (sender, rx)
    }
}
<commit_msg>Rename RefReducer -> VecReducer<commit_after>/*
 * Copyright 2016 rs-transducers developers
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

pub mod vec {
    use ::{Transducer, Reducing};

    pub trait Ref {
        type Input;

        fn transduce_ref<'a, T, O, RO, E>(&'a self, transducer: T) -> Result<Vec<O>, E>
            where RO: Reducing<&'a Self::Input, Vec<O>, E>,
                  T: Transducer<VecReducer<O>, RO=RO>;
    }

    pub struct VecReducer<O>(Vec<O>);

    impl<'a, O> Reducing<O, Vec<O>, ()> for VecReducer<O> {
        type Item = O;

        #[inline]
        fn step(&mut self, value: O) -> Result<(), ()> {
            self.0.push(value);
            Ok(())
        }

        fn complete(self) -> Vec<O> {
            self.0
        }
    }

    impl<X> Ref for Vec<X> {
        type Input = X;

        fn transduce_ref<'a, T, O, RO, E>(&'a self, mut transducer: T) -> Result<Vec<O>, E>
            where RO: Reducing<&'a Self::Input, Vec<O>, E>,
                  T: Transducer<VecReducer<O>, RO=RO> {
            let rr = VecReducer(Vec::with_capacity(self.len()));
            let mut reducing = transducer.new(rr);
            reducing.init();
            for val in self.iter() {
                try!(reducing.step(val));
            }
            Ok(reducing.complete())
        }
    }

    // pub trait Drain {
    //     type Input;

    //     fn transduce_drain<T, O>(mut self, transducer: T) -> Vec<O>
    //         where T: Transducer<Self::Input, O>;
    // }

    // impl<X> Drain for Vec<X> {
    //     type Input = X;

    //     fn transduce_drain<T, O>(mut self, mut transducer: T) -> Vec<O>
    //         where T: Transducer<Self::Input, O> {

    //         let mut result = Vec::with_capacity(self.len());
    //         for val in self.drain(..) {
    //             match transducer.accept(Some(val)) {
    //                 TransductionResult::End => { return result; },
    //                 TransductionResult::None => (),
    //                 TransductionResult::Some(r) => { result.push(r); }
    //             }
    //         }
    //         loop {
    //             match transducer.accept(None) {
    //                 TransductionResult::End => { return result; },
    //                 TransductionResult::None => (),
    //                 TransductionResult::Some(r) => { result.push(r); }
    //             }
    //         }
    //     }
    // }
}

// pub mod iter {
//     use std::marker::PhantomData;

//     use ::{Transducer, TransductionResult};

//     pub trait TransduceIter {
//         type UnderlyingIterator;

//         fn transduce<T, F, O>(self, transducer: T) -> TransduceIterator<Self::UnderlyingIterator, T, F, O>
//             where T: Transducer<F, O>;
//     }

//     impl<I> TransduceIter for I
//         where I: Iterator {

//         type UnderlyingIterator = I;

//         fn transduce<T, F, O>(self, transducer: T) -> TransduceIterator<Self::UnderlyingIterator, T, F, O>
//             where T: Transducer<F, O> {

//             TransduceIterator {
//                 underlying: self,
//                 finished: false,
//                 transducer: transducer,
//                 from: PhantomData,
//                 out: PhantomData
//             }
//         }
//     }

//     pub struct TransduceIterator<I, T, F, O> {
//         underlying: I,
//         finished: bool,
//         transducer: T,
//         from: PhantomData<F>,
//         out: PhantomData<O>
//     }

//     impl<I, T, F, O> TransduceIterator<I, T, F, O>
//         where T: Transducer<F, O> {
//     }

//     impl<I, T, F, O> Iterator for TransduceIterator<I, T, F, O>
//         where I: Iterator<Item=F>,
//               T: Transducer<F, O> {

//         type Item = O;

//         #[inline]
//         fn next(&mut self) -> Option<Self::Item> {
//             loop {
//                 let next_val = if self.finished {
//                     None
//                 } else {
//                     let interim = self.underlying.next();
//                     if interim.is_none() {
//                         self.finished = true
//                     }
//                     interim
//                 };
//                 match self.transducer.accept(next_val) {
//                     TransductionResult::End => return None,
//                     TransductionResult::None => (),
//                     TransductionResult::Some(value) => return Some(value)
//                 }
//             }
//         }
//     }
// }

pub mod channels {
    use std::marker::PhantomData;
    use std::sync::mpsc::{Receiver, Sender, SendError, channel};

    use ::{Transducer, Reducing};

    pub struct TransducingSender<O, SR>
        where SR: Reducing<O, (), SendError<O>> {

        rf: SR,
        o_type: PhantomData<O>
    }

    pub struct SenderReducer<T>(Sender<T>);

    impl<O> Reducing<O, (), SendError<O>> for SenderReducer<O> {
        type Item = O;

        #[inline]
        fn step(&mut self, value: O) -> Result<(), SendError<O>> {
            self.0.send(value)
        }

        fn complete(self) -> () {
            ()
        }
    }

    impl<O, SR> TransducingSender<O, SR>
        where SR: Reducing<O, (), SendError<O>> {

        pub fn send(&mut self, f: O) -> Result<(), SendError<O>> {
            self.rf.step(f)
        }

        pub fn close(self) -> Result<(), SendError<O>> {
            Ok(self.rf.complete())
        }
    }

    pub fn transducing_channel<I, O, T, RO>(transducer: T) -> (TransducingSender<I, RO>,
                                                               Receiver<O>)
        where RO: Reducing<I, (), SendError<I>, Item=O>,
              T: Transducer<SenderReducer<O>, RO=RO> {
        let (tx, rx) = channel();
        let sender = TransducingSender {
            rf: transducer.new(SenderReducer(tx)),
            o_type: PhantomData
        };
        (sender, rx)
    }
}
<|endoftext|>


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

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use opengles::gl2::{GLuint, delete_textures};
use std::managed::mut_ptr_eq;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub enum Layer {
    ContainerLayerKind(@mut ContainerLayer),
    TextureLayerKind(@mut TextureLayer),
    ImageLayerKind(@mut ImageLayer),
    TiledImageLayerKind(@mut TiledImageLayer)
}

impl Layer {
    pub fn with_common<T>(&self, f: &fn(&mut CommonLayer) -> T) -> T {
        match *self {
            ContainerLayerKind(container_layer) => f(&mut container_layer.common),
            TextureLayerKind(texture_layer) => f(&mut texture_layer.common),
            ImageLayerKind(image_layer) => f(&mut image_layer.common),
            TiledImageLayerKind(tiled_image_layer) => f(&mut tiled_image_layer.common)
        }
    }
}

pub struct CommonLayer {
    parent: Option<Layer>,
    prev_sibling: Option<Layer>,
    next_sibling: Option<Layer>,

    transform: Matrix4<f32>,
}

impl CommonLayer {
    // FIXME: Workaround for cross-crate bug regarding mutability of class fields
    pub fn set_transform(&mut self, new_transform: Matrix4<f32>) {
        self.transform = new_transform;
    }
}

pub fn CommonLayer() -> CommonLayer {
    CommonLayer {
        parent: None,
        prev_sibling: None,
        next_sibling: None,
        transform: identity(),
    }
}

pub struct ContainerLayer {
    common: CommonLayer,
    first_child: Option<Layer>,
    last_child: Option<Layer>,
    scissor: Option<Rect<f32>>,
}

pub fn ContainerLayer() -> ContainerLayer {
    ContainerLayer {
        common: CommonLayer(),
        first_child: None,
        last_child: None,
        scissor: None,
    }
}

struct ChildIterator {
    priv current: Option<Layer>,
}

impl Iterator<Layer> for ChildIterator {
    fn next(&mut self) -> Option<Layer> {
        match self.current {
            None => None,
            Some(child) => {
                self.current = child.with_common(|x| x.next_sibling);
                Some(child)
            }
        }
    }
}

impl ContainerLayer {
    pub fn children(&self) -> ChildIterator {
        ChildIterator { current: self.first_child }
    }

    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child(@mut self, new_child: Layer) {
        do new_child.with_common |new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.first_child {
                None => {}
                Some(first_child) => {
                    do first_child.with_common |first_child_common| {
                        assert!(first_child_common.prev_sibling.is_none());
                        first_child_common.prev_sibling = Some(new_child);
                        new_child_common.next_sibling = Some(first_child);
                    }
                }
            }

            self.first_child = Some(new_child);

            match self.last_child {
                None => self.last_child = Some(new_child),
                Some(_) => {}
            }
        }
    }

    pub fn remove_child(@mut self, child: Layer) {
        do child.with_common |child_common| {
            assert!(child_common.parent.is_some());
            match child_common.parent.unwrap() {
                ContainerLayerKind(ref container) => {
                    assert!(mut_ptr_eq(*container, self));
                },
                _ => fail!(~"Invalid parent of child in layer tree"),
            }

            match child_common.next_sibling {
                None => { // this is the last child
                    self.last_child = child_common.prev_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.prev_sibling = child_common.prev_sibling;
                    }
                }
            }
            match child_common.prev_sibling {
                None => { // this is the first child
                    self.first_child = child_common.next_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.next_sibling = child_common.next_sibling;
                    }
                }
            }
        }
    }
}

pub trait TextureManager {
    fn get_texture(&self) -> GLuint;
}

pub struct TextureLayer {
    common: CommonLayer,
    manager: @TextureManager,
    size: Size2D<uint>
}

impl TextureLayer {
    pub fn new(manager: @TextureManager, size: Size2D<uint>) -> TextureLayer {
        TextureLayer {
            common: CommonLayer(),
            manager: manager,
            size: size,
        }
    }
}

pub type WithDataFn<'self> = &'self fn(&'self [u8]);

pub trait ImageData {
    fn size(&self) -> Size2D<uint>;

    // NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH.
    fn stride(&self) -> uint;

    fn format(&self) -> Format;
    fn with_data(&self, WithDataFn);
}

pub struct Image {
    data: @ImageData,
    texture: Option<GLuint>,
}

#[unsafe_destructor]
impl Drop for Image {
    fn drop(&self) {
        match self.texture.clone() {
            None => {
                // Nothing to do.
            }
            Some(texture) => {
                delete_textures(&[texture]);
            }
        }
    }
}

impl Image {
    pub fn new(data: @ImageData) -> Image {
        Image { data: data, texture: None }
    }
}

/// Basic image data is a simple image data store that just owns the pixel data in memory.
pub struct BasicImageData {
    size: Size2D<uint>,
    stride: uint,
    format: Format,
    data: ~[u8]
}

impl BasicImageData {
    pub fn new(size: Size2D<uint>, stride: uint, format: Format, data: ~[u8]) ->
            BasicImageData {
        BasicImageData {
            size: size,
            stride: stride,
            format: format,
            data: data
        }
    }
}

impl ImageData for BasicImageData {
    fn size(&self) -> Size2D<uint> { self.size }
    fn stride(&self) -> uint { self.stride }
    fn format(&self) -> Format { self.format }
    fn with_data(&self, f: WithDataFn) { f(self.data) }
}

pub struct ImageLayer {
    common: CommonLayer,
    image: @mut Image,
}

impl ImageLayer {
    // FIXME: Workaround for cross-crate bug
    pub fn set_image(&mut self, new_image: @mut Image) {
        self.image = new_image;
    }
}

pub fn ImageLayer(image: @mut Image) -> ImageLayer {
    ImageLayer {
        common : CommonLayer(),
        image : image,
    }
}

pub struct TiledImageLayer {
    common: CommonLayer,
    tiles: @mut ~[@mut Image],
    tiles_across: uint,
}

pub fn TiledImageLayer(in_tiles: &[@mut Image], tiles_across: uint) -> TiledImageLayer {
    let tiles = @mut ~[];
    for tile in in_tiles.iter() {
        tiles.push(*tile);
    }

    TiledImageLayer {
        common: CommonLayer(),
        tiles: tiles,
        tiles_across: tiles_across
    }
}

<commit_msg>Specify which end of the list when adding child layers<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use geom::matrix::{Matrix4, identity};
use geom::size::Size2D;
use geom::rect::Rect;
use opengles::gl2::{GLuint, delete_textures};
use std::managed::mut_ptr_eq;

pub enum Format {
    ARGB32Format,
    RGB24Format
}

pub enum Layer {
    ContainerLayerKind(@mut ContainerLayer),
    TextureLayerKind(@mut TextureLayer),
    ImageLayerKind(@mut ImageLayer),
    TiledImageLayerKind(@mut TiledImageLayer)
}

impl Layer {
    pub fn with_common<T>(&self, f: &fn(&mut CommonLayer) -> T) -> T {
        match *self {
            ContainerLayerKind(container_layer) => f(&mut container_layer.common),
            TextureLayerKind(texture_layer) => f(&mut texture_layer.common),
            ImageLayerKind(image_layer) => f(&mut image_layer.common),
            TiledImageLayerKind(tiled_image_layer) => f(&mut tiled_image_layer.common)
        }
    }
}

pub struct CommonLayer {
    parent: Option<Layer>,
    prev_sibling: Option<Layer>,
    next_sibling: Option<Layer>,

    transform: Matrix4<f32>,
}

impl CommonLayer {
    // FIXME: Workaround for cross-crate bug regarding mutability of class fields
    pub fn set_transform(&mut self, new_transform: Matrix4<f32>) {
        self.transform = new_transform;
    }
}

pub fn CommonLayer() -> CommonLayer {
    CommonLayer {
        parent: None,
        prev_sibling: None,
        next_sibling: None,
        transform: identity(),
    }
}

pub struct ContainerLayer {
    common: CommonLayer,
    first_child: Option<Layer>,
    last_child: Option<Layer>,
    scissor: Option<Rect<f32>>,
}

pub fn ContainerLayer() -> ContainerLayer {
    ContainerLayer {
        common: CommonLayer(),
        first_child: None,
        last_child: None,
        scissor: None,
    }
}

struct ChildIterator {
    priv current: Option<Layer>,
}

impl Iterator<Layer> for ChildIterator {
    fn next(&mut self) -> Option<Layer> {
        match self.current {
            None => None,
            Some(child) => {
                self.current = child.with_common(|x| x.next_sibling);
                Some(child)
            }
        }
    }
}

impl ContainerLayer {
    pub fn children(&self) -> ChildIterator {
        ChildIterator { current: self.first_child }
    }

    /// Adds a child to the beginning of the list.
    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child_start(@mut self, new_child: Layer) {
        do new_child.with_common |new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.first_child {
                None => {}
                Some(first_child) => {
                    do first_child.with_common |first_child_common| {
                        assert!(first_child_common.prev_sibling.is_none());
                        first_child_common.prev_sibling = Some(new_child);
                        new_child_common.next_sibling = Some(first_child);
                    }
                }
            }

            self.first_child = Some(new_child);

            match self.last_child {
                None => self.last_child = Some(new_child),
                Some(_) => {}
            }
        }
    }

    /// Adds a child to the end of the list.
    /// Only works when the child is disconnected from the layer tree.
    pub fn add_child_end(@mut self, new_child: Layer) {
        do new_child.with_common |new_child_common| {
            assert!(new_child_common.parent.is_none());
            assert!(new_child_common.prev_sibling.is_none());
            assert!(new_child_common.next_sibling.is_none());

            new_child_common.parent = Some(ContainerLayerKind(self));

            match self.last_child {
                None => {}
                Some(last_child) => {
                    do last_child.with_common |last_child_common| {
                        assert!(last_child_common.next_sibling.is_none());
                        last_child_common.next_sibling = Some(new_child);
                        new_child_common.prev_sibling = Some(last_child);
                    }
                }
            }

            self.last_child = Some(new_child);

            match self.first_child {
                None => self.first_child = Some(new_child),
                Some(_) => {}
            }
        }
    }

    pub fn remove_child(@mut self, child: Layer) {
        do child.with_common |child_common| {
            assert!(child_common.parent.is_some());
            match child_common.parent.unwrap() {
                ContainerLayerKind(ref container) => {
                    assert!(mut_ptr_eq(*container, self));
                },
                _ => fail!(~"Invalid parent of child in layer tree"),
            }

            match child_common.next_sibling {
                None => { // this is the last child
                    self.last_child = child_common.prev_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.prev_sibling = child_common.prev_sibling;
                    }
                }
            }
            match child_common.prev_sibling {
                None => { // this is the first child
                    self.first_child = child_common.next_sibling;
                },
                Some(ref sibling) => {
                    do sibling.with_common |sibling_common| {
                        sibling_common.next_sibling = child_common.next_sibling;
                    }
                }
            }
        }
    }
}

pub trait TextureManager {
    fn get_texture(&self) -> GLuint;
}

pub struct TextureLayer {
    common: CommonLayer,
    manager: @TextureManager,
    size: Size2D<uint>
}

impl TextureLayer {
    pub fn new(manager: @TextureManager, size: Size2D<uint>) -> TextureLayer {
        TextureLayer {
            common: CommonLayer(),
            manager: manager,
            size: size,
        }
    }
}

pub type WithDataFn<'self> = &'self fn(&'self [u8]);

pub trait ImageData {
    fn size(&self) -> Size2D<uint>;

    // NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH.
    fn stride(&self) -> uint;

    fn format(&self) -> Format;
    fn with_data(&self, WithDataFn);
}

pub struct Image {
    data: @ImageData,
    texture: Option<GLuint>,
}

#[unsafe_destructor]
impl Drop for Image {
    fn drop(&self) {
        match self.texture.clone() {
            None => {
                // Nothing to do.
            }
            Some(texture) => {
                delete_textures(&[texture]);
            }
        }
    }
}

impl Image {
    pub fn new(data: @ImageData) -> Image {
        Image { data: data, texture: None }
    }
}

/// Basic image data is a simple image data store that just owns the pixel data in memory.
pub struct BasicImageData {
    size: Size2D<uint>,
    stride: uint,
    format: Format,
    data: ~[u8]
}

impl BasicImageData {
    pub fn new(size: Size2D<uint>, stride: uint, format: Format, data: ~[u8]) ->
            BasicImageData {
        BasicImageData {
            size: size,
            stride: stride,
            format: format,
            data: data
        }
    }
}

impl ImageData for BasicImageData {
    fn size(&self) -> Size2D<uint> { self.size }
    fn stride(&self) -> uint { self.stride }
    fn format(&self) -> Format { self.format }
    fn with_data(&self, f: WithDataFn) { f(self.data) }
}

pub struct ImageLayer {
    common: CommonLayer,
    image: @mut Image,
}

impl ImageLayer {
    // FIXME: Workaround for cross-crate bug
    pub fn set_image(&mut self, new_image: @mut Image) {
        self.image = new_image;
    }
}

pub fn ImageLayer(image: @mut Image) -> ImageLayer {
    ImageLayer {
        common : CommonLayer(),
        image : image,
    }
}

pub struct TiledImageLayer {
    common: CommonLayer,
    tiles: @mut ~[@mut Image],
    tiles_across: uint,
}

pub fn TiledImageLayer(in_tiles: &[@mut Image], tiles_across: uint) -> TiledImageLayer {
    let tiles = @mut ~[];
    for tile in in_tiles.iter() {
        tiles.push(*tile);
    }

    TiledImageLayer {
        common: CommonLayer(),
        tiles: tiles,
        tiles_across: tiles_across
    }
}

<|endoftext|>


<commit_before>//! Set up resource content for game.

use crate::brush::{Brush, Builder, Geom};
use std::str::FromStr;
use std::sync::Arc;
use vec_map::VecMap;
use vitral::color::*;
use vitral::{self, PngBytes, Rgba};

/// Load all game graphics in memory from image data.
///
/// Must be called before the main game loop starts and tries to render tiles.
pub fn load_graphics() {
    vitral::add_sheet(
        "assets/blobs.png",
        PngBytes(include_bytes!("../assets/blobs.png")),
    );
    vitral::add_sheet(
        "assets/floors.png",
        PngBytes(include_bytes!("../assets/floors.png")),
    );
    vitral::add_sheet(
        "assets/fx.png",
        PngBytes(include_bytes!("../assets/fx.png")),
    );
    vitral::add_sheet(
        "assets/gui.png",
        PngBytes(include_bytes!("../assets/gui.png")),
    );
    vitral::add_sheet(
        "assets/items.png",
        PngBytes(include_bytes!("../assets/items.png")),
    );
    vitral::add_sheet(
        "assets/logo.png",
        PngBytes(include_bytes!("../assets/logo.png")),
    );
    vitral::add_sheet(
        "assets/mobs.png",
        PngBytes(include_bytes!("../assets/mobs.png")),
    );
    vitral::add_sheet(
        "assets/portals.png",
        PngBytes(include_bytes!("../assets/portals.png")),
    );
    vitral::add_sheet(
        "assets/props.png",
        PngBytes(include_bytes!("../assets/props.png")),
    );
    vitral::add_sheet(
        "assets/walls.png",
        PngBytes(include_bytes!("../assets/walls.png")),
    );
}

#[rustfmt::skip]
pub fn terrain_brushes() -> VecMap<Arc<Brush>> {
    use world::Terrain::*;
    let mut ret = VecMap::new();

    ret.insert(Empty as usize, Builder::new("assets/floors.png").tile(0, 0).finish());
    ret.insert(Upstairs as usize, Builder::new("assets/portals.png")
        .color(LIGHTCYAN)
        .tile(0, 0).merge()
        .tile(32, 0).merge()
        .tile(64, 0).merge()
        .tile(96, 0).merge()
        .tile(128, 0).merge()
        .tile(160, 0).merge()
        .tile(192, 0).merge()
        .tile(224, 0).merge()
        .tile(256, 0).merge()
        .tile(288, 0).merge()
        .tile(320, 0).merge()
        .tile(352, 0).merge()
        .tile(384, 0).finish());
    ret.insert(Downstairs as usize, Builder::new("assets/portals.png")
        .color(LIGHTCYAN)
        .tile(0, 0).merge()
        .tile(32, 0).merge()
        .tile(64, 0).merge()
        .tile(96, 0).merge()
        .tile(128, 0).merge()
        .tile(160, 0).merge()
        .tile(192, 0).merge()
        .tile(224, 0).merge()
        .tile(256, 0).merge()
        .tile(288, 0).merge()
        .tile(320, 0).merge()
        .tile(352, 0).merge()
        .tile(384, 0).finish());
    ret.insert(Ground as usize, Builder::new("assets/floors.png").color(SLATEGRAY).tile(32, 0).finish());
    ret.insert(Grass as usize, Builder::new("assets/floors.png").color(DARKGREEN).tile(32, 0).finish());
    ret.insert(Snow as usize, Builder::new("assets/floors.png").color(WHITE).tile(32, 0).finish());
    ret.insert(Sand as usize, Builder::new("assets/floors.png").color(YELLOW).tile(32, 0).finish());
    ret.insert(Water as usize, Builder::new("assets/floors.png").colors(MIDNIGHTBLUE, ROYALBLUE).tile(96, 0).finish());
    ret.insert(Shallows as usize, Builder::new("assets/floors.png").colors(STEELBLUE, ROYALBLUE).tile(96, 0).finish());
    ret.insert(Magma as usize, Builder::new("assets/floors.png").colors(YELLOW, DARKRED).tile(96, 0).finish());
    ret.insert(Tree as usize, Builder::new("assets/props.png")
        .color(SADDLEBROWN).tile(160, 32)
        .color(GREEN).tile(192, 32).finish());
    ret.insert(Wall as usize, Builder::new("assets/walls.png").color(LIGHTSLATEGRAY).wall(0, 0, 32, 0).finish());
    ret.insert(Rock as usize, Builder::new("assets/blobs.png").color(DARKGOLDENROD).blob(0, 0, 0, 32, 0, 160).finish());
    ret.insert(Door as usize, Builder::new("assets/walls.png")
        .color(SADDLEBROWN).wall(128, 0, 160, 0)
        .color(LIGHTSLATEGRAY).wall(0, 0, 96, 0).finish());
    ret.insert(OpenDoor as usize, Builder::new("assets/walls.png").color(LIGHTSLATEGRAY).wall(0, 0, 96, 0).finish());
    ret.insert(Window as usize, Builder::new("assets/walls.png").color(LIGHTSLATEGRAY).wall(0, 0, 64, 0).finish());
    ret.insert(Pillar as usize, Builder::new("assets/props.png").color(GAINSBORO).tile(0, 32).finish());
    ret.insert(Grass2 as usize, Builder::new("assets/floors.png").color(DARKGREEN).tile(64, 0).finish());

    ret
}

#[rustfmt::skip]
#[allow(clippy::identity_op)]
pub fn entity_brushes() -> VecMap<Arc<Brush>> {
    use world::Icon::*;
    let mut ret = VecMap::new();

    ret.insert(Player as usize, Builder::new("assets/mobs.png").color(AZURE).mob(0, 0).finish());
    ret.insert(Snake as usize, Builder::new("assets/mobs.png").color(GREEN).mob(1*32, 0).finish());
    ret.insert(Dreg as usize, Builder::new("assets/mobs.png").color(OLIVE).mob(2*32, 0).finish());
    ret.insert(Ogre as usize, Builder::new("assets/mobs.png").color(DARKCYAN).mob(3*32, 0).finish());
    ret.insert(Wraith as usize, Builder::new("assets/mobs.png").color(GRAY).mob(4*32, 0).finish());
    ret.insert(Octopus as usize, Builder::new("assets/mobs.png").color(WHEAT).mob(5*32, 0).finish());
    ret.insert(Bug as usize, Builder::new("assets/mobs.png").color(0xFF_00_FF_FF).mob(6*32, 0).finish());
    ret.insert(Ooze as usize, Builder::new("assets/mobs.png").color(LIGHTSKYBLUE).mob(7*32, 0).finish());
    ret.insert(Efreet as usize, Builder::new("assets/mobs.png").color(ORANGE).mob(0, 1*32).finish());

    // The serpent has a special sprite structure where it's split to the head and mound parts,
    // and the mound part doesn't move during the idle animation.
    ret.insert(Serpent as usize, Builder::new("assets/mobs.png").color(CORAL)
        .splat(Some(Geom::new(16, 14, 1*32, 32, 32, 32))).tile(2*32, 32).merge()
        .tile(1*32, 32).tile(2*32, 32).merge()
        .finish());

    ret.insert(Sword as usize, Builder::new("assets/items.png").color(LIGHTGRAY).item(0*16, 0*16).finish());
    ret.insert(Helmet as usize, Builder::new("assets/items.png").color(LIGHTGRAY).item(1*16, 0*16).finish());
    ret.insert(Armor as usize, Builder::new("assets/items.png").color(LIGHTGRAY).item(6*16, 0*16).finish());

    ret.insert(Scroll1 as usize, Builder::new("assets/items.png").color(LIGHTYELLOW).item(0*16, 1*16).finish());
    ret.insert(Wand1 as usize, Builder::new("assets/items.png").color(RED).item(4*16, 0*16).finish());
    ret.insert(Wand2 as usize, Builder::new("assets/items.png").color(CYAN).item(4*16, 0*16).finish());
    ret
}

#[rustfmt::skip]
#[allow(clippy::identity_op)]
pub fn misc_brushes() -> VecMap<Arc<Brush>> {
    use crate::Icon::*;
    let mut ret = VecMap::new();

    ret.insert(SolidBlob as usize, Builder::new("assets/blobs.png").colors(BLACK, BLACK).blob(0, 64, 0, 96, 0, 128).finish());
    ret.insert(CursorTop as usize, Builder::new("assets/props.png").color(RED).tile(32, 0).finish());
    ret.insert(CursorBottom as usize, Builder::new("assets/props.png").color(RED).tile(0, 0).finish());
    ret.insert(Portal as usize, Builder::new("assets/props.png").color(Rgba::from_str("#fa08").unwrap()).tile(0, 0).finish());
    ret.insert(HealthPip as usize, Builder::new("assets/gui.png").color(LIMEGREEN).rect(0, 8, 4, 4).finish());
    ret.insert(DarkHealthPip as usize, Builder::new("assets/gui.png").color(DARKSLATEGRAY).rect(0, 8, 4, 4).finish());

    // Some animations are tweaked to repeat frames, this controls the relative speed in parts of
    // the animation. Usually the end dispersion needs to look faster than the initial expansion.
    ret.insert(Gib as usize, Builder::new("assets/fx.png")
        .color(RED)
        .tile(0*32, 0).merge()
        .tile(1*32, 0).merge()
        .tile(2*32, 0).merge()
        .tile(3*32, 0).merge()
        .tile(4*32, 0).merge()
        .finish());

    ret.insert(Smoke as usize, Builder::new("assets/fx.png")
        .color(LIGHTGRAY)
        .tile(5*32, 0).merge()
        .tile(5*32, 0).merge()
        .tile(6*32, 0).merge()
        .tile(6*32, 0).merge()
        .tile(7*32, 0).merge()
        .finish());

    ret.insert(Explosion as usize, Builder::new("assets/fx.png")
        .color(YELLOW)
        .tile(0*32, 1*32).merge()
        .tile(0*32, 1*32).merge()
        .tile(1*32, 1*32).merge()
        .tile(1*32, 1*32).merge()
        .tile(2*32, 1*32).merge()
        .tile(2*32, 1*32).merge()
        .tile(3*32, 1*32).merge()
        .tile(4*32, 1*32).merge()
        .finish());

    ret.insert(Firespell as usize, Builder::new("assets/fx.png")
        .color(YELLOW)
        .tile(5*32, 1*32).merge()
        .tile(6*32, 1*32).merge()
        .finish());

    ret
}
<commit_msg>Fix wand icons<commit_after>//! Set up resource content for game.

use crate::brush::{Brush, Builder, Geom};
use std::str::FromStr;
use std::sync::Arc;
use vec_map::VecMap;
use vitral::color::*;
use vitral::{self, PngBytes, Rgba};

/// Load all game graphics in memory from image data.
///
/// Must be called before the main game loop starts and tries to render tiles.
pub fn load_graphics() {
    vitral::add_sheet(
        "assets/blobs.png",
        PngBytes(include_bytes!("../assets/blobs.png")),
    );
    vitral::add_sheet(
        "assets/floors.png",
        PngBytes(include_bytes!("../assets/floors.png")),
    );
    vitral::add_sheet(
        "assets/fx.png",
        PngBytes(include_bytes!("../assets/fx.png")),
    );
    vitral::add_sheet(
        "assets/gui.png",
        PngBytes(include_bytes!("../assets/gui.png")),
    );
    vitral::add_sheet(
        "assets/items.png",
        PngBytes(include_bytes!("../assets/items.png")),
    );
    vitral::add_sheet(
        "assets/logo.png",
        PngBytes(include_bytes!("../assets/logo.png")),
    );
    vitral::add_sheet(
        "assets/mobs.png",
        PngBytes(include_bytes!("../assets/mobs.png")),
    );
    vitral::add_sheet(
        "assets/portals.png",
        PngBytes(include_bytes!("../assets/portals.png")),
    );
    vitral::add_sheet(
        "assets/props.png",
        PngBytes(include_bytes!("../assets/props.png")),
    );
    vitral::add_sheet(
        "assets/walls.png",
        PngBytes(include_bytes!("../assets/walls.png")),
    );
}

#[rustfmt::skip]
pub fn terrain_brushes() -> VecMap<Arc<Brush>> {
    use world::Terrain::*;
    let mut ret = VecMap::new();

    ret.insert(Empty as usize, Builder::new("assets/floors.png").tile(0, 0).finish());
    ret.insert(Upstairs as usize, Builder::new("assets/portals.png")
        .color(LIGHTCYAN)
        .tile(0, 0).merge()
        .tile(32, 0).merge()
        .tile(64, 0).merge()
        .tile(96, 0).merge()
        .tile(128, 0).merge()
        .tile(160, 0).merge()
        .tile(192, 0).merge()
        .tile(224, 0).merge()
        .tile(256, 0).merge()
        .tile(288, 0).merge()
        .tile(320, 0).merge()
        .tile(352, 0).merge()
        .tile(384, 0).finish());
    ret.insert(Downstairs as usize, Builder::new("assets/portals.png")
        .color(LIGHTCYAN)
        .tile(0, 0).merge()
        .tile(32, 0).merge()
        .tile(64, 0).merge()
        .tile(96, 0).merge()
        .tile(128, 0).merge()
        .tile(160, 0).merge()
        .tile(192, 0).merge()
        .tile(224, 0).merge()
        .tile(256, 0).merge()
        .tile(288, 0).merge()
        .tile(320, 0).merge()
        .tile(352, 0).merge()
        .tile(384, 0).finish());
    ret.insert(Ground as usize, Builder::new("assets/floors.png").color(SLATEGRAY).tile(32, 0).finish());
    ret.insert(Grass as usize, Builder::new("assets/floors.png").color(DARKGREEN).tile(32, 0).finish());
    ret.insert(Snow as usize, Builder::new("assets/floors.png").color(WHITE).tile(32, 0).finish());
    ret.insert(Sand as usize, Builder::new("assets/floors.png").color(YELLOW).tile(32, 0).finish());
    ret.insert(Water as usize, Builder::new("assets/floors.png").colors(MIDNIGHTBLUE, ROYALBLUE).tile(96, 0).finish());
    ret.insert(Shallows as usize, Builder::new("assets/floors.png").colors(STEELBLUE, ROYALBLUE).tile(96, 0).finish());
    ret.insert(Magma as usize, Builder::new("assets/floors.png").colors(YELLOW, DARKRED).tile(96, 0).finish());
    ret.insert(Tree as usize, Builder::new("assets/props.png")
        .color(SADDLEBROWN).tile(160, 32)
        .color(GREEN).tile(192, 32).finish());
    ret.insert(Wall as usize, Builder::new("assets/walls.png").color(LIGHTSLATEGRAY).wall(0, 0, 32, 0).finish());
    ret.insert(Rock as usize, Builder::new("assets/blobs.png").color(DARKGOLDENROD).blob(0, 0, 0, 32, 0, 160).finish());
    ret.insert(Door as usize, Builder::new("assets/walls.png")
        .color(SADDLEBROWN).wall(128, 0, 160, 0)
        .color(LIGHTSLATEGRAY).wall(0, 0, 96, 0).finish());
    ret.insert(OpenDoor as usize, Builder::new("assets/walls.png").color(LIGHTSLATEGRAY).wall(0, 0, 96, 0).finish());
    ret.insert(Window as usize, Builder::new("assets/walls.png").color(LIGHTSLATEGRAY).wall(0, 0, 64, 0).finish());
    ret.insert(Pillar as usize, Builder::new("assets/props.png").color(GAINSBORO).tile(0, 32).finish());
    ret.insert(Grass2 as usize, Builder::new("assets/floors.png").color(DARKGREEN).tile(64, 0).finish());

    ret
}

#[rustfmt::skip]
#[allow(clippy::identity_op)]
pub fn entity_brushes() -> VecMap<Arc<Brush>> {
    use world::Icon::*;
    let mut ret = VecMap::new();

    ret.insert(Player as usize, Builder::new("assets/mobs.png").color(AZURE).mob(0, 0).finish());
    ret.insert(Snake as usize, Builder::new("assets/mobs.png").color(GREEN).mob(1*32, 0).finish());
    ret.insert(Dreg as usize, Builder::new("assets/mobs.png").color(OLIVE).mob(2*32, 0).finish());
    ret.insert(Ogre as usize, Builder::new("assets/mobs.png").color(DARKCYAN).mob(3*32, 0).finish());
    ret.insert(Wraith as usize, Builder::new("assets/mobs.png").color(GRAY).mob(4*32, 0).finish());
    ret.insert(Octopus as usize, Builder::new("assets/mobs.png").color(WHEAT).mob(5*32, 0).finish());
    ret.insert(Bug as usize, Builder::new("assets/mobs.png").color(0xFF_00_FF_FF).mob(6*32, 0).finish());
    ret.insert(Ooze as usize, Builder::new("assets/mobs.png").color(LIGHTSKYBLUE).mob(7*32, 0).finish());
    ret.insert(Efreet as usize, Builder::new("assets/mobs.png").color(ORANGE).mob(0, 1*32).finish());

    // The serpent has a special sprite structure where it's split to the head and mound parts,
    // and the mound part doesn't move during the idle animation.
    ret.insert(Serpent as usize, Builder::new("assets/mobs.png").color(CORAL)
        .splat(Some(Geom::new(16, 14, 1*32, 32, 32, 32))).tile(2*32, 32).merge()
        .tile(1*32, 32).tile(2*32, 32).merge()
        .finish());

    ret.insert(Sword as usize, Builder::new("assets/items.png").color(LIGHTGRAY).item(0*16, 0*16).finish());
    ret.insert(Helmet as usize, Builder::new("assets/items.png").color(LIGHTGRAY).item(1*16, 0*16).finish());
    ret.insert(Armor as usize, Builder::new("assets/items.png").color(LIGHTGRAY).item(6*16, 0*16).finish());

    ret.insert(Scroll1 as usize, Builder::new("assets/items.png").color(LIGHTYELLOW).item(0*16, 1*16).finish());
    ret.insert(Wand1 as usize, Builder::new("assets/items.png").color(RED).item(3*16, 0*16).finish());
    ret.insert(Wand2 as usize, Builder::new("assets/items.png").color(CYAN).item(3*16, 0*16).finish());
    ret
}

#[rustfmt::skip]
#[allow(clippy::identity_op)]
pub fn misc_brushes() -> VecMap<Arc<Brush>> {
    use crate::Icon::*;
    let mut ret = VecMap::new();

    ret.insert(SolidBlob as usize, Builder::new("assets/blobs.png").colors(BLACK, BLACK).blob(0, 64, 0, 96, 0, 128).finish());
    ret.insert(CursorTop as usize, Builder::new("assets/props.png").color(RED).tile(32, 0).finish());
    ret.insert(CursorBottom as usize, Builder::new("assets/props.png").color(RED).tile(0, 0).finish());
    ret.insert(Portal as usize, Builder::new("assets/props.png").color(Rgba::from_str("#fa08").unwrap()).tile(0, 0).finish());
    ret.insert(HealthPip as usize, Builder::new("assets/gui.png").color(LIMEGREEN).rect(0, 8, 4, 4).finish());
    ret.insert(DarkHealthPip as usize, Builder::new("assets/gui.png").color(DARKSLATEGRAY).rect(0, 8, 4, 4).finish());

    // Some animations are tweaked to repeat frames, this controls the relative speed in parts of
    // the animation. Usually the end dispersion needs to look faster than the initial expansion.
    ret.insert(Gib as usize, Builder::new("assets/fx.png")
        .color(RED)
        .tile(0*32, 0).merge()
        .tile(1*32, 0).merge()
        .tile(2*32, 0).merge()
        .tile(3*32, 0).merge()
        .tile(4*32, 0).merge()
        .finish());

    ret.insert(Smoke as usize, Builder::new("assets/fx.png")
        .color(LIGHTGRAY)
        .tile(5*32, 0).merge()
        .tile(5*32, 0).merge()
        .tile(6*32, 0).merge()
        .tile(6*32, 0).merge()
        .tile(7*32, 0).merge()
        .finish());

    ret.insert(Explosion as usize, Builder::new("assets/fx.png")
        .color(YELLOW)
        .tile(0*32, 1*32).merge()
        .tile(0*32, 1*32).merge()
        .tile(1*32, 1*32).merge()
        .tile(1*32, 1*32).merge()
        .tile(2*32, 1*32).merge()
        .tile(2*32, 1*32).merge()
        .tile(3*32, 1*32).merge()
        .tile(4*32, 1*32).merge()
        .finish());

    ret.insert(Firespell as usize, Builder::new("assets/fx.png")
        .color(YELLOW)
        .tile(5*32, 1*32).merge()
        .tile(6*32, 1*32).merge()
        .finish());

    ret
}
<|endoftext|>


<commit_before><commit_msg>Svg.get_size - Inline get_unnormalized_size into here, so we can extract this function<commit_after><|endoftext|>


<commit_before>/*
  Copyright (c) 2015, Al Poole <netstar@gmail.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

//   This is a HTTPS CONNECT proxy!

use std::string::{String};
use std::net::{SocketAddrV4,Ipv4Addr,TcpListener,TcpStream};
use std::io::{Write, Read};

const REQUEST_LEN: usize = 65535;

fn substr(buf: [u8;REQUEST_LEN], needle: &str, byte: u8) -> String
{
	let mut i = 0;
	let mut x = 0;
	let mut request = String::new();

	let srch = needle.as_bytes();

	if srch.len() == 0 {
		return request;
	}

	while buf[i] as char != '\0'  {
		if buf[i] as char == srch[0] as char {
			while x < srch.len() && buf[i] as char  == srch[x] as char {
				i = i + 1;
				x = x + 1;
			}
			break;
		} else {
			i = i + 1;
		}
	}

	if x == srch.len() {
		let mut end = i;
		while buf[end] as char != byte as char && buf[end] as char != '\n'
		{
			end = end + 1;

		}

		for y in i..end {
			request.push(buf[y] as char);
		}
	}

	return request;
}

const CHUNK: usize = 4096; // PAGESIZEish

fn talk_to_me(mut instream: &TcpStream, mut outstream: &TcpStream, mut headers: &Header) -> bool
{

	let mut buf = [0u8; CHUNK];

	println!("top");
	let bytes = instream.read(&mut buf).unwrap();
	if bytes <= 0 {
		return false;
	}

	println!("recv {}", bytes);

	for i in 0..bytes {
		print!("{}", buf[i] as char);
	}

	let mut chunk = 0;

	while chunk < bytes {
		let sent = outstream.write(&mut buf[0..bytes]).unwrap();
		if sent <= 0 {
			return false;
		}
		println!("sent {}", sent);
		chunk = chunk + sent;
	}
	true
}

struct Header {
	pub hostname: String,
	pub connection: String,
	pub proxy: String,
	pub agent: String,
}

impl Header {

pub fn new() -> Header
{
	let hostname	 = String::new();
	let connection   = String::new();
	let proxy	 = String::new();
	let agent	 = String::new();

	let h = Header
	{
		hostname: hostname,
		connection: connection,
		proxy: proxy,
		agent: agent
	};

	return h;
}

}

fn http_connect_request(instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}", headers.hostname);

	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();
	let mut disconnected = false;

	let request = format!("HTTP/1.1 200 Connection established\r\nUser-Agent: {}\r\nProxy-Connection: {}\r\nConnection: {}\r\nHost: {}\r\n\r\n",
			headers.agent, headers.proxy, headers.connection, headers.hostname);
	println!("sending: \n\n{}", request);
	let mut s = &instream;
	s.write(request.as_bytes()).unwrap(); // tell client the connection is made

	while ! disconnected {
		disconnected = talk_to_me(&instream, &outstream, &headers);
	}

	let response = format!("HTTP/1.1 200 OK\r\n\r\n");
	outstream.write(response.as_bytes()).unwrap();

}

fn check_headers(buffer: [u8;REQUEST_LEN], headers: &mut Header) -> bool
{
	let mut i = 0;

	while buffer[i] != '\0' as u8
	{
		print!("{}", buffer[i] as char);
		i+=1;
	}
	print!("\n");

	if headers.hostname.is_empty()
	{
		headers.hostname = substr(buffer, "Host: ", '\r' as u8);
	}

	if headers.connection.is_empty()
	{
		headers.connection = substr(buffer, "Connection: ", '\r' as u8);
	}

	if headers.proxy.is_empty()
	{
		headers.proxy = substr(buffer, "Proxy-Connection: ", '\r' as u8);
	}

	if headers.agent.is_empty()
	{
		headers.agent = substr(buffer, "User-Agent: ", '\r' as u8);
	}

	if ! headers.hostname.is_empty() && ! headers.connection.is_empty()
		&& ! headers.proxy.is_empty() && ! headers.agent.is_empty()
	{

		return true;
	}

	return false;
}

fn request_headers(mut instream: &TcpStream, headers: &mut Header)
{
	 loop
	{
		let mut buffer = [0u8; REQUEST_LEN];
		let mut byte = [0u8; 1];
		let mut len = 0;

		while byte[0] as char != '\n'
		{
			let bytes = instream.read(&mut byte).unwrap();
			buffer[len] = byte[0];
			len += bytes;
		}

		buffer[len] = '\0' as u8;

		if check_headers(buffer, headers) && len == 2
		{
			let mut i = 0;

			while i < REQUEST_LEN
			{
				buffer[i] = 0;
				i += 1;
			}
			return;
		}
	}

}

fn request_method(mut instream: &TcpStream) -> String
{
	let mut byte = [0u8;1];

	let mut method: String = String::new();

	// bit better for now it'll do!
	while byte[0] as char != ' '
	{
		instream.read(&mut byte).unwrap();
		if byte[0] as char != ' '
		{
			method.push(byte[0] as char);
		}
	}

	match method.as_ref()
	{
		"CONNECT" =>
		{
			return method;
		}

		"GET" | "POST" | "OPTIONS" | "HEAD" =>
		{
			return "".to_string();
			// all good do not return!!!
		}

		_ =>
		{
			return "".to_string();
		}
	}
}

fn proxy(stream: TcpStream) {
	let method = request_method(&stream);

	match method.as_ref()
	{
		"CONNECT" =>
		{
			let mut headers = Header::new();
			request_headers(&stream, &mut headers);

			http_connect_request(stream, headers);
		}

		_ =>
		{
			println!("REQUEST UNKNOWN");
		}
	}
}

extern crate threadpool;
use threadpool::ThreadPool;

fn proxy_time(port: u16, threads: usize) {
	let ip = Ipv4Addr::new(127, 0, 0, 1);
	let host = SocketAddrV4::new(ip, port);
	let listener = TcpListener::bind(host).unwrap();

	let pool = ThreadPool::new(threads);

	for stream in listener.incoming()
	{
		match stream
		{
			Ok(stream) =>
			{
				pool.execute(move || { proxy(stream); });
			}

			Err(_) =>
			{
				println!("NET error");
				1 << 7;
			}
		}
	}

	drop (listener);
}

fn main () {
	let threads = 128;
	let port: u16 = 9998;

	proxy_time(port, threads);
	println!("Blocking all badness");
}

<commit_msg>meh tired<commit_after>/*
  Copyright (c) 2015, Al Poole <netstar@gmail.com>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

//   This is a HTTPS CONNECT proxy!

use std::string::{String};
use std::net::{SocketAddrV4,Ipv4Addr,TcpListener,TcpStream};
use std::io::{Write, Read};

const REQUEST_LEN: usize = 65535;

fn substr(buf: [u8;REQUEST_LEN], needle: &str, byte: u8) -> String
{
	let mut i = 0;
	let mut x = 0;
	let mut request = String::new();

	let srch = needle.as_bytes();

	if srch.len() == 0 {
		return request;
	}

	while buf[i] as char != '\0'  {
		if buf[i] as char == srch[0] as char {
			while x < srch.len() && buf[i] as char  == srch[x] as char {
				i = i + 1;
				x = x + 1;
			}
			break;
		} else {
			i = i + 1;
		}
	}

	if x == srch.len() {
		let mut end = i;
		while buf[end] as char != byte as char && buf[end] as char != '\n'
		{
			end = end + 1;

		}

		for y in i..end {
			request.push(buf[y] as char);
		}
	}

	return request;
}

const CHUNK: usize = 4096; // PAGESIZEish

fn talk_to_me(mut instream: &TcpStream, mut outstream: &TcpStream, mut headers: &Header) -> bool
{

	let mut buf = [0u8; CHUNK];

	println!("top");
	let bytes = outstream.read(&mut buf).unwrap();
	if bytes <= 0 {
		return false;
	}

	println!("recv {}", bytes);

	for i in 0..bytes {
		print!("{}", buf[i] as char);
	}

	let mut chunk = 0;

	while chunk < bytes {
		let sent = instream.write(&mut buf[0..bytes]).unwrap();
		if sent <= 0 {
			return false;
		}
		println!("sent {}", sent);
		chunk = chunk + sent;
	}
	true
}

struct Header {
	pub hostname: String,
	pub connection: String,
	pub proxy: String,
	pub agent: String,
}

impl Header {

pub fn new() -> Header
{
	let hostname	 = String::new();
	let connection   = String::new();
	let proxy	 = String::new();
	let agent	 = String::new();

	let h = Header
	{
		hostname: hostname,
		connection: connection,
		proxy: proxy,
		agent: agent
	};

	return h;
}

}

fn http_connect_request(instream: TcpStream, headers: Header)
{
	let bogus_fix = &format!("{}", headers.hostname);

	let mut outstream = TcpStream::connect::<(&str)>(bogus_fix).unwrap();
	let mut disconnected = false;

	let response = format!("HTTP/1.1 200 Connection established\r\nUser-Agent: {}\r\nProxy-Connection: {}\r\nConnection: {}\r\nHost: {}\r\n\r\n",
			headers.agent, headers.proxy, headers.connection, headers.hostname);
	println!("sending: \n\n{}", response);
	let mut s = &instream;
	s.write(response.as_bytes()).unwrap(); // tell client the connection is made

	while ! disconnected {
		disconnected = talk_to_me(&instream, &outstream, &headers);
	}

}

fn check_headers(buffer: [u8;REQUEST_LEN], headers: &mut Header) -> bool
{
	let mut i = 0;

	while buffer[i] != '\0' as u8
	{
		print!("{}", buffer[i] as char);
		i+=1;
	}
	print!("\n");

	if headers.hostname.is_empty()
	{
		headers.hostname = substr(buffer, "Host: ", '\r' as u8);
	}

	if headers.connection.is_empty()
	{
		headers.connection = substr(buffer, "Connection: ", '\r' as u8);
	}

	if headers.proxy.is_empty()
	{
		headers.proxy = substr(buffer, "Proxy-Connection: ", '\r' as u8);
	}

	if headers.agent.is_empty()
	{
		headers.agent = substr(buffer, "User-Agent: ", '\r' as u8);
	}

	if ! headers.hostname.is_empty() && ! headers.connection.is_empty()
		&& ! headers.proxy.is_empty() && ! headers.agent.is_empty()
	{

		return true;
	}

	return false;
}

fn request_headers(mut instream: &TcpStream, headers: &mut Header)
{
	 loop
	{
		let mut buffer = [0u8; REQUEST_LEN];
		let mut byte = [0u8; 1];
		let mut len = 0;

		while byte[0] as char != '\n'
		{
			let bytes = instream.read(&mut byte).unwrap();
			buffer[len] = byte[0];
			len += bytes;
		}

		buffer[len] = '\0' as u8;

		if check_headers(buffer, headers) && len == 2
		{
			let mut i = 0;

			while i < REQUEST_LEN
			{
				buffer[i] = 0;
				i += 1;
			}
			return;
		}
	}

}

fn request_method(mut instream: &TcpStream) -> String
{
	let mut byte = [0u8;1];

	let mut method: String = String::new();

	// bit better for now it'll do!
	while byte[0] as char != ' '
	{
		instream.read(&mut byte).unwrap();
		if byte[0] as char != ' '
		{
			method.push(byte[0] as char);
		}
	}

	match method.as_ref()
	{
		"CONNECT" =>
		{
			return method;
		}

		"GET" | "POST" | "OPTIONS" | "HEAD" =>
		{
			return "".to_string();
			// all good do not return!!!
		}

		_ =>
		{
			return "".to_string();
		}
	}
}

fn proxy(stream: TcpStream) {
	let method = request_method(&stream);

	match method.as_ref()
	{
		"CONNECT" =>
		{
			let mut headers = Header::new();
			request_headers(&stream, &mut headers);

			http_connect_request(stream, headers);
		}

		_ =>
		{
			println!("REQUEST UNKNOWN");
		}
	}
}

extern crate threadpool;
use threadpool::ThreadPool;

fn proxy_time(port: u16, threads: usize) {
	let ip = Ipv4Addr::new(127, 0, 0, 1);
	let host = SocketAddrV4::new(ip, port);
	let listener = TcpListener::bind(host).unwrap();

	let pool = ThreadPool::new(threads);

	for stream in listener.incoming()
	{
		match stream
		{
			Ok(stream) =>
			{
				pool.execute(move || { proxy(stream); });
			}

			Err(_) =>
			{
				println!("NET error");
				1 << 7;
			}
		}
	}

	drop (listener);
}

fn main () {
	let threads = 128;
	let port: u16 = 9998;

	proxy_time(port, threads);
	println!("Blocking all badness");
}

<|endoftext|>