<commit_before>use parser::{Cond, Expr, Node, Target, WS};
use std::str;
use std::collections::HashSet;
use syn;

fn annotations(generics: &syn::Generics) -> String {
    if generics.lifetimes.len() < 1 {
        return String::new();
    }
    let mut res = String::new();
    res.push('<');
    for lt in &generics.lifetimes {
        res.push_str(lt.lifetime.ident.as_ref());
    }
    res.push('>');
    res
}

fn path_as_identifier(s: &str) -> String {
    let mut res = String::new();
    for c in s.chars() {
        if c.is_alphanumeric() {
            res.push(c);
        } else {
            res.push_str(&format!("{:x}", c as u32));
        }
    }
    res
}

struct Generator<'a> {
    buf: String,
    indent: u8,
    start: bool,
    locals: HashSet<String>,
    next_ws: Option<&'a str>,
    skip_ws: bool,
    loop_vars: bool,
    loop_index: u8,
}

impl<'a> Generator<'a> {

    fn new() -> Generator<'a> {
        Generator {
            buf: String::new(),
            indent: 0,
            start: true,
            locals: HashSet::new(),
            next_ws: None,
            skip_ws: false,
            loop_vars: false,
            loop_index: 0,
        }
    }

    fn indent(&mut self) {
        self.indent += 1;
    }

    fn dedent(&mut self) {
        self.indent -= 1;
    }

    fn write(&mut self, s: &str) {
        if self.start {
            for _ in 0..(self.indent * 4) {
                self.buf.push(' ');
            }
            self.start = false;
        }
        self.buf.push_str(s);
    }

    fn writeln(&mut self, s: &str) {
        if s.is_empty() {
            return;
        }
        if s == "}" {
            self.dedent();
        }
        self.write(s);
        if s.ends_with('{') {
            self.indent();
        }
        self.buf.push('\n');
        self.start = true;
    }

    fn flush_ws(&mut self, ws: &WS) {
        if self.next_ws.is_some() && !ws.0 {
            let val = self.next_ws.unwrap();
            if !val.is_empty() {
                self.writeln(&format!("writer.write_str({:#?}).unwrap();",
                                      val));
            }
        }
        self.next_ws = None;
    }

    fn prepare_ws(&mut self, ws: &WS) {
        self.skip_ws = ws.1;
    }

    fn handle_ws(&mut self, ws: &WS) {
        self.flush_ws(ws);
        self.prepare_ws(ws);
    }

    fn visit_num_lit(&mut self, s: &str) {
        self.write(s);
    }

    fn visit_str_lit(&mut self, s: &str) {
        self.write(&format!("\"{}\"", s));
    }

    fn visit_var(&mut self, s: &str) {
        if self.locals.contains(s) {
            self.write(s);
        } else {
            self.write(&format!("self.{}", s));
        }
    }

    fn visit_attr(&mut self, obj: &Expr, attr: &str) {
        if let Expr::Var(name) = *obj {
            if name == "loop" {
                self.write("_loop_indexes[_loop_cur]");
                if attr == "index" {
                    return;
                } else if attr == "index0" {
                    self.write(" - 1");
                    return;
                } else {
                    panic!("unknown loop variable");
                }
            }
        }
        self.visit_expr(obj);
        self.write(&format!(".{}", attr));
    }

    fn visit_filter(&mut self, name: &str, args: &[Expr]) {
        if name == "format" {
            self.write("format!(");
        } else {
            self.write(&format!("askama::filters::{}(&", name));
        }

        for (i, arg) in args.iter().enumerate() {
            if i > 0 {
                self.write(", &");
            }
            self.visit_expr(arg);
        }
        self.write(")");
    }

    fn visit_binop(&mut self, op: &str, left: &Expr, right: &Expr) {
        self.visit_expr(left);
        self.write(&format!(" {} ", op));
        self.visit_expr(right);
    }

    fn visit_group(&mut self, inner: &Expr) {
        self.write("(");
        self.visit_expr(inner);
        self.write(")");
    }

    fn visit_call(&mut self, obj: &Expr, method: &str, args: &[Expr]) {
        self.visit_expr(obj);
        self.write(&format!(".{}(", method));
        for (i, arg) in args.iter().enumerate() {
            if i > 0 {
                self.write(", ");
            }
            self.visit_expr(arg);
        }
        self.write(")");
    }

    fn visit_expr(&mut self, expr: &Expr) {
        match *expr {
            Expr::NumLit(s) => self.visit_num_lit(s),
            Expr::StrLit(s) => self.visit_str_lit(s),
            Expr::Var(s) => self.visit_var(s),
            Expr::Attr(ref obj, name) => self.visit_attr(obj, name),
            Expr::Filter(name, ref args) => self.visit_filter(name, args),
            Expr::BinOp(op, ref left, ref right) =>
                self.visit_binop(op, left, right),
            Expr::Group(ref inner) => self.visit_group(inner),
            Expr::Call(ref obj, method, ref args) =>
                self.visit_call(obj, method, args),
        }
    }

    fn visit_target_single(&mut self, name: &str) -> Vec<String> {
        vec![name.to_string()]
    }

    fn visit_target(&mut self, target: &Target) -> Vec<String> {
        match *target {
            Target::Name(s) => { self.visit_target_single(s) },
        }
    }

    fn write_lit(&mut self, lws: &'a str, val: &str, rws: &'a str) {
        assert!(self.next_ws.is_none());
        if !lws.is_empty() {
            if self.skip_ws {
                self.skip_ws = false;
            } else if val.is_empty() {
                assert!(rws.is_empty());
                self.next_ws = Some(lws);
            } else {
                self.writeln(&format!("writer.write_str({:#?}).unwrap();",
                                      lws));
            }
        }
        if !val.is_empty() {
            self.writeln(&format!("writer.write_str({:#?}).unwrap();", val));
        }
        if !rws.is_empty() {
            self.next_ws = Some(rws);
        }
    }

    fn write_expr(&mut self, ws: &WS, s: &Expr) {
        self.handle_ws(ws);
        self.write("writer.write_fmt(format_args!(\"{}\", ");
        self.visit_expr(s);
        self.writeln(")).unwrap();");
    }

    fn write_cond(&mut self, conds: &'a [Cond], ws: &WS) {
        for (i, &(ref cws, ref cond, ref nodes)) in conds.iter().enumerate() {
            self.handle_ws(cws);
            match *cond {
                Some(ref expr) => {
                    if i == 0 {
                        self.write("if ");
                    } else {
                        self.dedent();
                        self.write("} else if ");
                    }
                    self.visit_expr(expr);
                },
                None => {
                    self.dedent();
                    self.write("} else");
                },
            }
            self.writeln(" {");
            self.handle(nodes);
        }
        self.handle_ws(ws);
        self.writeln("}");
    }

    fn write_loop(&mut self, ws1: &WS, var: &Target, iter: &Expr,
                  body: &'a [Node], ws2: &WS) {

        self.handle_ws(ws1);
        if !self.loop_vars {
            self.writeln("let mut _loop_indexes = Vec::new();");
            self.writeln("let mut _loop_cur = 0;");
            self.loop_vars = true;
        }

        self.writeln("_loop_indexes.push(0);");
        let cur_index = self.loop_index;
        self.loop_index += 1;
        self.writeln(&format!("_loop_cur = {};", cur_index));
        self.write("for ");
        let targets = self.visit_target(var);
        for name in &targets {
            self.locals.insert(name.clone());
            self.write(name);
        }
        self.write(" in &");
        self.visit_expr(iter);
        self.writeln(" {");

        self.writeln("_loop_indexes[_loop_cur] += 1;");
        self.handle(body);
        self.handle_ws(ws2);
        self.writeln("}");
        self.loop_index -= 1;
        self.writeln("_loop_indexes.pop();");
        for name in &targets {
            self.locals.remove(name);
        }
    }

    fn write_block(&mut self, ws1: &WS, name: &str, ws2: &WS) {
        self.flush_ws(ws1);
        self.writeln(&format!("timpl.render_block_{}_to(writer);", name));
        self.prepare_ws(ws2);
    }

    fn write_block_def(&mut self, ws1: &WS, name: &str, nodes: &'a [Node],
                       ws2: &WS) {
        self.writeln("#[allow(unused_variables)]");
        self.writeln(&format!(
            "fn render_block_{}_to(&self, writer: &mut std::fmt::Write) {{",
            name));
        self.prepare_ws(ws1);
        self.handle(nodes);
        self.flush_ws(ws2);
        self.writeln("}");
    }

    fn handle(&mut self, nodes: &'a [Node]) {
        for n in nodes {
            match *n {
                Node::Lit(lws, val, rws) => { self.write_lit(lws, val, rws); }
                Node::Comment() => {},
                Node::Expr(ref ws, ref val) => { self.write_expr(ws, val); },
                Node::Cond(ref conds, ref ws) => {
                    self.write_cond(conds, ws);
                },
                Node::Loop(ref ws1, ref var, ref iter, ref body, ref ws2) => {
                    self.write_loop(ws1, var, iter, body, ws2);
                },
                Node::Block(ref ws1, name, ref ws2) => {
                    self.write_block(ws1, name, ws2);
                },
                Node::BlockDef(ref ws1, name, ref block_nodes, ref ws2) => {
                    self.write_block_def(ws1, name, block_nodes, ws2);
                }
                Node::Extends(_) => {
                    panic!("no extends or block definition allowed in content");
                },
            }
        }
    }

    fn path_based_name(&mut self, ast: &syn::DeriveInput, path: &str) {
        let encoded = path_as_identifier(path);
        let original = ast.ident.as_ref();
        let anno = annotations(&ast.generics);
        self.writeln("#[allow(dead_code, non_camel_case_types)]");
        let s = format!("type TemplateFrom{}{} = {}{};",
                        encoded, &anno, original, &anno);
        self.writeln(&s);
    }

    fn impl_template(&mut self, ast: &syn::DeriveInput, nodes: &'a [Node]) {
        let anno = annotations(&ast.generics);
        self.writeln(&format!("impl{} askama::Template for {}{} {{",
                              anno, ast.ident.as_ref(), anno));

        self.writeln("fn render_to(&self, writer: &mut std::fmt::Write) {");
        self.handle(nodes);
        self.flush_ws(&WS(false, false));
        self.writeln("}");
        self.writeln("}");
    }

    fn impl_trait(&mut self, ast: &syn::DeriveInput, base: &str,
                  blocks: &'a [Node], nodes: Option<&'a [Node]>) {
        let anno = annotations(&ast.generics);
        self.writeln(&format!("impl{} TraitFrom{} for {}{} {{",
                              anno, path_as_identifier(base),
                              ast.ident.as_ref(), anno));
        self.handle(blocks);

        self.writeln("#[allow(unused_variables)]");
        let trait_name = format!("TraitFrom{}", path_as_identifier(base));
        self.writeln(&format!(
            "fn render_trait_to(&self, timpl: &{}, writer: &mut std::fmt::Write) {{",
            trait_name));

        if let Some(nodes) = nodes {
            self.handle(nodes);
            self.flush_ws(&WS(false, false));
        } else {
            self.writeln("self._parent.render_trait_to(self, writer);");
        }

        self.writeln("}");
        self.flush_ws(&WS(false, false));
        self.writeln("}");
    }

    fn impl_template_for_trait(&mut self, ast: &syn::DeriveInput, derived: bool) {
        let anno = annotations(&ast.generics);
        self.writeln(&format!("impl{} askama::Template for {}{} {{",
                              anno, ast.ident.as_ref(), anno));
        self.writeln("fn render_to(&self, writer: &mut std::fmt::Write) {");
        if derived {
            self.writeln("self._parent.render_trait_to(self, writer);");
        } else {
            self.writeln("self.render_trait_to(self, writer);");
        }
        self.writeln("}");
        self.writeln("}");
    }

    fn define_trait(&mut self, path: &str, block_names: &[&str]) {
        let trait_name = format!("TraitFrom{}", path_as_identifier(path));
        self.writeln(&format!("trait {} {{", &trait_name));

        for bname in block_names {
            self.writeln(&format!(
                "fn render_block_{}_to(&self, writer: &mut std::fmt::Write);",
                bname));
        }
        self.writeln(&format!(
            "fn render_trait_to(&self, timpl: &{}, writer: &mut std::fmt::Write);",
            trait_name));

        self.writeln("}");
    }

    fn result(self) -> String {
        self.buf
    }

}

pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> String {
    let mut base: Option<Expr> = None;
    let mut blocks = Vec::new();
    let mut block_names = Vec::new();
    let mut content = Vec::new();
    for n in nodes.drain(..) {
        match n {
            Node::Extends(path) => {
                match base {
                    Some(_) => panic!("multiple extend blocks found"),
                    None => { base = Some(path); },
                }
            },
            Node::BlockDef(ws1, name, _, ws2) => {
                blocks.push(n);
                block_names.push(name);
                content.push(Node::Block(ws1, name, ws2));
            },
            _ => { content.push(n); },
        }
    }

    let mut gen = Generator::new();
    gen.path_based_name(ast, path);
    if !blocks.is_empty() {
        if base.is_none() {
            gen.define_trait(path, &block_names);
        }
        let tmpl_path = match base {
            Some(Expr::StrLit(base_path)) => { base_path },
            _ => { path },
        };
        let trait_nodes = if base.is_none() { Some(&content[..]) } else { None };
        gen.impl_trait(ast, tmpl_path, &blocks, trait_nodes);
        gen.impl_template_for_trait(ast, base.is_some());
    } else {
        gen.impl_template(ast, &content);
    }
    gen.result()
}
<commit_msg>Remove unused TemplateFrom types (fixes #5)<commit_after>use parser::{Cond, Expr, Node, Target, WS};
use std::str;
use std::collections::HashSet;
use syn;

fn annotations(generics: &syn::Generics) -> String {
    if generics.lifetimes.len() < 1 {
        return String::new();
    }
    let mut res = String::new();
    res.push('<');
    for lt in &generics.lifetimes {
        res.push_str(lt.lifetime.ident.as_ref());
    }
    res.push('>');
    res
}

fn path_as_identifier(s: &str) -> String {
    let mut res = String::new();
    for c in s.chars() {
        if c.is_alphanumeric() {
            res.push(c);
        } else {
            res.push_str(&format!("{:x}", c as u32));
        }
    }
    res
}

struct Generator<'a> {
    buf: String,
    indent: u8,
    start: bool,
    locals: HashSet<String>,
    next_ws: Option<&'a str>,
    skip_ws: bool,
    loop_vars: bool,
    loop_index: u8,
}

impl<'a> Generator<'a> {

    fn new() -> Generator<'a> {
        Generator {
            buf: String::new(),
            indent: 0,
            start: true,
            locals: HashSet::new(),
            next_ws: None,
            skip_ws: false,
            loop_vars: false,
            loop_index: 0,
        }
    }

    fn indent(&mut self) {
        self.indent += 1;
    }

    fn dedent(&mut self) {
        self.indent -= 1;
    }

    fn write(&mut self, s: &str) {
        if self.start {
            for _ in 0..(self.indent * 4) {
                self.buf.push(' ');
            }
            self.start = false;
        }
        self.buf.push_str(s);
    }

    fn writeln(&mut self, s: &str) {
        if s.is_empty() {
            return;
        }
        if s == "}" {
            self.dedent();
        }
        self.write(s);
        if s.ends_with('{') {
            self.indent();
        }
        self.buf.push('\n');
        self.start = true;
    }

    fn flush_ws(&mut self, ws: &WS) {
        if self.next_ws.is_some() && !ws.0 {
            let val = self.next_ws.unwrap();
            if !val.is_empty() {
                self.writeln(&format!("writer.write_str({:#?}).unwrap();",
                                      val));
            }
        }
        self.next_ws = None;
    }

    fn prepare_ws(&mut self, ws: &WS) {
        self.skip_ws = ws.1;
    }

    fn handle_ws(&mut self, ws: &WS) {
        self.flush_ws(ws);
        self.prepare_ws(ws);
    }

    fn visit_num_lit(&mut self, s: &str) {
        self.write(s);
    }

    fn visit_str_lit(&mut self, s: &str) {
        self.write(&format!("\"{}\"", s));
    }

    fn visit_var(&mut self, s: &str) {
        if self.locals.contains(s) {
            self.write(s);
        } else {
            self.write(&format!("self.{}", s));
        }
    }

    fn visit_attr(&mut self, obj: &Expr, attr: &str) {
        if let Expr::Var(name) = *obj {
            if name == "loop" {
                self.write("_loop_indexes[_loop_cur]");
                if attr == "index" {
                    return;
                } else if attr == "index0" {
                    self.write(" - 1");
                    return;
                } else {
                    panic!("unknown loop variable");
                }
            }
        }
        self.visit_expr(obj);
        self.write(&format!(".{}", attr));
    }

    fn visit_filter(&mut self, name: &str, args: &[Expr]) {
        if name == "format" {
            self.write("format!(");
        } else {
            self.write(&format!("askama::filters::{}(&", name));
        }

        for (i, arg) in args.iter().enumerate() {
            if i > 0 {
                self.write(", &");
            }
            self.visit_expr(arg);
        }
        self.write(")");
    }

    fn visit_binop(&mut self, op: &str, left: &Expr, right: &Expr) {
        self.visit_expr(left);
        self.write(&format!(" {} ", op));
        self.visit_expr(right);
    }

    fn visit_group(&mut self, inner: &Expr) {
        self.write("(");
        self.visit_expr(inner);
        self.write(")");
    }

    fn visit_call(&mut self, obj: &Expr, method: &str, args: &[Expr]) {
        self.visit_expr(obj);
        self.write(&format!(".{}(", method));
        for (i, arg) in args.iter().enumerate() {
            if i > 0 {
                self.write(", ");
            }
            self.visit_expr(arg);
        }
        self.write(")");
    }

    fn visit_expr(&mut self, expr: &Expr) {
        match *expr {
            Expr::NumLit(s) => self.visit_num_lit(s),
            Expr::StrLit(s) => self.visit_str_lit(s),
            Expr::Var(s) => self.visit_var(s),
            Expr::Attr(ref obj, name) => self.visit_attr(obj, name),
            Expr::Filter(name, ref args) => self.visit_filter(name, args),
            Expr::BinOp(op, ref left, ref right) =>
                self.visit_binop(op, left, right),
            Expr::Group(ref inner) => self.visit_group(inner),
            Expr::Call(ref obj, method, ref args) =>
                self.visit_call(obj, method, args),
        }
    }

    fn visit_target_single(&mut self, name: &str) -> Vec<String> {
        vec![name.to_string()]
    }

    fn visit_target(&mut self, target: &Target) -> Vec<String> {
        match *target {
            Target::Name(s) => { self.visit_target_single(s) },
        }
    }

    fn write_lit(&mut self, lws: &'a str, val: &str, rws: &'a str) {
        assert!(self.next_ws.is_none());
        if !lws.is_empty() {
            if self.skip_ws {
                self.skip_ws = false;
            } else if val.is_empty() {
                assert!(rws.is_empty());
                self.next_ws = Some(lws);
            } else {
                self.writeln(&format!("writer.write_str({:#?}).unwrap();",
                                      lws));
            }
        }
        if !val.is_empty() {
            self.writeln(&format!("writer.write_str({:#?}).unwrap();", val));
        }
        if !rws.is_empty() {
            self.next_ws = Some(rws);
        }
    }

    fn write_expr(&mut self, ws: &WS, s: &Expr) {
        self.handle_ws(ws);
        self.write("writer.write_fmt(format_args!(\"{}\", ");
        self.visit_expr(s);
        self.writeln(")).unwrap();");
    }

    fn write_cond(&mut self, conds: &'a [Cond], ws: &WS) {
        for (i, &(ref cws, ref cond, ref nodes)) in conds.iter().enumerate() {
            self.handle_ws(cws);
            match *cond {
                Some(ref expr) => {
                    if i == 0 {
                        self.write("if ");
                    } else {
                        self.dedent();
                        self.write("} else if ");
                    }
                    self.visit_expr(expr);
                },
                None => {
                    self.dedent();
                    self.write("} else");
                },
            }
            self.writeln(" {");
            self.handle(nodes);
        }
        self.handle_ws(ws);
        self.writeln("}");
    }

    fn write_loop(&mut self, ws1: &WS, var: &Target, iter: &Expr,
                  body: &'a [Node], ws2: &WS) {

        self.handle_ws(ws1);
        if !self.loop_vars {
            self.writeln("let mut _loop_indexes = Vec::new();");
            self.writeln("let mut _loop_cur = 0;");
            self.loop_vars = true;
        }

        self.writeln("_loop_indexes.push(0);");
        let cur_index = self.loop_index;
        self.loop_index += 1;
        self.writeln(&format!("_loop_cur = {};", cur_index));
        self.write("for ");
        let targets = self.visit_target(var);
        for name in &targets {
            self.locals.insert(name.clone());
            self.write(name);
        }
        self.write(" in &");
        self.visit_expr(iter);
        self.writeln(" {");

        self.writeln("_loop_indexes[_loop_cur] += 1;");
        self.handle(body);
        self.handle_ws(ws2);
        self.writeln("}");
        self.loop_index -= 1;
        self.writeln("_loop_indexes.pop();");
        for name in &targets {
            self.locals.remove(name);
        }
    }

    fn write_block(&mut self, ws1: &WS, name: &str, ws2: &WS) {
        self.flush_ws(ws1);
        self.writeln(&format!("timpl.render_block_{}_to(writer);", name));
        self.prepare_ws(ws2);
    }

    fn write_block_def(&mut self, ws1: &WS, name: &str, nodes: &'a [Node],
                       ws2: &WS) {
        self.writeln("#[allow(unused_variables)]");
        self.writeln(&format!(
            "fn render_block_{}_to(&self, writer: &mut std::fmt::Write) {{",
            name));
        self.prepare_ws(ws1);
        self.handle(nodes);
        self.flush_ws(ws2);
        self.writeln("}");
    }

    fn handle(&mut self, nodes: &'a [Node]) {
        for n in nodes {
            match *n {
                Node::Lit(lws, val, rws) => { self.write_lit(lws, val, rws); }
                Node::Comment() => {},
                Node::Expr(ref ws, ref val) => { self.write_expr(ws, val); },
                Node::Cond(ref conds, ref ws) => {
                    self.write_cond(conds, ws);
                },
                Node::Loop(ref ws1, ref var, ref iter, ref body, ref ws2) => {
                    self.write_loop(ws1, var, iter, body, ws2);
                },
                Node::Block(ref ws1, name, ref ws2) => {
                    self.write_block(ws1, name, ws2);
                },
                Node::BlockDef(ref ws1, name, ref block_nodes, ref ws2) => {
                    self.write_block_def(ws1, name, block_nodes, ws2);
                }
                Node::Extends(_) => {
                    panic!("no extends or block definition allowed in content");
                },
            }
        }
    }

    fn impl_template(&mut self, ast: &syn::DeriveInput, nodes: &'a [Node]) {
        let anno = annotations(&ast.generics);
        self.writeln(&format!("impl{} askama::Template for {}{} {{",
                              anno, ast.ident.as_ref(), anno));

        self.writeln("fn render_to(&self, writer: &mut std::fmt::Write) {");
        self.handle(nodes);
        self.flush_ws(&WS(false, false));
        self.writeln("}");
        self.writeln("}");
    }

    fn impl_trait(&mut self, ast: &syn::DeriveInput, base: &str,
                  blocks: &'a [Node], nodes: Option<&'a [Node]>) {
        let anno = annotations(&ast.generics);
        self.writeln(&format!("impl{} TraitFrom{} for {}{} {{",
                              anno, path_as_identifier(base),
                              ast.ident.as_ref(), anno));
        self.handle(blocks);

        self.writeln("#[allow(unused_variables)]");
        let trait_name = format!("TraitFrom{}", path_as_identifier(base));
        self.writeln(&format!(
            "fn render_trait_to(&self, timpl: &{}, writer: &mut std::fmt::Write) {{",
            trait_name));

        if let Some(nodes) = nodes {
            self.handle(nodes);
            self.flush_ws(&WS(false, false));
        } else {
            self.writeln("self._parent.render_trait_to(self, writer);");
        }

        self.writeln("}");
        self.flush_ws(&WS(false, false));
        self.writeln("}");
    }

    fn impl_template_for_trait(&mut self, ast: &syn::DeriveInput, derived: bool) {
        let anno = annotations(&ast.generics);
        self.writeln(&format!("impl{} askama::Template for {}{} {{",
                              anno, ast.ident.as_ref(), anno));
        self.writeln("fn render_to(&self, writer: &mut std::fmt::Write) {");
        if derived {
            self.writeln("self._parent.render_trait_to(self, writer);");
        } else {
            self.writeln("self.render_trait_to(self, writer);");
        }
        self.writeln("}");
        self.writeln("}");
    }

    fn define_trait(&mut self, path: &str, block_names: &[&str]) {
        let trait_name = format!("TraitFrom{}", path_as_identifier(path));
        self.writeln(&format!("trait {} {{", &trait_name));

        for bname in block_names {
            self.writeln(&format!(
                "fn render_block_{}_to(&self, writer: &mut std::fmt::Write);",
                bname));
        }
        self.writeln(&format!(
            "fn render_trait_to(&self, timpl: &{}, writer: &mut std::fmt::Write);",
            trait_name));

        self.writeln("}");
    }

    fn result(self) -> String {
        self.buf
    }

}

pub fn generate(ast: &syn::DeriveInput, path: &str, mut nodes: Vec<Node>) -> String {
    let mut base: Option<Expr> = None;
    let mut blocks = Vec::new();
    let mut block_names = Vec::new();
    let mut content = Vec::new();
    for n in nodes.drain(..) {
        match n {
            Node::Extends(path) => {
                match base {
                    Some(_) => panic!("multiple extend blocks found"),
                    None => { base = Some(path); },
                }
            },
            Node::BlockDef(ws1, name, _, ws2) => {
                blocks.push(n);
                block_names.push(name);
                content.push(Node::Block(ws1, name, ws2));
            },
            _ => { content.push(n); },
        }
    }

    let mut gen = Generator::new();
    if !blocks.is_empty() {
        if base.is_none() {
            gen.define_trait(path, &block_names);
        }
        let tmpl_path = match base {
            Some(Expr::StrLit(base_path)) => { base_path },
            _ => { path },
        };
        let trait_nodes = if base.is_none() { Some(&content[..]) } else { None };
        gen.impl_trait(ast, tmpl_path, &blocks, trait_nodes);
        gen.impl_template_for_trait(ast, base.is_some());
    } else {
        gen.impl_template(ast, &content);
    }
    gen.result()
}
<|endoftext|>


<commit_before>use crate::core::{PackageSet, Resolve, Workspace};
use crate::ops;
use crate::util::CargoResult;
use crate::util::Config;

pub struct SyncLockfileOptions<'a> {
    pub config: &'a Config,
    /// The target arch triple to sync lockfile dependencies for
    pub targets: Vec<String>,
}

/// Executes `cargo sync_lockfile`.
pub fn sync_lockfile<'a>(
    ws: &Workspace<'a>,
    _options: &SyncLockfileOptions<'a>,
) -> CargoResult<(Resolve, PackageSet<'a>)> {
    ws.emit_warnings()?;
    let (packages, resolve) = ops::resolve_ws(ws)?;
    Ok((resolve, packages))
}
<commit_msg>fix: remove unused<commit_after><|endoftext|>


<commit_before>use std::cmp::min;

use crate::buffer::Buffer;
use crate::layout::Rect;
use crate::style::Style;
use crate::symbols::bar;
use crate::widgets::{Block, Widget};

/// Widget to render a sparkline over one or more lines.
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, Borders, Sparkline};
/// # use tui::style::{Style, Color};
/// # fn main() {
/// Sparkline::default()
///     .block(Block::default().title("Sparkline").borders(Borders::ALL))
///     .data(&[0, 2, 3, 4, 1, 4, 10])
///     .max(5)
///     .style(Style::default().fg(Color::Red).bg(Color::White));
/// # }
/// ```
pub struct Sparkline<'a> {
    /// A block to wrap the widget in
    block: Option<Block<'a>>,
    /// Widget style
    style: Style,
    /// A slice of the data to display
    data: &'a [u64],
    /// The maximum value to take to compute the maximum bar height (if nothing is specified, the
    /// widget uses the max of the dataset)
    max: Option<u64>,
}

impl<'a> Default for Sparkline<'a> {
    fn default() -> Sparkline<'a> {
        Sparkline {
            block: None,
            style: Default::default(),
            data: &[],
            max: None,
        }
    }
}

impl<'a> Sparkline<'a> {
    pub fn block(mut self, block: Block<'a>) -> Sparkline<'a> {
        self.block = Some(block);
        self
    }

    pub fn style(mut self, style: Style) -> Sparkline<'a> {
        self.style = style;
        self
    }

    pub fn data(mut self, data: &'a [u64]) -> Sparkline<'a> {
        self.data = data;
        self
    }

    pub fn max(mut self, max: u64) -> Sparkline<'a> {
        self.max = Some(max);
        self
    }
}

impl<'a> Widget for Sparkline<'a> {
    fn draw(&mut self, area: Rect, buf: &mut Buffer) {
        let spark_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => area,
        };

        if spark_area.height < 1 {
            return;
        }

        let max = match self.max {
            Some(v) => v,
            None => *self.data.iter().max().unwrap_or(&1u64),
        };
        let max_index = min(spark_area.width as usize, self.data.len());
        let mut data = self
            .data
            .iter()
            .take(max_index)
            .map(|e| {
                if max != 0 {
                    e * u64::from(spark_area.height) * 8 / max
                } else {
                    0
                }
            })
            .collect::<Vec<u64>>();
        for j in (0..spark_area.height).rev() {
            for (i, d) in data.iter_mut().enumerate() {
                let symbol = match *d {
                    0 => " ",
                    1 => bar::ONE_EIGHTH,
                    2 => bar::ONE_QUATER,
                    3 => bar::THREE_EIGHTHS,
                    4 => bar::HALF,
                    5 => bar::FIVE_EIGHTHS,
                    6 => bar::THREE_QUATERS,
                    7 => bar::SEVEN_EIGHTHS,
                    _ => bar::FULL,
                };
                buf.get_mut(spark_area.left() + i as u16, spark_area.top() + j)
                    .set_symbol(symbol)
                    .set_fg(self.style.fg)
                    .set_bg(self.style.bg);

                if *d > 8 {
                    *d -= 8;
                } else {
                    *d = 0;
                }
            }
        }
    }
}

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

    #[test]
    fn it_does_not_panic_if_max_is_zero() {
        let mut widget = Sparkline::default().data(&[0, 0, 0]);
        let area = Rect::new(0, 0, 3, 1);
        let mut buffer = Buffer::empty(area);
        widget.draw(area, &mut buffer);
    }

    #[test]
    fn it_does_not_panic_if_max_is_set_to_zero() {
        let mut widget = Sparkline::default().data(&[0, 1, 2]).max(0);
        let area = Rect::new(0, 0, 3, 1);
        let mut buffer = Buffer::empty(area);
        widget.draw(area, &mut buffer);
    }
}
<commit_msg>typo in sparkline.rs<commit_after>use std::cmp::min;

use crate::buffer::Buffer;
use crate::layout::Rect;
use crate::style::Style;
use crate::symbols::bar;
use crate::widgets::{Block, Widget};

/// Widget to render a sparkline over one or more lines.
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, Borders, Sparkline};
/// # use tui::style::{Style, Color};
/// # fn main() {
/// Sparkline::default()
///     .block(Block::default().title("Sparkline").borders(Borders::ALL))
///     .data(&[0, 2, 3, 4, 1, 4, 10])
///     .max(5)
///     .style(Style::default().fg(Color::Red).bg(Color::White));
/// # }
/// ```
pub struct Sparkline<'a> {
    /// A block to wrap the widget in
    block: Option<Block<'a>>,
    /// Widget style
    style: Style,
    /// A slice of the data to display
    data: &'a [u64],
    /// The maximum value to take to compute the maximum bar height (if nothing is specified, the
    /// widget uses the max of the dataset)
    max: Option<u64>,
}

impl<'a> Default for Sparkline<'a> {
    fn default() -> Sparkline<'a> {
        Sparkline {
            block: None,
            style: Default::default(),
            data: &[],
            max: None,
        }
    }
}

impl<'a> Sparkline<'a> {
    pub fn block(mut self, block: Block<'a>) -> Sparkline<'a> {
        self.block = Some(block);
        self
    }

    pub fn style(mut self, style: Style) -> Sparkline<'a> {
        self.style = style;
        self
    }

    pub fn data(mut self, data: &'a [u64]) -> Sparkline<'a> {
        self.data = data;
        self
    }

    pub fn max(mut self, max: u64) -> Sparkline<'a> {
        self.max = Some(max);
        self
    }
}

impl<'a> Widget for Sparkline<'a> {
    fn draw(&mut self, area: Rect, buf: &mut Buffer) {
        let spark_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => area,
        };

        if spark_area.height < 1 {
            return;
        }

        let max = match self.max {
            Some(v) => v,
            None => *self.data.iter().max().unwrap_or(&1u64),
        };
        let max_index = min(spark_area.width as usize, self.data.len());
        let mut data = self
            .data
            .iter()
            .take(max_index)
            .map(|e| {
                if max != 0 {
                    e * u64::from(spark_area.height) * 8 / max
                } else {
                    0
                }
            })
            .collect::<Vec<u64>>();
        for j in (0..spark_area.height).rev() {
            for (i, d) in data.iter_mut().enumerate() {
                let symbol = match *d {
                    0 => " ",
                    1 => bar::ONE_EIGHTH,
                    2 => bar::ONE_QUARTER,
                    3 => bar::THREE_EIGHTHS,
                    4 => bar::HALF,
                    5 => bar::FIVE_EIGHTHS,
                    6 => bar::THREE_QUARTERS,
                    7 => bar::SEVEN_EIGHTHS,
                    _ => bar::FULL,
                };
                buf.get_mut(spark_area.left() + i as u16, spark_area.top() + j)
                    .set_symbol(symbol)
                    .set_fg(self.style.fg)
                    .set_bg(self.style.bg);

                if *d > 8 {
                    *d -= 8;
                } else {
                    *d = 0;
                }
            }
        }
    }
}

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

    #[test]
    fn it_does_not_panic_if_max_is_zero() {
        let mut widget = Sparkline::default().data(&[0, 0, 0]);
        let area = Rect::new(0, 0, 3, 1);
        let mut buffer = Buffer::empty(area);
        widget.draw(area, &mut buffer);
    }

    #[test]
    fn it_does_not_panic_if_max_is_set_to_zero() {
        let mut widget = Sparkline::default().data(&[0, 1, 2]).max(0);
        let area = Rect::new(0, 0, 3, 1);
        let mut buffer = Buffer::empty(area);
        widget.draw(area, &mut buffer);
    }
}
<|endoftext|>


<commit_before>use libc::{size_t, c_int, c_uint};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

/// Nodes forming chains.
#[repr(C)]
pub struct Node {
  weight: size_t,     // Total weight (symbol count) of this chain.
  tail: *const Node,  // Previous node(s) of this chain, or 0 if none.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

#[repr(C)]
pub struct Leaf {
  weight: size_t,     // Total weight (symbol count) of this chain.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

/// Memory pool for nodes.
#[repr(C)]
pub struct NodePool {
  next: *const Node,   // Pointer to a possibly free node in the pool.
}

/// Initializes a chain node with the given values and marks it as in use.
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn InitNode(weight: size_t, count: c_int, tail: *const Node, node_ptr: *mut Node) {
    let node = unsafe {
        assert!(!node_ptr.is_null());
        &mut *node_ptr
    };

    node.weight = weight;
    node.count = count;
    node.tail = tail;
}

/// Converts result of boundary package-merge to the bitlengths. The result in the
/// last chain of the last list contains the amount of active leaves in each list.
/// chain: Chain to extract the bit length from (last chain from last list).
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ExtractBitLengths(chain: *const Node, leaves: *const Leaf, bitlengths: *mut c_uint) {
    let mut counts = [0; 16];
    let mut end = 16;
    let mut ptr = 15;
    let mut value = 1;

    let mut node_ptr = chain;
    while !node_ptr.is_null() {
        let node = unsafe {
           &*node_ptr
        };

        end -= 1;
        counts[end] = node.count;

        node_ptr = node.tail;
    }

    let mut val = counts[15];
    while ptr >= end {
        while val > counts[ptr - 1] {
            unsafe {
                let leaf = &*leaves.offset((val - 1) as isize);
                *bitlengths.offset(leaf.count as isize) = value;
            }
            val -= 1;
        }
        ptr -= 1;
        value += 1;
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    // #[test]
    // fn one_test() {
    //     let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    //     let output = length_limited_code_lengths(&input, 7);
    //     let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    //     assert_eq!(output, answer);
    // }
}

// maxbits: 7
// frequencies: [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// bitlengths: [1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// maxbits: 7
// frequencies: [10, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, ]
// bitlengths: [3, 0, 6, 4, 3, 4, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, ]
// bitlengths: [4, 0, 6, 4, 3, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 26, 0, ]
// bitlengths: [4, 0, 6, 4, 3, 4, 4, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, ]
// maxbits: 7
// frequencies: [19, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ]
// bitlengths: [2, 0, 6, 3, 3, 2, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ]
// maxbits: 7
// frequencies: [8, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, ]
// bitlengths: [3, 0, 5, 3, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, ]
// bitlengths: [4, 0, 6, 3, 2, 2, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, ]
// bitlengths: [3, 0, 6, 3, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, ]
// maxbits: 15
// frequencies: [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// bitlengths: [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
<commit_msg>Turn frequencies into ordered list of non-zero leaves<commit_after>use std::cmp::Ordering;

use libc::{size_t, c_int, c_uint};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

/// Nodes forming chains.
#[repr(C)]
pub struct Node {
  weight: size_t,     // Total weight (symbol count) of this chain.
  tail: *const Node,  // Previous node(s) of this chain, or 0 if none.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

#[repr(C)]
pub struct Leaf {
  weight: size_t,     // Total weight (symbol count) of this chain.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

/// Memory pool for nodes.
#[repr(C)]
pub struct NodePool {
  next: *const Node,   // Pointer to a possibly free node in the pool.
}

/// Initializes a chain node with the given values and marks it as in use.
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn InitNode(weight: size_t, count: c_int, tail: *const Node, node_ptr: *mut Node) {
    let node = unsafe {
        assert!(!node_ptr.is_null());
        &mut *node_ptr
    };

    node.weight = weight;
    node.count = count;
    node.tail = tail;
}

/// Converts result of boundary package-merge to the bitlengths. The result in the
/// last chain of the last list contains the amount of active leaves in each list.
/// chain: Chain to extract the bit length from (last chain from last list).
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ExtractBitLengths(chain: *const Node, leaves: *const Leaf, bitlengths: *mut c_uint) {
    let mut counts = [0; 16];
    let mut end = 16;
    let mut ptr = 15;
    let mut value = 1;

    let mut node_ptr = chain;
    while !node_ptr.is_null() {
        let node = unsafe {
           &*node_ptr
        };

        end -= 1;
        counts[end] = node.count;

        node_ptr = node.tail;
    }

    let mut val = counts[15];
    while ptr >= end {
        while val > counts[ptr - 1] {
            unsafe {
                let leaf = &*leaves.offset((val - 1) as isize);
                *bitlengths.offset(leaf.count as isize) = value;
            }
            val -= 1;
        }
        ptr -= 1;
        value += 1;
    }
}

struct N {
    weight: size_t,
    leaf_count: c_int,
}

struct L {
    pub weight: size_t,
    pub index: size_t,
}
impl PartialEq for L {
    fn eq(&self, other: &Self) -> bool {
        self.weight == other.weight
    }
}
impl Eq for L { }
impl Ord for L {
    fn cmp(&self, other: &Self) -> Ordering {
        self.weight.cmp(&other.weight)
    }
}
impl PartialOrd for L {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

struct List {
    lookahead1: N,
    lookahead2: N,
    last_active: N,
    next_leaf_index: size_t,
}

pub fn length_limited_code_lengths(frequencies: &[size_t], maxbits: c_int) -> Vec<size_t> {
    let mut leaves = vec![];

    // Count used symbols and place them in the leaves.
    for (i, &freq) in frequencies.iter().enumerate() {
        if freq != 0 {
            leaves.push(L { weight: freq, index: i });
        }
    }

    // Sort the leaves from least frequent to most frequent.
    // Add index into the same variable for stable sorting.
    for leaf in leaves.iter_mut() {
        leaf.weight = (leaf.weight << 9) | leaf.index;
    }
    leaves.sort();
    for leaf in leaves.iter_mut() {
        leaf.weight >>= 9;
    }

    let mut lists = Vec::with_capacity(maxbits as usize);
    for _ in 0..maxbits {
        lists.push(List {
            lookahead1: N { weight: leaves[0].weight, leaf_count: 1 },
            lookahead2: N { weight: leaves[1].weight, leaf_count: 2 },
            last_active: N { weight: leaves[1].weight, leaf_count: 2 },
            next_leaf_index: 2,
        });
    }

    let n = frequencies.len();

    let mut result = vec![0; n];
    result
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    // #[test]
    // fn one_test() {
    //     let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    //     let output = length_limited_code_lengths(&input, 7);
    //     let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    //     assert_eq!(output, answer);
    // }
}

// maxbits: 7
// frequencies: [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// bitlengths: [1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// maxbits: 7
// frequencies: [10, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, ]
// bitlengths: [3, 0, 6, 4, 3, 4, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, ]
// bitlengths: [4, 0, 6, 4, 3, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 26, 0, ]
// bitlengths: [4, 0, 6, 4, 3, 4, 4, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, ]
// maxbits: 7
// frequencies: [19, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ]
// bitlengths: [2, 0, 6, 3, 3, 2, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ]
// maxbits: 7
// frequencies: [8, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, ]
// bitlengths: [3, 0, 5, 3, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, ]
// bitlengths: [4, 0, 6, 3, 2, 2, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, ]
// bitlengths: [3, 0, 6, 3, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, ]
// maxbits: 15
// frequencies: [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// bitlengths: [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
<|endoftext|>


<commit_before>use util::units::{Offset, Point, Size};

pub struct Rectangle {
    location: Point,
    size: Size,
}

impl Rectangle {
    pub fn new(location: Point, size: Size) -> Rectangle {
        Rectangle { location: location, size: size }
    }

    pub fn translate(&self, offset: Offset) -> Rectangle {
        Rectangle { location: self.location + offset, size: self.size }
    }

    pub fn resize(&self, offset: Offset) -> Rectangle {
        Rectangle { location: self.location, size: self.size + offset }
    }

    pub fn location(&self) -> Point {
        return self.location;
    }

    pub fn size(&self) -> Size {
        return self.size;
    }

    pub fn width(&self) -> i32 {
        return self.size.x;
    }

    pub fn height(&self) -> i32 {
        return self.size.y;
    }
}

pub struct BorderedRectangle {
    rect: Rectangle,
}

impl BorderedRectangle {
    pub fn new(location: Point, size: Size) -> BorderedRectangle {
        BorderedRectangle { rect: Rectangle::new(location, size) }
    }

    pub fn translate(&self, offset: Offset) -> BorderedRectangle {
        BorderedRectangle { rect: self.rect.translate(offset) }
    }

    pub fn resize(&self, offset: Offset) -> BorderedRectangle {
        BorderedRectangle { rect: self.rect.resize(offset) }
    }

    pub fn location(&self) -> Point {
        return self.rect.location();
    }

    pub fn inner_location(&self) -> Point {
        return self.location() + Offset::new(1, 1);
    }

    pub fn size(&self) -> Size {
        return self.rect.size();
    }

    pub fn inner_size(&self) -> Size {
        return self.size() - Offset::new(2, 2);
    }

    pub fn width(&self) -> i32 {
        return self.rect.size().x;
    }

    pub fn inner_width(&self) -> i32 {
        return self.width() - 2;
    }

    pub fn height(&self) -> i32 {
        return self.rect.size().y;
    }

    pub fn inner_height(&self) -> i32 {
        return self.height() - 2;
    }
}
<commit_msg>Make Rectangle and BorderedRectangle derive standard traits<commit_after>use util::units::{Offset, Point, Size};

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Rectangle {
    location: Point,
    size: Size,
}

impl Rectangle {
    pub fn new(location: Point, size: Size) -> Rectangle {
        Rectangle { location: location, size: size }
    }

    pub fn translate(&self, offset: Offset) -> Rectangle {
        Rectangle { location: self.location + offset, size: self.size }
    }

    pub fn resize(&self, offset: Offset) -> Rectangle {
        Rectangle { location: self.location, size: self.size + offset }
    }

    pub fn location(&self) -> Point {
        return self.location;
    }

    pub fn size(&self) -> Size {
        return self.size;
    }

    pub fn width(&self) -> i32 {
        return self.size.x;
    }

    pub fn height(&self) -> i32 {
        return self.size.y;
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct BorderedRectangle {
    rect: Rectangle,
}

impl BorderedRectangle {
    pub fn new(location: Point, size: Size) -> BorderedRectangle {
        BorderedRectangle { rect: Rectangle::new(location, size) }
    }

    pub fn translate(&self, offset: Offset) -> BorderedRectangle {
        BorderedRectangle { rect: self.rect.translate(offset) }
    }

    pub fn resize(&self, offset: Offset) -> BorderedRectangle {
        BorderedRectangle { rect: self.rect.resize(offset) }
    }

    pub fn location(&self) -> Point {
        return self.rect.location();
    }

    pub fn inner_location(&self) -> Point {
        return self.location() + Offset::new(1, 1);
    }

    pub fn size(&self) -> Size {
        return self.rect.size();
    }

    pub fn inner_size(&self) -> Size {
        return self.size() - Offset::new(2, 2);
    }

    pub fn width(&self) -> i32 {
        return self.rect.size().x;
    }

    pub fn inner_width(&self) -> i32 {
        return self.width() - 2;
    }

    pub fn height(&self) -> i32 {
        return self.rect.size().y;
    }

    pub fn inner_height(&self) -> i32 {
        return self.height() - 2;
    }
}
<|endoftext|>


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

//! The implementation of the DOM.
//!
//! The DOM is comprised of interfaces (defined by specifications using
//! [WebIDL](https://heycam.github.io/webidl/)) that are implemented as Rust
//! structs in submodules of this module. Its implementation is documented
//! below.
//!
//! A DOM object and its reflector
//! ==============================
//!
//! The implementation of an interface `Foo` in Servo's DOM involves two
//! related but distinct objects:
//!
//! * the **DOM object**: an instance of the Rust struct `dom::foo::Foo`
//!   (marked with the `#[dom_struct]` attribute) on the Rust heap;
//! * the **reflector**: a `JSObject` allocated by SpiderMonkey, that owns the
//!   DOM object.
//!
//! Memory management
//! =================
//!
//! Reflectors of DOM objects, and thus the DOM objects themselves, are managed
//! by the SpiderMonkey Garbage Collector. Thus, keeping alive a DOM object
//! is done through its reflector.
//!
//! For more information, see:
//!
//! * rooting pointers on the stack:
//!   the [`Root`](bindings/js/struct.Root.html) smart pointer;
//! * tracing pointers in member fields: the [`JS`](bindings/js/struct.JS.html),
//!   [`MutNullableJS`](bindings/js/struct.MutNullableJS.html) and
//!   [`MutHeap`](bindings/js/struct.MutHeap.html) smart pointers and
//!   [the tracing implementation](bindings/trace/index.html);
//! * rooting pointers from across task boundaries or in channels: the
//!   [`Trusted`](bindings/refcounted/struct.Trusted.html) smart pointer;
//! * extracting pointers to DOM objects from their reflectors: the
//!   [`Unrooted`](bindings/js/struct.Unrooted.html) smart pointer.
//!
//! Inheritance
//! ===========
//!
//! Rust does not support struct inheritance, as would be used for the
//! object-oriented DOM APIs. To work around this issue, Servo stores an
//! instance of the superclass in the first field of its subclasses. (Note that
//! it is stored by value, rather than in a smart pointer such as `JS<T>`.)
//!
//! This implies that a pointer to an object can safely be cast to a pointer
//! to all its classes.
//!
//! This invariant is enforced by the lint in
//! `plugins::lints::inheritance_integrity`.
//!
//! Construction
//! ============
//!
//! DOM objects of type `T` in Servo have two constructors:
//!
//! * a `T::new_inherited` static method that returns a plain `T`, and
//! * a `T::new` static method that returns `Root<T>`.
//!
//! (The result of either method can be wrapped in `Result`, if that is
//! appropriate for the type in question.)
//!
//! The latter calls the former, boxes the result, and creates a reflector
//! corresponding to it by calling `dom::bindings::utils::reflect_dom_object`
//! (which yields ownership of the object to the SpiderMonkey Garbage Collector).
//! This is the API to use when creating a DOM object.
//!
//! The former should only be called by the latter, and by subclasses'
//! `new_inherited` methods.
//!
//! DOM object constructors in JavaScript correspond to a `T::Constructor`
//! static method. This method is always fallible.
//!
//! Destruction
//! ===========
//!
//! When the SpiderMonkey Garbage Collector discovers that the reflector of a
//! DOM object is garbage, it calls the reflector's finalization hook. This
//! function deletes the reflector's DOM object, calling its destructor in the
//! process.
//!
//! Mutability and aliasing
//! =======================
//!
//! Reflectors are JavaScript objects, and as such can be freely aliased. As
//! Rust does not allow mutable aliasing, mutable borrows of DOM objects are
//! not allowed. In particular, any mutable fields use `Cell` or `DOMRefCell`
//! to manage their mutability.
//!
//! `Reflector` and `Reflectable`
//! =============================
//!
//! Every DOM object has a `Reflector` as its first (transitive) member field.
//! This contains a `*mut JSObject` that points to its reflector.
//!
//! The `FooBinding::Wrap` function creates the reflector, stores a pointer to
//! the DOM object in the reflector, and initializes the pointer to the reflector
//! in the `Reflector` field.
//!
//! The `Reflectable` trait provides a `reflector()` method that returns the
//! DOM object's `Reflector`. It is implemented automatically for DOM structs
//! through the `#[dom_struct]` attribute.
//!
//! Implementing methods for a DOM object
//! =====================================
//!
//! XXX JSRef no longer exists - should we remove the *Helpers traits?
//! In order to ensure that DOM objects are rooted when they are called, we
//! require that all methods are implemented for `JSRef<'a, Foo>`. This means
//! that all methods are defined on traits. Conventionally, those traits are
//! called
//!
//! * `dom::bindings::codegen::Bindings::FooBindings::FooMethods` for methods
//!   defined through IDL;
//! * `FooHelpers` for public methods;
//! * `PrivateFooHelpers` for private methods.
//!
//! Accessing fields of a DOM object
//! ================================
//!
//! All fields of DOM objects are private; accessing them from outside their
//! module is done through explicit getter or setter methods.
//!
//! Inheritance and casting
//! =======================
//!
//! For all DOM interfaces `Foo` in an inheritance chain, a
//! `dom::bindings::codegen::InheritTypes::FooCast` provides methods to cast
//! to other types in the inheritance chain. For example:
//!
//! ```ignore
//! # use script::dom::bindings::codegen::InheritTypes::{NodeCast, HTMLElementCast};
//! # use script::dom::element::Element;
//! # use script::dom::node::Node;
//! # use script::dom::htmlelement::HTMLElement;
//! fn f(element: &Element) {
//!     let base: &Node = NodeCast::from_ref(element);
//!     let derived: Option<&HTMLElement> = HTMLElementCast::to_ref(element);
//! }
//! ```
//!
//! Adding a new DOM interface
//! ==========================
//!
//! Adding a new interface `Foo` requires at least the following:
//!
//! * adding the new IDL file at `components/script/dom/webidls/Foo.webidl`;
//! * creating `components/script/dom/foo.rs`;
//! * listing `foo.rs` in `components/script/dom/mod.rs`;
//! * defining the DOM struct `Foo` with a `#[dom_struct]` attribute, a
//!   superclass or `Reflector` member, and other members as appropriate;
//! * implementing the
//!   `dom::bindings::codegen::Bindings::FooBindings::FooMethods` trait for
//!   `&'a Foo`.
//!
//! More information is available in the [bindings module](bindings/index.html).
//!
//! Accessing DOM objects from layout
//! =================================
//!
//! Layout code can access the DOM through the
//! [`LayoutJS`](bindings/js/struct.LayoutJS.html) smart pointer. This does not
//! keep the DOM object alive; we ensure that no DOM code (Garbage Collection
//! in particular) runs while the layout task is accessing the DOM.
//!
//! Methods accessible to layout are implemented on `LayoutJS<Foo>` using
//! `LayoutFooHelpers` traits.

#[macro_use]
pub mod macros;

pub mod bindings;

pub mod types {
    include!(concat!(env!("OUT_DIR"), "/InterfaceTypes.rs"));
}

pub mod activation;
pub mod attr;
pub mod blob;
pub mod browsercontext;
pub mod canvasgradient;
pub mod canvaspattern;
pub mod canvasrenderingcontext2d;
pub mod characterdata;
pub mod css;
pub mod cssstyledeclaration;
pub mod dompoint;
pub mod dompointreadonly;
pub mod domrect;
pub mod domrectlist;
pub mod domstringmap;
pub mod closeevent;
pub mod comment;
pub mod console;
mod create;
pub mod crypto;
pub mod customevent;
pub mod dedicatedworkerglobalscope;
pub mod document;
pub mod documentfragment;
pub mod documenttype;
pub mod domexception;
pub mod domimplementation;
pub mod domparser;
pub mod domtokenlist;
pub mod element;
pub mod errorevent;
pub mod event;
pub mod eventdispatcher;
pub mod eventtarget;
pub mod file;
pub mod filelist;
pub mod filereader;
pub mod formdata;
pub mod htmlanchorelement;
pub mod htmlappletelement;
pub mod htmlareaelement;
pub mod htmlaudioelement;
pub mod htmlbaseelement;
pub mod htmlbodyelement;
pub mod htmlbrelement;
pub mod htmlbuttonelement;
pub mod htmlcanvaselement;
pub mod htmlcollection;
pub mod htmldataelement;
pub mod htmldatalistelement;
pub mod htmldialogelement;
pub mod htmldirectoryelement;
pub mod htmldivelement;
pub mod htmldlistelement;
pub mod htmlelement;
pub mod htmlembedelement;
pub mod htmlfieldsetelement;
pub mod htmlfontelement;
pub mod htmlformelement;
pub mod htmlframeelement;
pub mod htmlframesetelement;
pub mod htmlheadelement;
pub mod htmlheadingelement;
pub mod htmlhrelement;
pub mod htmlhtmlelement;
pub mod htmliframeelement;
pub mod htmlimageelement;
pub mod htmlinputelement;
pub mod htmllabelelement;
pub mod htmllegendelement;
pub mod htmllielement;
pub mod htmllinkelement;
pub mod htmlmapelement;
pub mod htmlmediaelement;
pub mod htmlmetaelement;
pub mod htmlmeterelement;
pub mod htmlmodelement;
pub mod htmlobjectelement;
pub mod htmlolistelement;
pub mod htmloptgroupelement;
pub mod htmloptionelement;
pub mod htmloutputelement;
pub mod htmlparagraphelement;
pub mod htmlparamelement;
pub mod htmlpreelement;
pub mod htmlprogresselement;
pub mod htmlquoteelement;
pub mod htmlscriptelement;
pub mod htmlselectelement;
pub mod htmlspanelement;
pub mod htmlsourceelement;
pub mod htmlstyleelement;
pub mod htmltableelement;
pub mod htmltablecaptionelement;
pub mod htmltablecellelement;
pub mod htmltabledatacellelement;
pub mod htmltableheadercellelement;
pub mod htmltablecolelement;
pub mod htmltablerowelement;
pub mod htmltablesectionelement;
pub mod htmltemplateelement;
pub mod htmltextareaelement;
pub mod htmltimeelement;
pub mod htmltitleelement;
pub mod htmltrackelement;
pub mod htmlulistelement;
pub mod htmlvideoelement;
pub mod htmlunknownelement;
pub mod imagedata;
pub mod keyboardevent;
pub mod location;
pub mod messageevent;
pub mod mouseevent;
pub mod namednodemap;
pub mod navigator;
pub mod navigatorinfo;
pub mod node;
pub mod nodeiterator;
pub mod nodelist;
pub mod processinginstruction;
pub mod performance;
pub mod performancetiming;
pub mod progressevent;
pub mod range;
pub mod screen;
pub mod servohtmlparser;
pub mod storage;
pub mod storageevent;
pub mod text;
pub mod textdecoder;
pub mod textencoder;
pub mod treewalker;
pub mod uievent;
pub mod url;
pub mod urlhelper;
pub mod urlsearchparams;
pub mod userscripts;
pub mod validitystate;
pub mod virtualmethods;
pub mod webglobject;
pub mod webglbuffer;
pub mod webglprogram;
pub mod webglrenderingcontext;
pub mod webglshader;
pub mod webgluniformlocation;
pub mod webgltexture;
pub mod webglframebuffer;
pub mod webglrenderbuffer;
pub mod webglactiveinfo;
pub mod webglshaderprecisionformat;
pub mod websocket;
pub mod window;
pub mod worker;
pub mod workerglobalscope;
pub mod workerlocation;
pub mod workernavigator;
pub mod xmlhttprequest;
pub mod xmlhttprequesteventtarget;
pub mod xmlhttprequestupload;

pub mod testbinding;
pub mod testbindingproxy;
<commit_msg>Documentation of inheritance in type ids<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! The implementation of the DOM.
//!
//! The DOM is comprised of interfaces (defined by specifications using
//! [WebIDL](https://heycam.github.io/webidl/)) that are implemented as Rust
//! structs in submodules of this module. Its implementation is documented
//! below.
//!
//! A DOM object and its reflector
//! ==============================
//!
//! The implementation of an interface `Foo` in Servo's DOM involves two
//! related but distinct objects:
//!
//! * the **DOM object**: an instance of the Rust struct `dom::foo::Foo`
//!   (marked with the `#[dom_struct]` attribute) on the Rust heap;
//! * the **reflector**: a `JSObject` allocated by SpiderMonkey, that owns the
//!   DOM object.
//!
//! Memory management
//! =================
//!
//! Reflectors of DOM objects, and thus the DOM objects themselves, are managed
//! by the SpiderMonkey Garbage Collector. Thus, keeping alive a DOM object
//! is done through its reflector.
//!
//! For more information, see:
//!
//! * rooting pointers on the stack:
//!   the [`Root`](bindings/js/struct.Root.html) smart pointer;
//! * tracing pointers in member fields: the [`JS`](bindings/js/struct.JS.html),
//!   [`MutNullableJS`](bindings/js/struct.MutNullableJS.html) and
//!   [`MutHeap`](bindings/js/struct.MutHeap.html) smart pointers and
//!   [the tracing implementation](bindings/trace/index.html);
//! * rooting pointers from across task boundaries or in channels: the
//!   [`Trusted`](bindings/refcounted/struct.Trusted.html) smart pointer;
//! * extracting pointers to DOM objects from their reflectors: the
//!   [`Unrooted`](bindings/js/struct.Unrooted.html) smart pointer.
//!
//! Inheritance
//! ===========
//!
//! Rust does not support struct inheritance, as would be used for the
//! object-oriented DOM APIs. To work around this issue, Servo stores an
//! instance of the superclass in the first field of its subclasses. (Note that
//! it is stored by value, rather than in a smart pointer such as `JS<T>`.)
//!
//! This implies that a pointer to an object can safely be cast to a pointer
//! to all its classes.
//!
//! This invariant is enforced by the lint in
//! `plugins::lints::inheritance_integrity`.
//!
//! The same principle applies to typeids,
//! the derived type enum should
//! use one addititional type (the parent class) because sometimes the parent
//! can be the most-derived class of an object.
//! ```ignore
//! pub enum EventTypeId {
//!     UIEvent(UIEventTypeId),
//!     //others events
//! }
//!
//! pub enum UIEventTypeId {
//!    MouseEvent,
//!    KeyboardEvent,
//!    UIEvent, //<- parent of MouseEvent and KeyboardEvent
//! }
//! ```
//!
//! Construction
//! ============
//!
//! DOM objects of type `T` in Servo have two constructors:
//!
//! * a `T::new_inherited` static method that returns a plain `T`, and
//! * a `T::new` static method that returns `Root<T>`.
//!
//! (The result of either method can be wrapped in `Result`, if that is
//! appropriate for the type in question.)
//!
//! The latter calls the former, boxes the result, and creates a reflector
//! corresponding to it by calling `dom::bindings::utils::reflect_dom_object`
//! (which yields ownership of the object to the SpiderMonkey Garbage Collector).
//! This is the API to use when creating a DOM object.
//!
//! The former should only be called by the latter, and by subclasses'
//! `new_inherited` methods.
//!
//! DOM object constructors in JavaScript correspond to a `T::Constructor`
//! static method. This method is always fallible.
//!
//! Destruction
//! ===========
//!
//! When the SpiderMonkey Garbage Collector discovers that the reflector of a
//! DOM object is garbage, it calls the reflector's finalization hook. This
//! function deletes the reflector's DOM object, calling its destructor in the
//! process.
//!
//! Mutability and aliasing
//! =======================
//!
//! Reflectors are JavaScript objects, and as such can be freely aliased. As
//! Rust does not allow mutable aliasing, mutable borrows of DOM objects are
//! not allowed. In particular, any mutable fields use `Cell` or `DOMRefCell`
//! to manage their mutability.
//!
//! `Reflector` and `Reflectable`
//! =============================
//!
//! Every DOM object has a `Reflector` as its first (transitive) member field.
//! This contains a `*mut JSObject` that points to its reflector.
//!
//! The `FooBinding::Wrap` function creates the reflector, stores a pointer to
//! the DOM object in the reflector, and initializes the pointer to the reflector
//! in the `Reflector` field.
//!
//! The `Reflectable` trait provides a `reflector()` method that returns the
//! DOM object's `Reflector`. It is implemented automatically for DOM structs
//! through the `#[dom_struct]` attribute.
//!
//! Implementing methods for a DOM object
//! =====================================
//!
//! XXX JSRef no longer exists - should we remove the *Helpers traits?
//! In order to ensure that DOM objects are rooted when they are called, we
//! require that all methods are implemented for `JSRef<'a, Foo>`. This means
//! that all methods are defined on traits. Conventionally, those traits are
//! called
//!
//! * `dom::bindings::codegen::Bindings::FooBindings::FooMethods` for methods
//!   defined through IDL;
//! * `FooHelpers` for public methods;
//! * `PrivateFooHelpers` for private methods.
//!
//! Accessing fields of a DOM object
//! ================================
//!
//! All fields of DOM objects are private; accessing them from outside their
//! module is done through explicit getter or setter methods.
//!
//! Inheritance and casting
//! =======================
//!
//! For all DOM interfaces `Foo` in an inheritance chain, a
//! `dom::bindings::codegen::InheritTypes::FooCast` provides methods to cast
//! to other types in the inheritance chain. For example:
//!
//! ```ignore
//! # use script::dom::bindings::codegen::InheritTypes::{NodeCast, HTMLElementCast};
//! # use script::dom::element::Element;
//! # use script::dom::node::Node;
//! # use script::dom::htmlelement::HTMLElement;
//! fn f(element: &Element) {
//!     let base: &Node = NodeCast::from_ref(element);
//!     let derived: Option<&HTMLElement> = HTMLElementCast::to_ref(element);
//! }
//! ```
//!
//! Adding a new DOM interface
//! ==========================
//!
//! Adding a new interface `Foo` requires at least the following:
//!
//! * adding the new IDL file at `components/script/dom/webidls/Foo.webidl`;
//! * creating `components/script/dom/foo.rs`;
//! * listing `foo.rs` in `components/script/dom/mod.rs`;
//! * defining the DOM struct `Foo` with a `#[dom_struct]` attribute, a
//!   superclass or `Reflector` member, and other members as appropriate;
//! * implementing the
//!   `dom::bindings::codegen::Bindings::FooBindings::FooMethods` trait for
//!   `&'a Foo`.
//!
//! More information is available in the [bindings module](bindings/index.html).
//!
//! Accessing DOM objects from layout
//! =================================
//!
//! Layout code can access the DOM through the
//! [`LayoutJS`](bindings/js/struct.LayoutJS.html) smart pointer. This does not
//! keep the DOM object alive; we ensure that no DOM code (Garbage Collection
//! in particular) runs while the layout task is accessing the DOM.
//!
//! Methods accessible to layout are implemented on `LayoutJS<Foo>` using
//! `LayoutFooHelpers` traits.

#[macro_use]
pub mod macros;

pub mod bindings;

pub mod types {
    include!(concat!(env!("OUT_DIR"), "/InterfaceTypes.rs"));
}

pub mod activation;
pub mod attr;
pub mod blob;
pub mod browsercontext;
pub mod canvasgradient;
pub mod canvaspattern;
pub mod canvasrenderingcontext2d;
pub mod characterdata;
pub mod css;
pub mod cssstyledeclaration;
pub mod dompoint;
pub mod dompointreadonly;
pub mod domrect;
pub mod domrectlist;
pub mod domstringmap;
pub mod closeevent;
pub mod comment;
pub mod console;
mod create;
pub mod crypto;
pub mod customevent;
pub mod dedicatedworkerglobalscope;
pub mod document;
pub mod documentfragment;
pub mod documenttype;
pub mod domexception;
pub mod domimplementation;
pub mod domparser;
pub mod domtokenlist;
pub mod element;
pub mod errorevent;
pub mod event;
pub mod eventdispatcher;
pub mod eventtarget;
pub mod file;
pub mod filelist;
pub mod filereader;
pub mod formdata;
pub mod htmlanchorelement;
pub mod htmlappletelement;
pub mod htmlareaelement;
pub mod htmlaudioelement;
pub mod htmlbaseelement;
pub mod htmlbodyelement;
pub mod htmlbrelement;
pub mod htmlbuttonelement;
pub mod htmlcanvaselement;
pub mod htmlcollection;
pub mod htmldataelement;
pub mod htmldatalistelement;
pub mod htmldialogelement;
pub mod htmldirectoryelement;
pub mod htmldivelement;
pub mod htmldlistelement;
pub mod htmlelement;
pub mod htmlembedelement;
pub mod htmlfieldsetelement;
pub mod htmlfontelement;
pub mod htmlformelement;
pub mod htmlframeelement;
pub mod htmlframesetelement;
pub mod htmlheadelement;
pub mod htmlheadingelement;
pub mod htmlhrelement;
pub mod htmlhtmlelement;
pub mod htmliframeelement;
pub mod htmlimageelement;
pub mod htmlinputelement;
pub mod htmllabelelement;
pub mod htmllegendelement;
pub mod htmllielement;
pub mod htmllinkelement;
pub mod htmlmapelement;
pub mod htmlmediaelement;
pub mod htmlmetaelement;
pub mod htmlmeterelement;
pub mod htmlmodelement;
pub mod htmlobjectelement;
pub mod htmlolistelement;
pub mod htmloptgroupelement;
pub mod htmloptionelement;
pub mod htmloutputelement;
pub mod htmlparagraphelement;
pub mod htmlparamelement;
pub mod htmlpreelement;
pub mod htmlprogresselement;
pub mod htmlquoteelement;
pub mod htmlscriptelement;
pub mod htmlselectelement;
pub mod htmlspanelement;
pub mod htmlsourceelement;
pub mod htmlstyleelement;
pub mod htmltableelement;
pub mod htmltablecaptionelement;
pub mod htmltablecellelement;
pub mod htmltabledatacellelement;
pub mod htmltableheadercellelement;
pub mod htmltablecolelement;
pub mod htmltablerowelement;
pub mod htmltablesectionelement;
pub mod htmltemplateelement;
pub mod htmltextareaelement;
pub mod htmltimeelement;
pub mod htmltitleelement;
pub mod htmltrackelement;
pub mod htmlulistelement;
pub mod htmlvideoelement;
pub mod htmlunknownelement;
pub mod imagedata;
pub mod keyboardevent;
pub mod location;
pub mod messageevent;
pub mod mouseevent;
pub mod namednodemap;
pub mod navigator;
pub mod navigatorinfo;
pub mod node;
pub mod nodeiterator;
pub mod nodelist;
pub mod processinginstruction;
pub mod performance;
pub mod performancetiming;
pub mod progressevent;
pub mod range;
pub mod screen;
pub mod servohtmlparser;
pub mod storage;
pub mod storageevent;
pub mod text;
pub mod textdecoder;
pub mod textencoder;
pub mod treewalker;
pub mod uievent;
pub mod url;
pub mod urlhelper;
pub mod urlsearchparams;
pub mod userscripts;
pub mod validitystate;
pub mod virtualmethods;
pub mod webglobject;
pub mod webglbuffer;
pub mod webglprogram;
pub mod webglrenderingcontext;
pub mod webglshader;
pub mod webgluniformlocation;
pub mod webgltexture;
pub mod webglframebuffer;
pub mod webglrenderbuffer;
pub mod webglactiveinfo;
pub mod webglshaderprecisionformat;
pub mod websocket;
pub mod window;
pub mod worker;
pub mod workerglobalscope;
pub mod workerlocation;
pub mod workernavigator;
pub mod xmlhttprequest;
pub mod xmlhttprequesteventtarget;
pub mod xmlhttprequestupload;

pub mod testbinding;
pub mod testbindingproxy;
<|endoftext|>


<commit_before>use errors::*;

use rsa::Rsa;

use bignum::OpensslBigNum as BigNum;
use bignum::{BigNumExt, BigNumTrait};

use rand;
use rand::Rng;

use std::cmp;

// We use the variable names from the paper
#[allow(non_snake_case)]
pub fn run(rsa_bits: usize) -> Result<(), Error> {
    let _0 = BigNum::zero();
    let _1 = BigNum::one();
    let _2 = BigNum::from_u32(2);
    let _3 = BigNum::from_u32(3);

    let rsa = Rsa::<BigNum>::generate(rsa_bits);
    let n = rsa.n();
    let k = n.bytes() as usize;
    let B = _1.lsh(8 * (k - 2));
    let _2B = &_2 * &B;
    let _3B = &_3 * &B;

    let oracle = |ciphertext: &BigNum| -> bool {
        let cleartext = rsa.decrypt(ciphertext);
        cleartext.rsh(8 * (k - 2)) == _2
    };

    let cleartext = b"kick it, CC";
    let cleartext_len = cleartext.len();
    assert!(cleartext_len <= k - 11);
    let mut padded_cleartext = vec![2u8];
    let mut rng = rand::thread_rng();
    padded_cleartext.extend((0..(k - 3 - cleartext_len)).map(|_| rng.gen_range(1, 256) as u8));
    padded_cleartext.push(0);
    padded_cleartext.extend_from_slice(cleartext);
    let m: BigNum = BigNumTrait::from_bytes_be(&padded_cleartext);
    let c = rsa.encrypt(&m);

    // We are only ever going to use `oracle` in the following way
    let wrapped_oracle = |s: &BigNum| -> bool { oracle(&(&c * &rsa.encrypt(s))) };

    let mut M_prev = vec![(_2B.clone(), &_3B - &_1)];
    let mut s_prev = _1.clone();
    let mut i = 1;

    loop {
        // Step 2
        let mut si;
        if i == 1 {
            // Step 2.a
            si = n.ceil_quotient(&_3B);
            while !wrapped_oracle(&si) {
                si = &si + &_1;
            }
        } else if M_prev.len() >= 2 {
            // Step 2.b
            si = &s_prev + &_1;
            while !wrapped_oracle(&si) {
                si = &si + &_1;
            }
        } else {
            // Step 2.c
            let (ref a, ref b) = M_prev[0];
            let mut ri = (&_2 * &(&(b * &s_prev) - &_2B)).ceil_quotient(n);
            'outer: loop {
                si = (&_2B + &(&ri * n)).ceil_quotient(b);
                let U = (&_3B + &(&ri * n)).ceil_quotient(a);
                while si < U {
                    if wrapped_oracle(&si) {
                        break 'outer;
                    }
                    si = &si + &_1;
                }
                ri = &ri + &_1;
            }
        }

        let mut Mi = Vec::new();
        for &(ref a, ref b) in &M_prev {
            let mut r = (&(&(a * &si) - &_3B) + &_1).ceil_quotient(n);
            let U = (&(b * &si) - &_2B).floor_quotient(n);
            while r <= U {
                Mi.push((
                    cmp::max(a.clone(), (&_2B + &(&r * n)).ceil_quotient(&si)),
                    cmp::min(b.clone(), (&(&_3B - &_1) + &(&r * n)).floor_quotient(&si)),
                ));
                r = &r + &_1;
            }
        }

        Mi.sort();
        Mi.dedup();
        if Mi.len() == 1 && Mi[0].0 == Mi[0].1 {
            return compare_eq(&m, &Mi[0].0);
        }
        i += 1;
        s_prev = si;
        M_prev = Mi;
    }
}
<commit_msg>Reorganize code a bit<commit_after>use errors::*;

use rsa::Rsa;

use bignum::OpensslBigNum as BigNum;
use bignum::{BigNumExt, BigNumTrait};

use rand;
use rand::Rng;

use std::cmp;

struct Server {
    rsa: Rsa<BigNum>,
}

// We do not need an oracle which checks for full PKCS#1v1.5 conformance.
// It suffices that the oracle tells us whether the cleartext is of the form
// 00 || 02 || another k - 2 bytes,
// where k is the number of bytes in the RSA modulus.
impl Server {
    fn new(rsa_bits: usize) -> Self {
        let rsa = Rsa::generate(rsa_bits);
        Server { rsa }
    }

    fn n(&self) -> &BigNum {
        self.rsa.n()
    }

    fn oracle(&self, ciphertext: &BigNum) -> bool {
        let cleartext = self.rsa.decrypt(ciphertext);
        cleartext.rsh(8 * (self.rsa.n().bytes() - 2)) == BigNum::from_u32(2)
    }

    fn get_ciphertext(&self) -> BigNum {
        let k = self.rsa.n().bytes() as usize;
        let cleartext = b"kick it, CC";
        let cleartext_len = cleartext.len();
        assert!(cleartext_len <= k - 11);
        let mut padded_cleartext = vec![2u8];
        let mut rng = rand::thread_rng();
        padded_cleartext.extend((0..(k - 3 - cleartext_len)).map(|_| rng.gen_range(1, 256) as u8));
        padded_cleartext.push(0);
        padded_cleartext.extend_from_slice(cleartext);
        let m: BigNum = BigNumTrait::from_bytes_be(&padded_cleartext);
        self.rsa.encrypt(&m)
    }

    fn encrypt(&self, cleartext: &BigNum) -> BigNum {
        self.rsa.encrypt(cleartext)
    }
}

// We use the variable names from the paper
#[allow(non_snake_case)]
pub fn run(rsa_bits: usize) -> Result<(), Error> {
    let _0 = BigNum::zero();
    let _1 = BigNum::one();
    let _2 = BigNum::from_u32(2);
    let _3 = BigNum::from_u32(3);

    let server = Server::new(rsa_bits);
    let n = server.n();
    let k = n.bytes() as usize;
    let B = _1.lsh(8 * (k - 2));
    let _2B = &_2 * &B;
    let _3B = &_3 * &B;

    let c = server.get_ciphertext();

    // We are only ever going to use `oracle` in the following way
    let wrapped_oracle = |s: &BigNum| -> bool { server.oracle(&(&c * &server.encrypt(s))) };

    let mut M_prev = vec![(_2B.clone(), &_3B - &_1)];
    let mut s_prev = _1.clone();
    let mut i = 1;

    // We know that the cleartext corresponding to our ciphertext is PKCS conforming, so we can skip
    // Step 1 of the paper.
    loop {
        // Step 2
        let mut si;
        if i == 1 {
            // Step 2.a
            si = n.ceil_quotient(&_3B);
            while !wrapped_oracle(&si) {
                si = &si + &_1;
            }
        } else if M_prev.len() >= 2 {
            // Step 2.b
            si = &s_prev + &_1;
            while !wrapped_oracle(&si) {
                si = &si + &_1;
            }
        } else {
            // Step 2.c
            let (ref a, ref b) = M_prev[0];
            let mut ri = (&_2 * &(&(b * &s_prev) - &_2B)).ceil_quotient(n);
            'outer: loop {
                si = (&_2B + &(&ri * n)).ceil_quotient(b);
                let U = (&_3B + &(&ri * n)).ceil_quotient(a);
                while si < U {
                    if wrapped_oracle(&si) {
                        break 'outer;
                    }
                    si = &si + &_1;
                }
                ri = &ri + &_1;
            }
        }

        let mut Mi = Vec::new();
        for &(ref a, ref b) in &M_prev {
            let mut r = (&(&(a * &si) - &_3B) + &_1).ceil_quotient(n);
            let U = (&(b * &si) - &_2B).floor_quotient(n);
            while r <= U {
                Mi.push((
                    cmp::max(a.clone(), (&_2B + &(&r * n)).ceil_quotient(&si)),
                    cmp::min(b.clone(), (&(&_3B - &_1) + &(&r * n)).floor_quotient(&si)),
                ));
                r = &r + &_1;
            }
        }

        Mi.sort();
        Mi.dedup();
        if Mi.len() == 1 && Mi[0].0 == Mi[0].1 {
            // Verify that our cleartext encrypts to the ciphertext
            return compare_eq(&c, &server.encrypt(&Mi[0].0));
        }
        i += 1;
        s_prev = si;
        M_prev = Mi;
    }
}
<|endoftext|>


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

// ignore-windows
// ignore-macos

#![feature(macro_rules)]

extern crate native;
extern crate rustrt;
extern crate libc;
use libc::{c_char, c_int};
use native::io::process;
use rustrt::rtio;
use rustrt::c_str;

macro_rules! c_string {
    ($s:expr) => { {
        let ptr = concat!($s, "\0").as_ptr() as *const i8;
        unsafe { &c_str::CString::new(ptr, false) }
    } }
}

static EXPECTED_ERRNO: c_int = 0x778899aa;

#[no_mangle]
pub unsafe extern "C" fn chdir(_: *const c_char) -> c_int {
    // copied from std::os::errno()
    #[cfg(any(target_os = "macos",
              target_os = "ios",
              target_os = "freebsd"))]
    fn errno_location() -> *mut c_int {
        extern {
            fn __error() -> *mut c_int;
        }
        unsafe {
            __error()
        }
    }

    #[cfg(target_os = "dragonfly")]
    fn errno_location() -> *mut c_int {
        extern {
            fn __dfly_error() -> *mut c_int;
        }
        unsafe {
            __dfly_error()
        }
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    fn errno_location() -> *mut c_int {
        extern {
            fn __errno_location() -> *mut c_int;
        }
        unsafe {
            __errno_location()
        }
    }

    *errno_location() = EXPECTED_ERRNO;
    return -1;
}

fn main() {
    let program = c_string!("true");
    let cwd = c_string!("whatever");
    let cfg = rtio::ProcessConfig {
        program: program,
        args: &[],
        env: None,
        cwd: Some(cwd),
        stdin: rtio::Ignored,
        stdout: rtio::Ignored,
        stderr: rtio::Ignored,
        extra_io: &[],
        uid: None,
        gid: None,
        detach: false
    };

    match process::Process::spawn(cfg) {
        Ok(_) => { panic!("spawn() should have panicked"); }
        Err(rtio::IoError { code: err, ..}) => {
            assert_eq!(err as c_int, EXPECTED_ERRNO);
        }
    };
}
<commit_msg>Remove somewhat bogus process-spawn-errno test (non-mac, non-windows only)<commit_after><|endoftext|>