<commit_before>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;
use std::fs;
use std::path::Path;
use std::collections::{HashMap, hash_map};

use csv;
use itertools::Itertools;
use bio::alignment::distance;

/// A codebook record.
#[derive(RustcDecodable)]
pub struct Record {
    pub feature: String,
    pub codeword: String,
    pub expressed: u8
}

/// Codebook representation.
pub struct Codebook {
    inner: HashMap<String, [u32; 4]>
}

impl Codebook {
    pub fn neighbors(&self, feature: &str, dist: u8) -> u32 {
        self.inner.get(feature)
                  .expect(&format!("Error: Feature {} not in codebook.", feature))[dist as usize - 1]
    }

    pub fn features(&self) -> hash_map::Keys<String, [u32; 4]> {
        self.inner.keys()
    }

    pub fn contains(&self, feature: &str) -> bool {
        self.inner.contains(feature)
    }
}

/// Reader for codebook definitions.
pub struct Reader<R: io::Read> {
    inner: csv::Reader<R>,
    dist: u8
}

impl Reader<fs::File> {
    /// Read from a given file path.
    pub fn from_file<P: AsRef<Path>>(path: P, dist: u8) -> io::Result<Self> {
        fs::File::open(path).map(|f| Reader::from_reader(f, dist))
    }
}

impl<R: io::Read> Reader<R> {
    pub fn from_reader(rdr: R, dist: u8) -> Self {
        Reader {
            inner: csv::Reader::from_reader(rdr).delimiter(b'\t'),
            dist: dist
        }
    }

    pub fn codebook(&mut self) -> Codebook {
        let records = self.inner.decode::<Record>().map(|record| record.unwrap()).collect_vec();
        let mut inner = HashMap::new();
        for record in records.iter() {
            if record.expressed == 1 {
                inner.insert(record.feature.clone(), [0; 4]);
            }
        }
        for a in records.iter() {
            let codeword = a.codeword.as_bytes();
            let neighbors = inner.get_mut(&a.feature).unwrap();
            for b in records.iter() {
                if b.feature != a.feature {
                    let dist = distance::hamming(codeword, b.codeword.as_bytes()).unwrap();
                    assert!(dist >= self.dist as u32, "Unexpected hamming distance {} (>={} allowed).", dist, self.dist);
                    if dist <= 4 && b.expressed == 1 {
                        neighbors[(dist - 1) as usize] += 1;
                    }
                }
            }
        }
        Codebook { inner: inner }
    }
}
<commit_msg>Minor.<commit_after>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::io;
use std::fs;
use std::path::Path;
use std::collections::{HashMap, hash_map};

use csv;
use itertools::Itertools;
use bio::alignment::distance;

/// A codebook record.
#[derive(RustcDecodable)]
pub struct Record {
    pub feature: String,
    pub codeword: String,
    pub expressed: u8
}

/// Codebook representation.
pub struct Codebook {
    inner: HashMap<String, [u32; 4]>
}

impl Codebook {
    pub fn neighbors(&self, feature: &str, dist: u8) -> u32 {
        self.inner.get(feature)
                  .expect(&format!("Error: Feature {} not in codebook.", feature))[dist as usize - 1]
    }

    pub fn features(&self) -> hash_map::Keys<String, [u32; 4]> {
        self.inner.keys()
    }

    pub fn contains(&self, feature: &str) -> bool {
        self.inner.contains_key(feature)
    }
}

/// Reader for codebook definitions.
pub struct Reader<R: io::Read> {
    inner: csv::Reader<R>,
    dist: u8
}

impl Reader<fs::File> {
    /// Read from a given file path.
    pub fn from_file<P: AsRef<Path>>(path: P, dist: u8) -> io::Result<Self> {
        fs::File::open(path).map(|f| Reader::from_reader(f, dist))
    }
}

impl<R: io::Read> Reader<R> {
    pub fn from_reader(rdr: R, dist: u8) -> Self {
        Reader {
            inner: csv::Reader::from_reader(rdr).delimiter(b'\t'),
            dist: dist
        }
    }

    pub fn codebook(&mut self) -> Codebook {
        let records = self.inner.decode::<Record>().map(|record| record.unwrap()).collect_vec();
        let mut inner = HashMap::new();
        for record in records.iter() {
            if record.expressed == 1 {
                inner.insert(record.feature.clone(), [0; 4]);
            }
        }
        for a in records.iter() {
            let codeword = a.codeword.as_bytes();
            let neighbors = inner.get_mut(&a.feature).unwrap();
            for b in records.iter() {
                if b.feature != a.feature {
                    let dist = distance::hamming(codeword, b.codeword.as_bytes()).unwrap();
                    assert!(dist >= self.dist as u32, "Unexpected hamming distance {} (>={} allowed).", dist, self.dist);
                    if dist <= 4 && b.expressed == 1 {
                        neighbors[(dist - 1) as usize] += 1;
                    }
                }
            }
        }
        Codebook { inner: inner }
    }
}
<|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.

//! This module provides linkage between libgraphviz traits and
//! `rustc::middle::typeck::infer::region_inference`, generating a
//! rendering of the graph represented by the list of `Constraint`
//! instances (which make up the edges of the graph), as well as the
//! origin for each constraint (which are attached to the labels on
//! each edge).

/// For clarity, rename the graphviz crate locally to dot.
use graphviz as dot;

use hir::def_id::DefIndex;
use ty;
use middle::free_region::RegionRelations;
use middle::region::CodeExtent;
use super::Constraint;
use infer::SubregionOrigin;
use infer::region_inference::RegionVarBindings;
use util::nodemap::{FxHashMap, FxHashSet};

use std::borrow::Cow;
use std::collections::hash_map::Entry::Vacant;
use std::env;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::sync::atomic::{AtomicBool, Ordering};

fn print_help_message() {
    println!("\
-Z print-region-graph by default prints a region constraint graph for every \n\
function body, to the path `/tmp/constraints.nodeXXX.dot`, where the XXX is \n\
replaced with the node id of the function under analysis.                   \n\
                                                                            \n\
To select one particular function body, set `RUST_REGION_GRAPH_NODE=XXX`,   \n\
where XXX is the node id desired.                                           \n\
                                                                            \n\
To generate output to some path other than the default                      \n\
`/tmp/constraints.nodeXXX.dot`, set `RUST_REGION_GRAPH=/path/desired.dot`;  \n\
occurrences of the character `%` in the requested path will be replaced with\n\
the node id of the function under analysis.                                 \n\
                                                                            \n\
(Since you requested help via RUST_REGION_GRAPH=help, no region constraint  \n\
graphs will be printed.                                                     \n\
");
}

pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
    region_vars: &RegionVarBindings<'a, 'gcx, 'tcx>,
    region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
{
    let context = region_rels.context;

    if !region_vars.tcx.sess.opts.debugging_opts.print_region_graph {
        return;
    }

    let requested_node = env::var("RUST_REGION_GRAPH_NODE")
        .ok().and_then(|s| s.parse().map(DefIndex::new).ok());

    if requested_node.is_some() && requested_node != Some(context.index) {
        return;
    }

    let requested_output = env::var("RUST_REGION_GRAPH");
    debug!("requested_output: {:?} requested_node: {:?}",
           requested_output,
           requested_node);

    let output_path = {
        let output_template = match requested_output {
            Ok(ref s) if s == "help" => {
                static PRINTED_YET: AtomicBool = AtomicBool::new(false);
                if !PRINTED_YET.load(Ordering::SeqCst) {
                    print_help_message();
                    PRINTED_YET.store(true, Ordering::SeqCst);
                }
                return;
            }

            Ok(other_path) => other_path,
            Err(_) => "/tmp/constraints.node%.dot".to_string(),
        };

        if output_template.is_empty() {
            panic!("empty string provided as RUST_REGION_GRAPH");
        }

        if output_template.contains('%') {
            let mut new_str = String::new();
            for c in output_template.chars() {
                if c == '%' {
                    new_str.push_str(&context.index.as_usize().to_string());
                } else {
                    new_str.push(c);
                }
            }
            new_str
        } else {
            output_template
        }
    };

    let constraints = &*region_vars.constraints.borrow();
    match dump_region_constraints_to(region_rels, constraints, &output_path) {
        Ok(()) => {}
        Err(e) => {
            let msg = format!("io error dumping region constraints: {}", e);
            region_vars.tcx.sess.err(&msg)
        }
    }
}

struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    graph_name: String,
    region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
    map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
    node_ids: FxHashMap<Node, usize>,
}

#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
enum Node {
    RegionVid(ty::RegionVid),
    Region(ty::RegionKind),
}

// type Edge = Constraint;
#[derive(Clone, PartialEq, Eq, Debug, Copy)]
enum Edge<'tcx> {
    Constraint(Constraint<'tcx>),
    EnclScope(CodeExtent, CodeExtent),
}

impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
    fn new(name: String,
           region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
           map: &'a ConstraintMap<'tcx>)
           -> ConstraintGraph<'a, 'gcx, 'tcx> {
        let mut i = 0;
        let mut node_ids = FxHashMap();
        {
            let mut add_node = |node| {
                if let Vacant(e) = node_ids.entry(node) {
                    e.insert(i);
                    i += 1;
                }
            };

            for (n1, n2) in map.keys().map(|c| constraint_to_nodes(c)) {
                add_node(n1);
                add_node(n2);
            }

            region_rels.region_maps.each_encl_scope(|sub, sup| {
                add_node(Node::Region(ty::ReScope(sub)));
                add_node(Node::Region(ty::ReScope(sup)));
            });
        }

        ConstraintGraph {
            map,
            node_ids,
            region_rels,
            graph_name: name,
        }
    }
}

impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
    type Node = Node;
    type Edge = Edge<'tcx>;
    fn graph_id(&self) -> dot::Id {
        dot::Id::new(&*self.graph_name).unwrap()
    }
    fn node_id(&self, n: &Node) -> dot::Id {
        let node_id = match self.node_ids.get(n) {
            Some(node_id) => node_id,
            None => bug!("no node_id found for node: {:?}", n),
        };
        let name = || format!("node_{}", node_id);
        match dot::Id::new(name()) {
            Ok(id) => id,
            Err(_) => {
                bug!("failed to create graphviz node identified by {}", name());
            }
        }
    }
    fn node_label(&self, n: &Node) -> dot::LabelText {
        match *n {
            Node::RegionVid(n_vid) => dot::LabelText::label(format!("{:?}", n_vid)),
            Node::Region(n_rgn) => dot::LabelText::label(format!("{:?}", n_rgn)),
        }
    }
    fn edge_label(&self, e: &Edge) -> dot::LabelText {
        match *e {
            Edge::Constraint(ref c) =>
                dot::LabelText::label(format!("{:?}", self.map.get(c).unwrap())),
            Edge::EnclScope(..) => dot::LabelText::label(format!("(enclosed)")),
        }
    }
}

fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
    match *c {
        Constraint::ConstrainVarSubVar(rv_1, rv_2) =>
            (Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
        Constraint::ConstrainRegSubVar(r_1, rv_2) =>
            (Node::Region(*r_1), Node::RegionVid(rv_2)),
        Constraint::ConstrainVarSubReg(rv_1, r_2) =>
            (Node::RegionVid(rv_1), Node::Region(*r_2)),
        Constraint::ConstrainRegSubReg(r_1, r_2) =>
            (Node::Region(*r_1), Node::Region(*r_2)),
    }
}

fn edge_to_nodes(e: &Edge) -> (Node, Node) {
    match *e {
        Edge::Constraint(ref c) => constraint_to_nodes(c),
        Edge::EnclScope(sub, sup) => {
            (Node::Region(ty::ReScope(sub)),
             Node::Region(ty::ReScope(sup)))
        }
    }
}

impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
    type Node = Node;
    type Edge = Edge<'tcx>;
    fn nodes(&self) -> dot::Nodes<Node> {
        let mut set = FxHashSet();
        for node in self.node_ids.keys() {
            set.insert(*node);
        }
        debug!("constraint graph has {} nodes", set.len());
        set.into_iter().collect()
    }
    fn edges(&self) -> dot::Edges<Edge<'tcx>> {
        debug!("constraint graph has {} edges", self.map.len());
        let mut v: Vec<_> = self.map.keys().map(|e| Edge::Constraint(*e)).collect();
        self.region_rels.region_maps.each_encl_scope(|sub, sup| v.push(Edge::EnclScope(sub, sup)));
        debug!("region graph has {} edges", v.len());
        Cow::Owned(v)
    }
    fn source(&self, edge: &Edge<'tcx>) -> Node {
        let (n1, _) = edge_to_nodes(edge);
        debug!("edge {:?} has source {:?}", edge, n1);
        n1
    }
    fn target(&self, edge: &Edge<'tcx>) -> Node {
        let (_, n2) = edge_to_nodes(edge);
        debug!("edge {:?} has target {:?}", edge, n2);
        n2
    }
}

pub type ConstraintMap<'tcx> = FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;

fn dump_region_constraints_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
                                              map: &ConstraintMap<'tcx>,
                                              path: &str)
                                              -> io::Result<()> {
    debug!("dump_region_constraints map (len: {}) path: {}",
           map.len(),
           path);
    let g = ConstraintGraph::new(format!("region_constraints"), region_rels, map);
    debug!("dump_region_constraints calling render");
    let mut v = Vec::new();
    dot::render(&g, &mut v).unwrap();
    File::create(path).and_then(|mut f| f.write_all(&v))
}
<commit_msg>Remove leftover? of old code<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module provides linkage between libgraphviz traits and
//! `rustc::middle::typeck::infer::region_inference`, generating a
//! rendering of the graph represented by the list of `Constraint`
//! instances (which make up the edges of the graph), as well as the
//! origin for each constraint (which are attached to the labels on
//! each edge).

/// For clarity, rename the graphviz crate locally to dot.
use graphviz as dot;

use hir::def_id::DefIndex;
use ty;
use middle::free_region::RegionRelations;
use middle::region::CodeExtent;
use super::Constraint;
use infer::SubregionOrigin;
use infer::region_inference::RegionVarBindings;
use util::nodemap::{FxHashMap, FxHashSet};

use std::borrow::Cow;
use std::collections::hash_map::Entry::Vacant;
use std::env;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::sync::atomic::{AtomicBool, Ordering};

fn print_help_message() {
    println!("\
-Z print-region-graph by default prints a region constraint graph for every \n\
function body, to the path `/tmp/constraints.nodeXXX.dot`, where the XXX is \n\
replaced with the node id of the function under analysis.                   \n\
                                                                            \n\
To select one particular function body, set `RUST_REGION_GRAPH_NODE=XXX`,   \n\
where XXX is the node id desired.                                           \n\
                                                                            \n\
To generate output to some path other than the default                      \n\
`/tmp/constraints.nodeXXX.dot`, set `RUST_REGION_GRAPH=/path/desired.dot`;  \n\
occurrences of the character `%` in the requested path will be replaced with\n\
the node id of the function under analysis.                                 \n\
                                                                            \n\
(Since you requested help via RUST_REGION_GRAPH=help, no region constraint  \n\
graphs will be printed.                                                     \n\
");
}

pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
    region_vars: &RegionVarBindings<'a, 'gcx, 'tcx>,
    region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
{
    let context = region_rels.context;

    if !region_vars.tcx.sess.opts.debugging_opts.print_region_graph {
        return;
    }

    let requested_node = env::var("RUST_REGION_GRAPH_NODE")
        .ok().and_then(|s| s.parse().map(DefIndex::new).ok());

    if requested_node.is_some() && requested_node != Some(context.index) {
        return;
    }

    let requested_output = env::var("RUST_REGION_GRAPH");
    debug!("requested_output: {:?} requested_node: {:?}",
           requested_output,
           requested_node);

    let output_path = {
        let output_template = match requested_output {
            Ok(ref s) if s == "help" => {
                static PRINTED_YET: AtomicBool = AtomicBool::new(false);
                if !PRINTED_YET.load(Ordering::SeqCst) {
                    print_help_message();
                    PRINTED_YET.store(true, Ordering::SeqCst);
                }
                return;
            }

            Ok(other_path) => other_path,
            Err(_) => "/tmp/constraints.node%.dot".to_string(),
        };

        if output_template.is_empty() {
            panic!("empty string provided as RUST_REGION_GRAPH");
        }

        if output_template.contains('%') {
            let mut new_str = String::new();
            for c in output_template.chars() {
                if c == '%' {
                    new_str.push_str(&context.index.as_usize().to_string());
                } else {
                    new_str.push(c);
                }
            }
            new_str
        } else {
            output_template
        }
    };

    let constraints = &*region_vars.constraints.borrow();
    match dump_region_constraints_to(region_rels, constraints, &output_path) {
        Ok(()) => {}
        Err(e) => {
            let msg = format!("io error dumping region constraints: {}", e);
            region_vars.tcx.sess.err(&msg)
        }
    }
}

struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
    graph_name: String,
    region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
    map: &'a FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
    node_ids: FxHashMap<Node, usize>,
}

#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
enum Node {
    RegionVid(ty::RegionVid),
    Region(ty::RegionKind),
}

#[derive(Clone, PartialEq, Eq, Debug, Copy)]
enum Edge<'tcx> {
    Constraint(Constraint<'tcx>),
    EnclScope(CodeExtent, CodeExtent),
}

impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
    fn new(name: String,
           region_rels: &'a RegionRelations<'a, 'gcx, 'tcx>,
           map: &'a ConstraintMap<'tcx>)
           -> ConstraintGraph<'a, 'gcx, 'tcx> {
        let mut i = 0;
        let mut node_ids = FxHashMap();
        {
            let mut add_node = |node| {
                if let Vacant(e) = node_ids.entry(node) {
                    e.insert(i);
                    i += 1;
                }
            };

            for (n1, n2) in map.keys().map(|c| constraint_to_nodes(c)) {
                add_node(n1);
                add_node(n2);
            }

            region_rels.region_maps.each_encl_scope(|sub, sup| {
                add_node(Node::Region(ty::ReScope(sub)));
                add_node(Node::Region(ty::ReScope(sup)));
            });
        }

        ConstraintGraph {
            map,
            node_ids,
            region_rels,
            graph_name: name,
        }
    }
}

impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
    type Node = Node;
    type Edge = Edge<'tcx>;
    fn graph_id(&self) -> dot::Id {
        dot::Id::new(&*self.graph_name).unwrap()
    }
    fn node_id(&self, n: &Node) -> dot::Id {
        let node_id = match self.node_ids.get(n) {
            Some(node_id) => node_id,
            None => bug!("no node_id found for node: {:?}", n),
        };
        let name = || format!("node_{}", node_id);
        match dot::Id::new(name()) {
            Ok(id) => id,
            Err(_) => {
                bug!("failed to create graphviz node identified by {}", name());
            }
        }
    }
    fn node_label(&self, n: &Node) -> dot::LabelText {
        match *n {
            Node::RegionVid(n_vid) => dot::LabelText::label(format!("{:?}", n_vid)),
            Node::Region(n_rgn) => dot::LabelText::label(format!("{:?}", n_rgn)),
        }
    }
    fn edge_label(&self, e: &Edge) -> dot::LabelText {
        match *e {
            Edge::Constraint(ref c) =>
                dot::LabelText::label(format!("{:?}", self.map.get(c).unwrap())),
            Edge::EnclScope(..) => dot::LabelText::label(format!("(enclosed)")),
        }
    }
}

fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
    match *c {
        Constraint::ConstrainVarSubVar(rv_1, rv_2) =>
            (Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
        Constraint::ConstrainRegSubVar(r_1, rv_2) =>
            (Node::Region(*r_1), Node::RegionVid(rv_2)),
        Constraint::ConstrainVarSubReg(rv_1, r_2) =>
            (Node::RegionVid(rv_1), Node::Region(*r_2)),
        Constraint::ConstrainRegSubReg(r_1, r_2) =>
            (Node::Region(*r_1), Node::Region(*r_2)),
    }
}

fn edge_to_nodes(e: &Edge) -> (Node, Node) {
    match *e {
        Edge::Constraint(ref c) => constraint_to_nodes(c),
        Edge::EnclScope(sub, sup) => {
            (Node::Region(ty::ReScope(sub)),
             Node::Region(ty::ReScope(sup)))
        }
    }
}

impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
    type Node = Node;
    type Edge = Edge<'tcx>;
    fn nodes(&self) -> dot::Nodes<Node> {
        let mut set = FxHashSet();
        for node in self.node_ids.keys() {
            set.insert(*node);
        }
        debug!("constraint graph has {} nodes", set.len());
        set.into_iter().collect()
    }
    fn edges(&self) -> dot::Edges<Edge<'tcx>> {
        debug!("constraint graph has {} edges", self.map.len());
        let mut v: Vec<_> = self.map.keys().map(|e| Edge::Constraint(*e)).collect();
        self.region_rels.region_maps.each_encl_scope(|sub, sup| v.push(Edge::EnclScope(sub, sup)));
        debug!("region graph has {} edges", v.len());
        Cow::Owned(v)
    }
    fn source(&self, edge: &Edge<'tcx>) -> Node {
        let (n1, _) = edge_to_nodes(edge);
        debug!("edge {:?} has source {:?}", edge, n1);
        n1
    }
    fn target(&self, edge: &Edge<'tcx>) -> Node {
        let (_, n2) = edge_to_nodes(edge);
        debug!("edge {:?} has target {:?}", edge, n2);
        n2
    }
}

pub type ConstraintMap<'tcx> = FxHashMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;

fn dump_region_constraints_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
                                              map: &ConstraintMap<'tcx>,
                                              path: &str)
                                              -> io::Result<()> {
    debug!("dump_region_constraints map (len: {}) path: {}",
           map.len(),
           path);
    let g = ConstraintGraph::new(format!("region_constraints"), region_rels, map);
    debug!("dump_region_constraints calling render");
    let mut v = Vec::new();
    dot::render(&g, &mut v).unwrap();
    File::create(path).and_then(|mut f| f.write_all(&v))
}
<|endoftext|>


<commit_before>use std::fmt;

use super::tokenizer::Token;

#[derive(PartialEq, Clone, Debug)]
pub struct Assignment {
   name: String,
   value: Ast,
}

impl Assignment {
   pub fn new(name: String, value: Ast) -> Box<Self> {
      Box::new(
         Assignment {
            name: name,
            value: value
         }
      )
   }
}

pub type AssignmentBox = Box<Assignment>;

#[derive(PartialEq, Clone, Debug)]
pub struct List {
   contents: Vec<Ast>,
}

impl List {
   pub fn new(contents: Vec<Ast>) -> Box<Self> {
      Box::new(
         List {
            contents: contents
         }
      )
   }
}

pub type ListBox = Box<List>;

#[derive(PartialEq, Clone, Debug)]
pub struct Tuple {
   contents: Vec<Ast>,
}

impl Tuple {
   pub fn new(contents: Vec<Ast>) -> Box<Self> {
      Box::new(
         Tuple {
            contents: contents
         }
      )
   }
}

pub type TupleBox = Box<Tuple>;

#[derive(PartialEq, Clone, Debug)]
pub struct Function {
   name: String,
   arguments: Vec<Ast>,
}

impl Function {
   pub fn new(name: String, arguments: Vec<Ast>) -> Box<Self> {
      Box::new(
         Function {
            name: name,
            arguments: arguments,
         }
      )
   }
}

pub type FunctionBox = Box<Function>;

#[derive(PartialEq, Clone)]
pub enum BinaryType {
   Subtract,
   Add,
   Divide,
   Multiply,
}

impl fmt::Debug for BinaryType {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      match self {
         &BinaryType::Subtract => write!(f, "-"),
         &BinaryType::Add => write!(f, "+"),
         &BinaryType::Divide => write!(f, "/"),
         &BinaryType::Multiply => write!(f, "*"),
      }
   }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Binary {
   operator: BinaryType,
   left: Ast,
   right: Ast,
}

impl Binary {
   pub fn new(operator: BinaryType, left: Ast, right: Ast) -> Box<Self> {
      Box::new(
         Binary {
            operator: operator,
            left: left,
            right: right,
         }
      )
   }
}

pub type BinaryBox = Box<Binary>;

#[derive(PartialEq, Clone)]
pub enum Ast {
   Name(String),
   Integer(i64),
   Float(f64),
   Assignment(AssignmentBox),
   List(ListBox),
   Tuple(TupleBox),
   Function(FunctionBox),
   Binary(BinaryBox),
}

impl fmt::Debug for Ast {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      match self {
         &Ast::Name(ref value) => write!(f, "{}", value),
         &Ast::Integer(ref value) => write!(f, "{}", value),
         &Ast::Float(ref value) => write!(f, "{}", value),
         &Ast::Assignment(ref value) => write!(f, "{} = {:?}", value.name, value.value),
         &Ast::List(ref value) => write!(f, "{:?}", value.contents),
         &Ast::Tuple(ref value) => {
            let tuple_fmt = format!("{:?}", value.contents);
            write!(f, "({})", &tuple_fmt[1..tuple_fmt.len() - 1])
         },
         &Ast::Function(ref value) => write!(f, "{}!{:?}", value.name, value.arguments),
         &Ast::Binary(ref value) => write!(f, "({:?} {:?} {:?})", value.left, value.operator, value.right),
      }
   }
}

pub type AstResult = Option<(Ast, usize)>;

pub fn parse(tokens: Vec<Token>) -> Option<Vec<Ast>> {
   let mut assignments = Vec::new();

   let mut tokens = &tokens[..];

   loop {
      let taken = consume_new_line(tokens);
      tokens = &tokens[taken..];

      if let Some((ast, taken)) = parse_assignment(tokens) {
         tokens = &tokens[taken..];
         assignments.push(ast);
      } else {
         break;
      }
  }

   Some(assignments)
}

fn parse_assignment(tokens: &[Token]) -> AstResult {
   if tokens.len() < 4 {
      return None;
   }

   let name = match &tokens[0] {
      &Token::Name(ref name) => name,
      _ => return None,
   };

   if tokens[1] != Token::Assign {
      return None;
   }

   let next_new_line = find_next_new_line(tokens);

   let tokens = &tokens[2..next_new_line];

   if let Some(value) = match_value(tokens) {
      let assignment = Assignment::new(name.clone(), value);
      Some((Ast::Assignment(assignment), next_new_line + 1))
   } else {
      None
   }
}

fn match_value(tokens: &[Token]) -> Option<Ast> {
   if let Some(ast) = match_list(tokens) {
      Some(ast)
   } else if let Some(ast) = match_tuple_or_parenthesis(tokens) {
      Some(ast)
   } else if let Some(ast) = match_function(tokens) {
      Some(ast)
   } else if let Some(ast) = match_binary(tokens) {
      Some(ast)
   } else if let Some(ast) = match_single(tokens) {
      Some(ast)
   } else {
      None
   }
}

fn match_binary(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   let binary_types = [
      (Token::Subtract, BinaryType::Subtract),
      (Token::Add, BinaryType::Add),
      (Token::Divide, BinaryType::Divide),
      (Token::Multiply, BinaryType::Multiply),
   ];

   for binary_type in &binary_types {
      for middle in 1..tokens.len() - 1 {
         if binary_type.0 != tokens[middle] {
            continue;
         }

         if let Some(left) = match_value(&tokens[..middle]) {
            if let Some(right) = match_value(&tokens[middle + 1..]) {
               return Some(Ast::Binary(Binary::new(binary_type.1.clone(), left, right)));
            }
         }
      }
   }

   None
}

fn match_function(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   let name = match &tokens[0] {
      &Token::Name(ref name) => name,
      _ => return None,
   };

   if tokens[1] != Token::Not {
      return None;
   }

   let tokens = &tokens[2..];

   if let Some(contents) = match_sequence_contents(tokens) {
      Some(Ast::Function(Function::new(name.clone(), contents)))
   } else {
      None
   }
}

fn match_single(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() != 1 {
      return None;
   }

   match &tokens[0] {
      &Token::Name(ref value) => Some(Ast::Name(value.clone())),
      &Token::Integer(ref value) => Some(Ast::Integer(*value)),
      &Token::Float(ref value) => Some(Ast::Float(*value)),
      _ => None
   }
}

fn match_list(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   if tokens[0] != Token::BracketLeft {
      return None;
   }

   if tokens[tokens.len() - 1] != Token::BracketRight {
      return None;
   }

   let tokens = &tokens[1..tokens.len() - 1];

   if let Some(contents) = match_sequence_contents(tokens) {
      Some(Ast::List(List::new(contents)))
   } else {
      None
   }
}

fn match_tuple_or_parenthesis(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   if tokens[0] != Token::ParenLeft {
      return None;
   }

   if tokens[tokens.len() - 1] != Token::ParenRight {
      return None;
   }

   let tokens = &tokens[1..tokens.len() - 1];

   if let Some(ast) = match_value(tokens) {
      Some(ast)
   } else if let Some(contents) = match_sequence_contents(tokens) {
      Some(Ast::Tuple(Tuple::new(contents)))
   } else {
      None
   }
}

fn match_sequence_contents(tokens: &[Token]) -> Option<Vec<Ast>> {
   let mut contents = Vec::new();
   let mut tokens = tokens;

   loop {
      if tokens.len() == 0 {
         return Some(contents);
      }

      match try_list_item(tokens) {
         Some((ast, end)) => {
            contents.push(ast);
            tokens = &tokens[end..];
         },
         None => return None
      }
   }
}

fn try_list_item(tokens: &[Token]) -> AstResult {
   if tokens.len() == 0 {
      return None;
   }

   if let Some(end) = try_sequence(tokens, Token::BracketLeft, Token::BracketRight) {
      let tokens = &tokens[1..end];

      if let Some(contents) = match_sequence_contents(tokens) {
         return Some((Ast::List(List::new(contents)), end + 1));
      }

      return None;
   }

   if let Some(end) = try_sequence(tokens, Token::ParenLeft, Token::ParenRight) {
      let tokens = &tokens[1..end];

      if let Some(ast) = match_value(tokens) {
         return Some((ast, end + 1));
      }

      if let Some(contents) = match_sequence_contents(tokens) {
         return Some((Ast::Tuple(Tuple::new(contents)), end + 1));
      }

      return None;
   }

   if let Some(ast) = match_single(&tokens[..1]) {
      Some((ast, 1))
   } else {
      None
   }
}

fn try_sequence(tokens: &[Token], left: Token, right: Token) -> Option<usize> {
   if tokens.len() < 3 {
      return None;
   }

   if tokens[0] != left {
      return None;
   }

   let tokens = &tokens[1..];

   let mut start = 1;
   let mut end = 0;

   for (index, token) in tokens.iter().enumerate() {
      if *token == left {
         start += 1;
      } else if *token == right {
         end += 1;
      }

      if start == end {
         return Some(index + 1)
      }
   }

   None
}

fn find_next_new_line(tokens: &[Token]) -> usize {
   for (index, token) in tokens.iter().enumerate() {
      if let &Token::NewLine = token {
         return index;
      }
   }

   tokens.len()
}

fn consume_new_line(tokens: &[Token]) -> usize {
   for (index, token) in tokens.iter().enumerate() {
      match token {
         &Token::NewLine => {},
         _ => {
            return index;
         }
      }
   }

   tokens.len()
}
<commit_msg>Parser error detection<commit_after>use std::fmt;

use super::tokenizer::Token;

#[derive(PartialEq, Clone, Debug)]
pub struct Assignment {
   name: String,
   value: Ast,
}

impl Assignment {
   pub fn new(name: String, value: Ast) -> Box<Self> {
      Box::new(
         Assignment {
            name: name,
            value: value
         }
      )
   }
}

pub type AssignmentBox = Box<Assignment>;

#[derive(PartialEq, Clone, Debug)]
pub struct List {
   contents: Vec<Ast>,
}

impl List {
   pub fn new(contents: Vec<Ast>) -> Box<Self> {
      Box::new(
         List {
            contents: contents
         }
      )
   }
}

pub type ListBox = Box<List>;

#[derive(PartialEq, Clone, Debug)]
pub struct Tuple {
   contents: Vec<Ast>,
}

impl Tuple {
   pub fn new(contents: Vec<Ast>) -> Box<Self> {
      Box::new(
         Tuple {
            contents: contents
         }
      )
   }
}

pub type TupleBox = Box<Tuple>;

#[derive(PartialEq, Clone, Debug)]
pub struct Function {
   name: String,
   arguments: Vec<Ast>,
}

impl Function {
   pub fn new(name: String, arguments: Vec<Ast>) -> Box<Self> {
      Box::new(
         Function {
            name: name,
            arguments: arguments,
         }
      )
   }
}

pub type FunctionBox = Box<Function>;

#[derive(PartialEq, Clone)]
pub enum BinaryType {
   Subtract,
   Add,
   Divide,
   Multiply,
}

impl fmt::Debug for BinaryType {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      match self {
         &BinaryType::Subtract => write!(f, "-"),
         &BinaryType::Add => write!(f, "+"),
         &BinaryType::Divide => write!(f, "/"),
         &BinaryType::Multiply => write!(f, "*"),
      }
   }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Binary {
   operator: BinaryType,
   left: Ast,
   right: Ast,
}

impl Binary {
   pub fn new(operator: BinaryType, left: Ast, right: Ast) -> Box<Self> {
      Box::new(
         Binary {
            operator: operator,
            left: left,
            right: right,
         }
      )
   }
}

pub type BinaryBox = Box<Binary>;

#[derive(PartialEq, Clone)]
pub enum Ast {
   Name(String),
   Integer(i64),
   Float(f64),
   Assignment(AssignmentBox),
   List(ListBox),
   Tuple(TupleBox),
   Function(FunctionBox),
   Binary(BinaryBox),
}

impl fmt::Debug for Ast {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      match self {
         &Ast::Name(ref value) => write!(f, "{}", value),
         &Ast::Integer(ref value) => write!(f, "{}", value),
         &Ast::Float(ref value) => write!(f, "{}", value),
         &Ast::Assignment(ref value) => write!(f, "{} = {:?}", value.name, value.value),
         &Ast::List(ref value) => write!(f, "{:?}", value.contents),
         &Ast::Tuple(ref value) => {
            let tuple_fmt = format!("{:?}", value.contents);
            write!(f, "({})", &tuple_fmt[1..tuple_fmt.len() - 1])
         },
         &Ast::Function(ref value) => write!(f, "{}!{:?}", value.name, value.arguments),
         &Ast::Binary(ref value) => write!(f, "({:?} {:?} {:?})", value.left, value.operator, value.right),
      }
   }
}

pub type AstResult = Option<(Ast, usize)>;

pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>, String> {
   let mut assignments = Vec::new();

   let mut tokens = &tokens[..];
   let mut new_lines = 0;

   loop {
      let taken = consume_new_line(tokens);

      new_lines += taken;
      tokens = &tokens[taken..];

      if let Some((ast, taken)) = parse_assignment(tokens) {
         tokens = &tokens[taken..];
         assignments.push(ast);
      } else {
         let taken = consume_new_line(tokens);

         tokens = &tokens[taken..];

         if tokens.len() == 0 {
            return Ok(assignments);
         } else {
            return Err(format!("Parse error at line {}", new_lines + 1));
         }
      }
   }
}

fn parse_assignment(tokens: &[Token]) -> AstResult {
   if tokens.len() < 4 {
      return None;
   }

   let name = match &tokens[0] {
      &Token::Name(ref name) => name,
      _ => return None,
   };

   if tokens[1] != Token::Assign {
      return None;
   }

   let next_new_line = find_next_new_line(tokens);

   let tokens = &tokens[2..next_new_line];

   if let Some(value) = match_value(tokens) {
      let assignment = Assignment::new(name.clone(), value);
      Some((Ast::Assignment(assignment), next_new_line))
   } else {
      None
   }
}

fn match_value(tokens: &[Token]) -> Option<Ast> {
   if let Some(ast) = match_list(tokens) {
      Some(ast)
   } else if let Some(ast) = match_tuple_or_parenthesis(tokens) {
      Some(ast)
   } else if let Some(ast) = match_function(tokens) {
      Some(ast)
   } else if let Some(ast) = match_binary(tokens) {
      Some(ast)
   } else if let Some(ast) = match_single(tokens) {
      Some(ast)
   } else {
      None
   }
}

fn match_binary(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   let binary_types = [
      (Token::Subtract, BinaryType::Subtract),
      (Token::Add, BinaryType::Add),
      (Token::Divide, BinaryType::Divide),
      (Token::Multiply, BinaryType::Multiply),
   ];

   for binary_type in &binary_types {
      for middle in 1..tokens.len() - 1 {
         if binary_type.0 != tokens[middle] {
            continue;
         }

         if let Some(left) = match_value(&tokens[..middle]) {
            if let Some(right) = match_value(&tokens[middle + 1..]) {
               return Some(Ast::Binary(Binary::new(binary_type.1.clone(), left, right)));
            }
         }
      }
   }

   None
}

fn match_function(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   let name = match &tokens[0] {
      &Token::Name(ref name) => name,
      _ => return None,
   };

   if tokens[1] != Token::Not {
      return None;
   }

   let tokens = &tokens[2..];

   if let Some(contents) = match_sequence_contents(tokens) {
      Some(Ast::Function(Function::new(name.clone(), contents)))
   } else {
      None
   }
}

fn match_single(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() != 1 {
      return None;
   }

   match &tokens[0] {
      &Token::Name(ref value) => Some(Ast::Name(value.clone())),
      &Token::Integer(ref value) => Some(Ast::Integer(*value)),
      &Token::Float(ref value) => Some(Ast::Float(*value)),
      _ => None
   }
}

fn match_list(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   if tokens[0] != Token::BracketLeft {
      return None;
   }

   if tokens[tokens.len() - 1] != Token::BracketRight {
      return None;
   }

   let tokens = &tokens[1..tokens.len() - 1];

   if let Some(contents) = match_sequence_contents(tokens) {
      Some(Ast::List(List::new(contents)))
   } else {
      None
   }
}

fn match_tuple_or_parenthesis(tokens: &[Token]) -> Option<Ast> {
   if tokens.len() < 3 {
      return None;
   }

   if tokens[0] != Token::ParenLeft {
      return None;
   }

   if tokens[tokens.len() - 1] != Token::ParenRight {
      return None;
   }

   let tokens = &tokens[1..tokens.len() - 1];

   if let Some(ast) = match_value(tokens) {
      Some(ast)
   } else if let Some(contents) = match_sequence_contents(tokens) {
      Some(Ast::Tuple(Tuple::new(contents)))
   } else {
      None
   }
}

fn match_sequence_contents(tokens: &[Token]) -> Option<Vec<Ast>> {
   let mut contents = Vec::new();
   let mut tokens = tokens;

   loop {
      if tokens.len() == 0 {
         return Some(contents);
      }

      match try_list_item(tokens) {
         Some((ast, end)) => {
            contents.push(ast);
            tokens = &tokens[end..];
         },
         None => return None
      }
   }
}

fn try_list_item(tokens: &[Token]) -> AstResult {
   if tokens.len() == 0 {
      return None;
   }

   if let Some(end) = try_sequence(tokens, Token::BracketLeft, Token::BracketRight) {
      let tokens = &tokens[1..end];

      if let Some(contents) = match_sequence_contents(tokens) {
         return Some((Ast::List(List::new(contents)), end + 1));
      }

      return None;
   }

   if let Some(end) = try_sequence(tokens, Token::ParenLeft, Token::ParenRight) {
      let tokens = &tokens[1..end];

      if let Some(ast) = match_value(tokens) {
         return Some((ast, end + 1));
      }

      if let Some(contents) = match_sequence_contents(tokens) {
         return Some((Ast::Tuple(Tuple::new(contents)), end + 1));
      }

      return None;
   }

   if let Some(ast) = match_single(&tokens[..1]) {
      Some((ast, 1))
   } else {
      None
   }
}

fn try_sequence(tokens: &[Token], left: Token, right: Token) -> Option<usize> {
   if tokens.len() < 3 {
      return None;
   }

   if tokens[0] != left {
      return None;
   }

   let tokens = &tokens[1..];

   let mut start = 1;
   let mut end = 0;

   for (index, token) in tokens.iter().enumerate() {
      if *token == left {
         start += 1;
      } else if *token == right {
         end += 1;
      }

      if start == end {
         return Some(index + 1)
      }
   }

   None
}

fn find_next_new_line(tokens: &[Token]) -> usize {
   for (index, token) in tokens.iter().enumerate() {
      if let &Token::NewLine = token {
         return index;
      }
   }

   tokens.len()
}

fn consume_new_line(tokens: &[Token]) -> usize {
   for (index, token) in tokens.iter().enumerate() {
      match token {
         &Token::NewLine => {},
         _ => {
            return index;
         }
      }
   }

   tokens.len()
}
<|endoftext|>


<commit_before>#![feature(const_fn)]
#![feature(global_allocator)]
#![feature(alloc)]
#![feature(allocator_api)]
#![feature(lang_items)]
#![no_std]

extern crate system;
extern crate spin;
extern crate alloc;
extern crate abi;

use spin::Mutex;
use abi::CAddr;

const PAGE_LENGTH: usize = 4096;

static ALLOCATOR: Mutex<Option<WatermarkAllocator>> = Mutex::new(None);

struct WatermarkAllocator {
    untyped_cap: CAddr,
    toplevel_table_cap: CAddr,
    page_cap: CAddr,
    page_start_addr: usize,
    watermark: usize,
}

pub unsafe fn setup_allocator(untyped_cap: CAddr, pt_cap: CAddr, page_start_addr: usize) {
    *ALLOCATOR.lock() = Some(WatermarkAllocator::new(untyped_cap, pt_cap, page_start_addr));
}

// http://os.phil-opp.com/kernel-heap.html#alignment

/// Align downwards. Returns the greatest x with alignment `align`
/// so that x <= addr. The alignment must be a power of 2.
pub fn align_down(addr: usize, align: usize) -> usize {
    if align.is_power_of_two() {
        addr & !(align - 1)
    } else if align == 0 {
        addr
    } else {
        panic!("`align` must be a power of 2");
    }
}

/// Align upwards. Returns the smallest x with alignment `align`
/// so that x >= addr. The alignment must be a power of 2.
pub fn align_up(addr: usize, align: usize) -> usize {
    align_down(addr + align - 1, align)
}

impl WatermarkAllocator {
    fn new(untyped_cap: CAddr, toplevel_table_cap: CAddr, page_start_addr: usize) -> Self {
        let page_cap = system::retype_raw_page_free(untyped_cap);
        system::map_raw_page_free(page_start_addr, untyped_cap, toplevel_table_cap, page_cap.clone());

        WatermarkAllocator {
            untyped_cap: untyped_cap,
            page_cap: page_cap,
            toplevel_table_cap: toplevel_table_cap,
            page_start_addr: page_start_addr,
            watermark: 0,
        }
    }

    pub fn allocate(&mut self, size: usize, align: usize) -> *mut u8 {
        let alloc_start = align_up(self.watermark, align);
        let ret = (self.page_start_addr + alloc_start) as *mut u8;

        let mut alloc_end = alloc_start.saturating_add(size);

        while alloc_end >= PAGE_LENGTH {
            self.page_cap = system::retype_raw_page_free(self.untyped_cap);
            self.page_start_addr += PAGE_LENGTH;
            system::map_raw_page_free(self.page_start_addr, self.untyped_cap, self.toplevel_table_cap, self.page_cap.clone());

            alloc_end -= PAGE_LENGTH;
        }

        self.watermark = alloc_end;
        ret
    }
}

#[global_allocator]
static WATER_ALLOCATOR: WaterAlloc = WaterAlloc;

use alloc::allocator::Layout;
use core::alloc::{GlobalAlloc, Opaque};

struct WaterAlloc;

unsafe impl<'a> GlobalAlloc for WaterAlloc {
    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
        ALLOCATOR.lock().as_mut().unwrap().allocate(layout.size(), layout.align()) as _
    }

    unsafe fn dealloc(&self, _pointer: *mut Opaque, _layout: Layout) { }
}

#[lang="oom"]
#[no_mangle]
pub fn rust_oom() -> ! {
    panic!("Out of memory");
}
<commit_msg>Panic in case allocator lock is not available<commit_after>#![feature(const_fn)]
#![feature(global_allocator)]
#![feature(alloc)]
#![feature(allocator_api)]
#![feature(lang_items)]
#![no_std]

#[macro_use]
extern crate system;
extern crate spin;
extern crate alloc;
extern crate abi;

use spin::Mutex;
use abi::CAddr;

const PAGE_LENGTH: usize = 4096;

static ALLOCATOR: Mutex<Option<WatermarkAllocator>> = Mutex::new(None);

struct WatermarkAllocator {
    untyped_cap: CAddr,
    toplevel_table_cap: CAddr,
    page_cap: CAddr,
    page_start_addr: usize,
    watermark: usize,
}

pub unsafe fn setup_allocator(untyped_cap: CAddr, pt_cap: CAddr, page_start_addr: usize) {
    let allocator = Some(WatermarkAllocator::new(untyped_cap, pt_cap, page_start_addr));
    let mut lock = ALLOCATOR.try_lock().unwrap();
    *lock = allocator;
}

// http://os.phil-opp.com/kernel-heap.html#alignment

/// Align downwards. Returns the greatest x with alignment `align`
/// so that x <= addr. The alignment must be a power of 2.
pub fn align_down(addr: usize, align: usize) -> usize {
    if align.is_power_of_two() {
        addr & !(align - 1)
    } else if align == 0 {
        addr
    } else {
        panic!("`align` must be a power of 2");
    }
}

/// Align upwards. Returns the smallest x with alignment `align`
/// so that x >= addr. The alignment must be a power of 2.
pub fn align_up(addr: usize, align: usize) -> usize {
    align_down(addr + align - 1, align)
}

impl WatermarkAllocator {
    fn new(untyped_cap: CAddr, toplevel_table_cap: CAddr, page_start_addr: usize) -> Self {
        let page_cap = system::retype_raw_page_free(untyped_cap);
        system::map_raw_page_free(page_start_addr, untyped_cap, toplevel_table_cap, page_cap.clone());

        WatermarkAllocator {
            untyped_cap: untyped_cap,
            page_cap: page_cap,
            toplevel_table_cap: toplevel_table_cap,
            page_start_addr: page_start_addr,
            watermark: 0,
        }
    }

    pub fn allocate(&mut self, size: usize, align: usize) -> *mut u8 {
        let alloc_start = align_up(self.watermark, align);
        let ret = (self.page_start_addr + alloc_start) as *mut u8;

        let mut alloc_end = alloc_start.saturating_add(size);

        while alloc_end >= PAGE_LENGTH {
            self.page_cap = system::retype_raw_page_free(self.untyped_cap);
            self.page_start_addr += PAGE_LENGTH;
            system::map_raw_page_free(self.page_start_addr, self.untyped_cap, self.toplevel_table_cap, self.page_cap.clone());

            alloc_end -= PAGE_LENGTH;
        }

        self.watermark = alloc_end;
        ret
    }
}

#[global_allocator]
static WATER_ALLOCATOR: WaterAlloc = WaterAlloc;

use alloc::allocator::Layout;
use core::alloc::{GlobalAlloc, Opaque};

struct WaterAlloc;

unsafe impl<'a> GlobalAlloc for WaterAlloc {
    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
        ALLOCATOR.lock().as_mut().unwrap().allocate(layout.size(), layout.align()) as _
    }

    unsafe fn dealloc(&self, _pointer: *mut Opaque, _layout: Layout) { }
}

#[lang="oom"]
#[no_mangle]
pub fn rust_oom() -> ! {
    panic!("Out of memory");
}
<|endoftext|>


<commit_before>#![cfg(feature = "sqs")]

extern crate env_logger;
extern crate rand;
extern crate rusoto_core;
extern crate rusoto_sqs;
extern crate time;

use std::collections::HashMap;
use std::time::Duration;

use rusoto_core::Region;
use rusoto_sqs::{CreateQueueRequest, GetQueueUrlRequest, ListQueuesRequest, SendMessageRequest};
use rusoto_sqs::{
    DeleteMessageBatchRequest, DeleteMessageBatchRequestEntry, SendMessageBatchRequest,
    SendMessageBatchRequestEntry,
};
use rusoto_sqs::{
    DeleteMessageRequest, DeleteQueueRequest, GetQueueAttributesRequest, ReceiveMessageRequest,
};
use rusoto_sqs::{Sqs, SqsClient};

#[tokio::test]
async fn list_queues() {
    let sqs = SqsClient::new(Region::UsEast1);

    let request = ListQueuesRequest {
        ..Default::default()
    };

    let result = sqs.list_queues(request).await.expect("List queues failed");
    println!("{:#?}", result);
}

#[tokio::test]
async fn sqs_roundtrip_tests() {
    let _ = env_logger::try_init();
    let sqs = SqsClient::new(Region::UsEast1);

    // create a new queue
    let q_name = &format!("test_q_{}", rand::random::<u64>());
    let mut attrs = HashMap::new();
    attrs.insert(
        String::from("ReceiveMessageWaitTimeSeconds"),
        String::from("1"),
    );
    let q_creation_req = CreateQueueRequest {
        attributes: Some(attrs),
        queue_name: q_name.clone(),
        ..Default::default()
    };

    let response = sqs
        .create_queue(q_creation_req)
        .await
        .expect("Create queue failed");
    println!(
        "Created queue {} with url {}",
        q_name,
        response
            .queue_url
            .clone()
            .expect("Queue url wasn't available in response")
    );
    // q_url_from_aws looks like https://sqs.us-east-1.amazonaws.com/acct_id_here/test_q_1495776719
    assert!(response.queue_url.unwrap().clone().ends_with(q_name));

    // query it by name
    let get_q_by_name_request = GetQueueUrlRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };
    let response = sqs
        .get_queue_url(get_q_by_name_request)
        .await
        .expect("Get queue by URL request failed");
    let queue_url = &response
        .queue_url
        .expect("Queue url should be available from list queues");
    println!(
        "Verified queue url {} for queue name {}",
        queue_url.clone(),
        q_name
    );

    // queue attributes
    let queue_attributes_req = GetQueueAttributesRequest {
        queue_url: queue_url.clone(),
        attribute_names: Some(vec!["All".to_string()]),
    };
    match sqs.get_queue_attributes(queue_attributes_req).await {
        Ok(result) => println!("Queue attributes: {:?}", result),
        Err(e) => panic!("Error getting queue attributes: {:?}", e),
    }

    // send it a message
    let msg_str = String::from("lorem ipsum dolor sit amet");
    let send_msg_request = SendMessageRequest {
        message_body: msg_str.clone(),
        queue_url: queue_url.clone(),
        ..Default::default()
    };
    let response = sqs.send_message(send_msg_request).await;
    println!(
        "Sent message with body '{}' and created message_id {}",
        msg_str,
        response.unwrap().message_id.unwrap()
    );

    // message_attribute_names is for testing https://github.com/rusoto/rusoto/issues/586
    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        message_attribute_names: Some(vec!["All".to_string()]),
        ..Default::default()
    };

    let response = sqs.receive_message(receive_request).await;
    for msg in response
        .expect("Expected to have a receive message response")
        .messages
        .expect("message should be available")
    {
        println!(
            "Received message '{}' with id {}",
            msg.body.clone().unwrap(),
            msg.message_id.clone().unwrap()
        );
        println!("Receipt handle is {:?}", msg.receipt_handle);

        assert!(msg.body.unwrap().eq(&msg_str));

        let delete_message_request = DeleteMessageRequest {
            queue_url: queue_url.clone(),
            receipt_handle: msg.receipt_handle.clone().unwrap(),
        };
        match sqs.delete_message(delete_message_request).await {
            Ok(_) => println!(
                "Deleted message via receipt handle {:?}",
                msg.receipt_handle
            ),
            Err(e) => panic!("Couldn't delete message: {:?}", e),
        }
    }

    let queue_deletion_req = DeleteQueueRequest {
        queue_url: queue_url.clone(),
    };
    match sqs.delete_queue(queue_deletion_req).await {
        Ok(_) => (),
        Err(e) => panic!("Couldn't delete queue: {:?}", e),
    }
    println!("Queue {} deleted", queue_url.clone());
}

#[tokio::test]
async fn sqs_timeout_test() {
    let _ = env_logger::try_init();
    let sqs = SqsClient::new(Region::UsEast1);

    let q_name = &format!("test_q_{}", rand::random::<u64>());

    let q_creation_req = CreateQueueRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };
    let response = sqs
        .create_queue(q_creation_req)
        .await
        .expect("create queue failed");
    let queue_url = response.queue_url.unwrap();
    assert!(queue_url.ends_with(q_name));

    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        wait_time_seconds: Some(10),
        ..Default::default()
    };
    let result = tokio::time::timeout(Duration::from_secs(2), sqs
        .receive_message(receive_request))
        .await;
    println!("sqs receive result: {:?}", result);

    let err = result.err().expect("receive did not fail as expected");
    assert!(err.to_string().find("Request timed out").is_some());

    let queue_deletion_req = DeleteQueueRequest {
        queue_url: queue_url.clone(),
    };
    sqs.delete_queue(queue_deletion_req)
        .await
        .expect("delete queue failed");
}

#[tokio::test]
async fn sqs_bulk_roundtrip_tests() {
    let _ = env_logger::try_init();
    let sqs = SqsClient::new(Region::UsEast1);

    // create a new queue
    let q_name = &format!("test_q_{}", rand::random::<u64>());
    let q_creation_req = CreateQueueRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };

    let response = sqs
        .create_queue(q_creation_req)
        .await
        .expect("Create queue failed");
    println!(
        "Created queue {} with url {}",
        q_name,
        response
            .queue_url
            .clone()
            .expect("Queue url wasn't available in response")
    );
    // q_url_from_aws looks like https://sqs.us-east-1.amazonaws.com/acct_id_here/test_q_1495776719
    assert!(response.queue_url.unwrap().clone().ends_with(q_name));

    // query it by name
    let get_q_by_name_request = GetQueueUrlRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };
    let response = sqs
        .get_queue_url(get_q_by_name_request)
        .await
        .expect("Get queue by URL request failed");
    let queue_url = &response
        .queue_url
        .expect("Queue url should be available from list queues");
    println!(
        "Verified queue url {} for queue name {}",
        queue_url.clone(),
        q_name
    );

    // queue attributes
    let queue_attributes_req = GetQueueAttributesRequest {
        queue_url: queue_url.clone(),
        attribute_names: Some(vec!["All".to_string()]),
    };
    match sqs.get_queue_attributes(queue_attributes_req).await {
        Ok(result) => println!("Queue attributes: {:?}", result),
        Err(e) => panic!("Error getting queue attributes: {:?}", e),
    }

    // send it a message
    let msg_str = String::from("lorem ipsum dolor sit amet");
    let send_msg_request_entry_1 = SendMessageBatchRequestEntry {
        message_body: msg_str.clone(),
        id: "1".to_string(),
        ..Default::default()
    };
    let send_msg_request_entry_2 = SendMessageBatchRequestEntry {
        message_body: msg_str.clone(),
        id: "2".to_string(),
        ..Default::default()
    };
    let send_msg_request = SendMessageBatchRequest {
        queue_url: queue_url.clone(),
        entries: vec![send_msg_request_entry_1, send_msg_request_entry_2],
        ..Default::default()
    };
    let response = sqs.send_message_batch(send_msg_request).await;
    println!(
        "Sent message with body '{}' and created messages {:?}",
        msg_str,
        response.unwrap()
    );

    // message_attribute_names is for testing https://github.com/rusoto/rusoto/issues/586
    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        message_attribute_names: Some(vec!["All".to_string()]),
        ..Default::default()
    };

    let response = sqs.receive_message(receive_request).await;
    let mut delete_entries: Vec<DeleteMessageBatchRequestEntry> = Vec::new();
    for msg in response
        .expect("Expected to have a receive message response")
        .messages
        .expect("message should be available")
    {
        println!(
            "Received message '{}' with id {}",
            msg.body.clone().unwrap(),
            msg.message_id.clone().unwrap()
        );

        assert!(msg.body.unwrap().eq(&msg_str));
        delete_entries.push(DeleteMessageBatchRequestEntry {
            receipt_handle: msg.receipt_handle.clone().unwrap(),
            id: msg.message_id.clone().unwrap(),
        });
    }
    let delete_message_request = DeleteMessageBatchRequest {
        queue_url: queue_url.clone(),
        entries: delete_entries.clone(),
    };
    match sqs.delete_message_batch(delete_message_request).await {
        Ok(_) => println!("Deleted messages via receipt handle {:?}", delete_entries),
        Err(e) => panic!("Couldn't delete message: {:?}", e),
    }

    let queue_deletion_req = DeleteQueueRequest {
        queue_url: queue_url.clone(),
    };
    match sqs.delete_queue(queue_deletion_req).await {
        Ok(_) => (),
        Err(e) => panic!("Couldn't delete queue: {:?}", e),
    }
    println!("Queue {} deleted", queue_url.clone());
}
<commit_msg>Remove error string check in SQS integ tests<commit_after>#![cfg(feature = "sqs")]

extern crate env_logger;
extern crate rand;
extern crate rusoto_core;
extern crate rusoto_sqs;
extern crate time;

use std::collections::HashMap;
use std::time::Duration;

use rusoto_core::Region;
use rusoto_sqs::{CreateQueueRequest, GetQueueUrlRequest, ListQueuesRequest, SendMessageRequest};
use rusoto_sqs::{
    DeleteMessageBatchRequest, DeleteMessageBatchRequestEntry, SendMessageBatchRequest,
    SendMessageBatchRequestEntry,
};
use rusoto_sqs::{
    DeleteMessageRequest, DeleteQueueRequest, GetQueueAttributesRequest, ReceiveMessageRequest,
};
use rusoto_sqs::{Sqs, SqsClient};

#[tokio::test]
async fn list_queues() {
    let sqs = SqsClient::new(Region::UsEast1);

    let request = ListQueuesRequest {
        ..Default::default()
    };

    let result = sqs.list_queues(request).await.expect("List queues failed");
    println!("{:#?}", result);
}

#[tokio::test]
async fn sqs_roundtrip_tests() {
    let _ = env_logger::try_init();
    let sqs = SqsClient::new(Region::UsEast1);

    // create a new queue
    let q_name = &format!("test_q_{}", rand::random::<u64>());
    let mut attrs = HashMap::new();
    attrs.insert(
        String::from("ReceiveMessageWaitTimeSeconds"),
        String::from("1"),
    );
    let q_creation_req = CreateQueueRequest {
        attributes: Some(attrs),
        queue_name: q_name.clone(),
        ..Default::default()
    };

    let response = sqs
        .create_queue(q_creation_req)
        .await
        .expect("Create queue failed");
    println!(
        "Created queue {} with url {}",
        q_name,
        response
            .queue_url
            .clone()
            .expect("Queue url wasn't available in response")
    );
    // q_url_from_aws looks like https://sqs.us-east-1.amazonaws.com/acct_id_here/test_q_1495776719
    assert!(response.queue_url.unwrap().clone().ends_with(q_name));

    // query it by name
    let get_q_by_name_request = GetQueueUrlRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };
    let response = sqs
        .get_queue_url(get_q_by_name_request)
        .await
        .expect("Get queue by URL request failed");
    let queue_url = &response
        .queue_url
        .expect("Queue url should be available from list queues");
    println!(
        "Verified queue url {} for queue name {}",
        queue_url.clone(),
        q_name
    );

    // queue attributes
    let queue_attributes_req = GetQueueAttributesRequest {
        queue_url: queue_url.clone(),
        attribute_names: Some(vec!["All".to_string()]),
    };
    match sqs.get_queue_attributes(queue_attributes_req).await {
        Ok(result) => println!("Queue attributes: {:?}", result),
        Err(e) => panic!("Error getting queue attributes: {:?}", e),
    }

    // send it a message
    let msg_str = String::from("lorem ipsum dolor sit amet");
    let send_msg_request = SendMessageRequest {
        message_body: msg_str.clone(),
        queue_url: queue_url.clone(),
        ..Default::default()
    };
    let response = sqs.send_message(send_msg_request).await;
    println!(
        "Sent message with body '{}' and created message_id {}",
        msg_str,
        response.unwrap().message_id.unwrap()
    );

    // message_attribute_names is for testing https://github.com/rusoto/rusoto/issues/586
    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        message_attribute_names: Some(vec!["All".to_string()]),
        ..Default::default()
    };

    let response = sqs.receive_message(receive_request).await;
    for msg in response
        .expect("Expected to have a receive message response")
        .messages
        .expect("message should be available")
    {
        println!(
            "Received message '{}' with id {}",
            msg.body.clone().unwrap(),
            msg.message_id.clone().unwrap()
        );
        println!("Receipt handle is {:?}", msg.receipt_handle);

        assert!(msg.body.unwrap().eq(&msg_str));

        let delete_message_request = DeleteMessageRequest {
            queue_url: queue_url.clone(),
            receipt_handle: msg.receipt_handle.clone().unwrap(),
        };
        match sqs.delete_message(delete_message_request).await {
            Ok(_) => println!(
                "Deleted message via receipt handle {:?}",
                msg.receipt_handle
            ),
            Err(e) => panic!("Couldn't delete message: {:?}", e),
        }
    }

    let queue_deletion_req = DeleteQueueRequest {
        queue_url: queue_url.clone(),
    };
    match sqs.delete_queue(queue_deletion_req).await {
        Ok(_) => (),
        Err(e) => panic!("Couldn't delete queue: {:?}", e),
    }
    println!("Queue {} deleted", queue_url.clone());
}

#[tokio::test]
async fn sqs_timeout_test() {
    let _ = env_logger::try_init();
    let sqs = SqsClient::new(Region::UsEast1);

    let q_name = &format!("test_q_{}", rand::random::<u64>());

    let q_creation_req = CreateQueueRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };
    let response = sqs
        .create_queue(q_creation_req)
        .await
        .expect("create queue failed");
    let queue_url = response.queue_url.unwrap();
    assert!(queue_url.ends_with(q_name));

    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        wait_time_seconds: Some(10),
        ..Default::default()
    };
    let result = tokio::time::timeout(Duration::from_secs(2), sqs
        .receive_message(receive_request))
        .await;
    println!("sqs receive result: {:?}", result);

    result.err().expect("receive did not fail as expected");

    let queue_deletion_req = DeleteQueueRequest {
        queue_url: queue_url.clone(),
    };
    sqs.delete_queue(queue_deletion_req)
        .await
        .expect("delete queue failed");
}

#[tokio::test]
async fn sqs_bulk_roundtrip_tests() {
    let _ = env_logger::try_init();
    let sqs = SqsClient::new(Region::UsEast1);

    // create a new queue
    let q_name = &format!("test_q_{}", rand::random::<u64>());
    let q_creation_req = CreateQueueRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };

    let response = sqs
        .create_queue(q_creation_req)
        .await
        .expect("Create queue failed");
    println!(
        "Created queue {} with url {}",
        q_name,
        response
            .queue_url
            .clone()
            .expect("Queue url wasn't available in response")
    );
    // q_url_from_aws looks like https://sqs.us-east-1.amazonaws.com/acct_id_here/test_q_1495776719
    assert!(response.queue_url.unwrap().clone().ends_with(q_name));

    // query it by name
    let get_q_by_name_request = GetQueueUrlRequest {
        queue_name: q_name.clone(),
        ..Default::default()
    };
    let response = sqs
        .get_queue_url(get_q_by_name_request)
        .await
        .expect("Get queue by URL request failed");
    let queue_url = &response
        .queue_url
        .expect("Queue url should be available from list queues");
    println!(
        "Verified queue url {} for queue name {}",
        queue_url.clone(),
        q_name
    );

    // queue attributes
    let queue_attributes_req = GetQueueAttributesRequest {
        queue_url: queue_url.clone(),
        attribute_names: Some(vec!["All".to_string()]),
    };
    match sqs.get_queue_attributes(queue_attributes_req).await {
        Ok(result) => println!("Queue attributes: {:?}", result),
        Err(e) => panic!("Error getting queue attributes: {:?}", e),
    }

    // send it a message
    let msg_str = String::from("lorem ipsum dolor sit amet");
    let send_msg_request_entry_1 = SendMessageBatchRequestEntry {
        message_body: msg_str.clone(),
        id: "1".to_string(),
        ..Default::default()
    };
    let send_msg_request_entry_2 = SendMessageBatchRequestEntry {
        message_body: msg_str.clone(),
        id: "2".to_string(),
        ..Default::default()
    };
    let send_msg_request = SendMessageBatchRequest {
        queue_url: queue_url.clone(),
        entries: vec![send_msg_request_entry_1, send_msg_request_entry_2],
        ..Default::default()
    };
    let response = sqs.send_message_batch(send_msg_request).await;
    println!(
        "Sent message with body '{}' and created messages {:?}",
        msg_str,
        response.unwrap()
    );

    // message_attribute_names is for testing https://github.com/rusoto/rusoto/issues/586
    let receive_request = ReceiveMessageRequest {
        queue_url: queue_url.clone(),
        message_attribute_names: Some(vec!["All".to_string()]),
        ..Default::default()
    };

    let response = sqs.receive_message(receive_request).await;
    let mut delete_entries: Vec<DeleteMessageBatchRequestEntry> = Vec::new();
    for msg in response
        .expect("Expected to have a receive message response")
        .messages
        .expect("message should be available")
    {
        println!(
            "Received message '{}' with id {}",
            msg.body.clone().unwrap(),
            msg.message_id.clone().unwrap()
        );

        assert!(msg.body.unwrap().eq(&msg_str));
        delete_entries.push(DeleteMessageBatchRequestEntry {
            receipt_handle: msg.receipt_handle.clone().unwrap(),
            id: msg.message_id.clone().unwrap(),
        });
    }
    let delete_message_request = DeleteMessageBatchRequest {
        queue_url: queue_url.clone(),
        entries: delete_entries.clone(),
    };
    match sqs.delete_message_batch(delete_message_request).await {
        Ok(_) => println!("Deleted messages via receipt handle {:?}", delete_entries),
        Err(e) => panic!("Couldn't delete message: {:?}", e),
    }

    let queue_deletion_req = DeleteQueueRequest {
        queue_url: queue_url.clone(),
    };
    match sqs.delete_queue(queue_deletion_req).await {
        Ok(_) => (),
        Err(e) => panic!("Couldn't delete queue: {:?}", e),
    }
    println!("Queue {} deleted", queue_url.clone());
}
<|endoftext|>


<commit_before>pub mod message;

use std::net::TcpStream;
use std::io;
use std::io::{BufReader, Write, BufRead, Error};
use irc::message::{Message, MessageError};

/// Represents an error caused by reading a [`Message`] from the server.
/// [`Message`]: message/enum.Message.html
#[derive(Debug)]
pub enum ReadLineError {
    /// The error is related to the connection.
    Connection(Error),
    /// The error is related to the attempt to parse the message received from the server.
    Message(MessageError),
}

/// Represents a TCP connection to an IRC server.
pub struct Connection {
    /// Utility field to allow easy reading from the server.
    reader: BufReader<TcpStream>,
}

impl Connection {
    /// Connects to the specified IRC server.
    pub fn new(host: &str) -> Result<Connection, io::Error> {
        let socket = TcpStream::connect(host)?;
        Ok(Connection {
            reader: BufReader::new(socket)
        })
    }

    /// Sends login credentials to the IRC server.
    pub fn login(&mut self, username: &str, oauth: &str) -> Result<(), io::Error> {
        let mut socket = self.reader.get_mut();

        writeln!(socket, "USER {} 0 * :{}", username, username)?;
        writeln!(socket, "PASS {}", oauth)?;
        writeln!(socket, "NICK {}", username)?;
        writeln!(socket, "CAP REQ :twitch.tv/membership")?;

        Ok(())
    }

    /// Sends a `&str` to the IRC server immediately.
    pub fn write_line(&mut self, string: &str) -> Result<(), io::Error> {
        let socket = self.reader.get_mut();
        writeln!(socket, "{}", string)?;
        socket.flush()
    }

    /// Reads a line directly from the connected server.
    pub fn read_line_raw(&mut self) -> Result<String, Error> {
        let mut line = String::new();
        self.reader.read_line(&mut line)?;

        Ok(line)
    }

    /// Reads a line from the server and parses a [`Message`] from it.
    /// [`Message`]: message/enum.Message.html
    pub fn read_line(&mut self) -> Result<Message, ReadLineError> {
        match self.read_line_raw() {
            Ok(line) => {
                match Message::parse(&line) {
                    Ok(msg)  => Ok(msg),
                    Err(err) => Err(ReadLineError::Message(err)),
                }
            },
            Err(err) => Err(ReadLineError::Connection(err)),
        }
    }
}<commit_msg>Simplify error handling<commit_after>pub mod message;

use std::net::TcpStream;
use std::io;
use std::io::{BufReader, Write, BufRead, Error};
use irc::message::{Message, MessageError};

/// Represents an error caused by reading a [`Message`] from the server.
/// [`Message`]: message/enum.Message.html
#[derive(Debug)]
pub enum ReadLineError {
    /// The error is related to the connection.
    Connection(Error),
    /// The error is related to the attempt to parse the message received from the server.
    Message(MessageError),
}

/// Represents a TCP connection to an IRC server.
pub struct Connection {
    /// Utility field to allow easy reading from the server.
    reader: BufReader<TcpStream>,
}

impl Connection {
    /// Connects to the specified IRC server.
    pub fn new(host: &str) -> Result<Connection, io::Error> {
        let socket = TcpStream::connect(host)?;
        Ok(Connection {
            reader: BufReader::new(socket)
        })
    }

    /// Sends login credentials to the IRC server.
    pub fn login(&mut self, username: &str, oauth: &str) -> Result<(), io::Error> {
        let mut socket = self.reader.get_mut();

        writeln!(socket, "USER {} 0 * :{}", username, username)?;
        writeln!(socket, "PASS {}", oauth)?;
        writeln!(socket, "NICK {}", username)?;
        writeln!(socket, "CAP REQ :twitch.tv/membership")?;

        Ok(())
    }

    /// Sends a `&str` to the IRC server immediately.
    pub fn write_line(&mut self, string: &str) -> Result<(), io::Error> {
        let socket = self.reader.get_mut();
        writeln!(socket, "{}", string)?;
        socket.flush()
    }

    /// Reads a line directly from the connected server.
    pub fn read_line_raw(&mut self) -> Result<String, Error> {
        let mut line = String::new();
        self.reader.read_line(&mut line)?;

        Ok(line)
    }

    /// Reads a line from the server and parses a [`Message`] from it.
    /// [`Message`]: message/enum.Message.html
    pub fn read_line(&mut self) -> Result<Message, ReadLineError> {
        match self.read_line_raw() {
            Ok(line) => Message::parse(&line).map_err(ReadLineError::Message),
            Err(err) => Err(ReadLineError::Connection(err)),
        }
    }
}<|endoftext|>


<commit_before>export ptr_eq;

#[doc(
  brief = "Determine if two shared boxes point to the same object"
)]
pure fn ptr_eq<T>(a: @T, b: @T) -> bool {
    // FIXME: ptr::addr_of
    unsafe {
        let a_ptr: uint = unsafe::reinterpret_cast(a);
        let b_ptr: uint = unsafe::reinterpret_cast(b);
        ret a_ptr == b_ptr;
    }
}

#[test]
fn test() {
    let x = @3;
    let y = @3;
    assert (ptr_eq::<int>(x, x));
    assert (ptr_eq::<int>(y, y));
    assert (!ptr_eq::<int>(x, y));
    assert (!ptr_eq::<int>(y, x));
}
<commit_msg>core: Resolve a FIXME in box::ptr_eq<commit_after>export ptr_eq;

#[doc(
  brief = "Determine if two shared boxes point to the same object"
)]
pure fn ptr_eq<T>(a: @T, b: @T) -> bool unchecked {
    ptr::addr_of(*a) == ptr::addr_of(*b)
}

#[test]
fn test() {
    let x = @3;
    let y = @3;
    assert (ptr_eq::<int>(x, x));
    assert (ptr_eq::<int>(y, y));
    assert (!ptr_eq::<int>(x, y));
    assert (!ptr_eq::<int>(y, x));
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use layout::{PointerBuilder, PointerReader};
use common::Word;

pub trait FromPointerReader<'a> {
    fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Self;
}

pub trait FromPointerBuilder<'a> {
    fn init_pointer(PointerBuilder<'a>, uint) -> Self;
    fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Self;
}

pub mod PrimitiveList {
    use super::{FromPointerReader, FromPointerBuilder};
    use layout::{ListReader, ListBuilder, PointerReader, PointerBuilder,
                 PrimitiveElement, POINTER};
    use common::Word;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T : PrimitiveElement> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }
    }

    impl <'a, T : PrimitiveElement> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(POINTER, default_value) }
        }
    }

    impl <'a, T : PrimitiveElement> Index<uint, T> for Reader<'a, T> {
        fn index(&self, index : &uint) -> T {
            PrimitiveElement::get(&self.reader, *index)
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : PrimitiveElement> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }

        pub fn set(&self, index : uint, value : T) {
            PrimitiveElement::set(&self.builder, index, value);
        }
    }

    impl <'a, T : PrimitiveElement> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(_builder : PointerBuilder<'a>, _size : uint) -> Builder<'a, T> {
//            builder.init_list(
            fail!();
        }
        fn get_from_pointer(_builder : PointerBuilder<'a>, _default_value : *Word) -> Builder<'a, T> {
            fail!();
        }
    }

    impl <'a, T : PrimitiveElement> Index<uint, T> for Builder<'a, T> {
        fn index(&self, index : &uint) -> T {
            PrimitiveElement::get_from_builder(&self.builder, *index)
        }
    }
}

pub trait ToU16 {
    fn to_u16(self) -> u16;
}

pub mod EnumList {
    use layout::*;
    use list::*;
    use common::Word;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T : FromPrimitive> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }

    }

    impl <'a, T : FromPrimitive> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(TWO_BYTES, default_value) }
        }
    }

    impl <'a, T : FromPrimitive> Index<uint, Option<T>> for Reader<'a, T> {
        fn index(&self, index : &uint) -> Option<T> {
            let result : u16 = PrimitiveElement::get(&self.reader, *index);
            FromPrimitive::from_u16(result)
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : ToU16 + FromPrimitive> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }

        pub fn set(&self, index : uint, value : T) {
            PrimitiveElement::set(&self.builder, index, value.to_u16());
        }
    }

    impl <'a, T : FromPrimitive> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(builder : PointerBuilder<'a>, size : uint) -> Builder<'a, T> {
            Builder { builder : builder.init_list(TWO_BYTES, size) }
        }
        fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Builder<'a, T> {
            Builder { builder : builder.get_list(TWO_BYTES, default_value) }
        }
    }

    impl <'a, T : ToU16 + FromPrimitive> Index<uint, Option<T>> for Builder<'a, T> {
        fn index(&self, index : &uint) -> Option<T> {
            let result : u16 = PrimitiveElement::get_from_builder(&self.builder, *index);
            FromPrimitive::from_u16(result)
        }
    }
}

pub mod StructList {
    use super::{FromPointerReader, FromPointerBuilder};
    use common::Word;
    use layout::*;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T : FromStructReader<'a>> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }
    }

    impl <'a, T : FromStructReader<'a>> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(INLINE_COMPOSITE, default_value) }
        }
    }

    impl <'a, T : FromStructReader<'a>> Index<uint, T> for Reader<'a, T> {
        fn index(&self, index : &uint) -> T {
            let result : T = FromStructReader::from_struct_reader(self.reader.get_struct_element(*index));
            result
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : FromStructBuilder<'a>> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }

//        pub fn set(&self, index : uint, value : T) {
//        }
    }

    impl <'a, T : FromStructBuilder<'a> + HasStructSize> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(builder : PointerBuilder<'a>, size : uint) -> Builder<'a, T> {
            Builder {
                builder : builder.init_struct_list(size, HasStructSize::struct_size(None::<T>))
            }
        }
        fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Builder<'a, T> {
            Builder {
                builder : builder.get_struct_list(HasStructSize::struct_size(None::<T>), default_value)
            }
        }
    }

    impl <'a, T : FromStructBuilder<'a>> Index<uint, T> for Builder<'a, T> {
        fn index(&self, index : &uint) -> T {
            let result : T =
                FromStructBuilder::from_struct_builder(self.builder.get_struct_element(*index));
            result
        }
    }
}

pub mod ListList {
    use super::{FromPointerReader, FromPointerBuilder};
    use std;
    use common::Word;
    use layout::*;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }
    }

    impl <'a, T : FromPointerReader<'a>> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(POINTER, default_value) }
        }
    }

    impl <'a, T : FromPointerReader<'a>> Index<uint, T> for Reader<'a, T> {
        fn index(&self, index : &uint) -> T {
            assert!(*index <  self.size());
            FromPointerReader::get_from_pointer(
                &self.reader.get_pointer_element(*index), std::ptr::null())
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : FromPointerBuilder<'a>> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }
    }

    impl <'a, T : FromPointerBuilder<'a>> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(builder : PointerBuilder<'a>, size : uint) -> Builder<'a, T> {
            Builder {
                builder : builder.init_list(POINTER, size)
            }
        }
        fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Builder<'a, T> {
            Builder {
                builder : builder.get_list(POINTER, default_value)
            }
        }
    }

    impl <'a, T : FromPointerBuilder<'a>> Index<uint, T> for Builder<'a, T> {
        fn index(&self, index : &uint) -> T {
            let result : T =
                FromPointerBuilder::get_from_pointer(
                self.builder.get_pointer_element(*index),
                std::ptr::null());
            result
        }
    }

}

pub mod BlobList {

}
<commit_msg>TextList<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use layout::{PointerBuilder, PointerReader};
use common::Word;

pub trait FromPointerReader<'a> {
    fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Self;
}

pub trait FromPointerBuilder<'a> {
    fn init_pointer(PointerBuilder<'a>, uint) -> Self;
    fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Self;
}

pub mod PrimitiveList {
    use super::{FromPointerReader, FromPointerBuilder};
    use layout::{ListReader, ListBuilder, PointerReader, PointerBuilder,
                 PrimitiveElement, POINTER};
    use common::Word;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T : PrimitiveElement> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }
    }

    impl <'a, T : PrimitiveElement> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(POINTER, default_value) }
        }
    }

    impl <'a, T : PrimitiveElement> Index<uint, T> for Reader<'a, T> {
        fn index(&self, index : &uint) -> T {
            PrimitiveElement::get(&self.reader, *index)
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : PrimitiveElement> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }

        pub fn set(&self, index : uint, value : T) {
            PrimitiveElement::set(&self.builder, index, value);
        }
    }

    impl <'a, T : PrimitiveElement> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(_builder : PointerBuilder<'a>, _size : uint) -> Builder<'a, T> {
//            builder.init_list(
            fail!();
        }
        fn get_from_pointer(_builder : PointerBuilder<'a>, _default_value : *Word) -> Builder<'a, T> {
            fail!();
        }
    }

    impl <'a, T : PrimitiveElement> Index<uint, T> for Builder<'a, T> {
        fn index(&self, index : &uint) -> T {
            PrimitiveElement::get_from_builder(&self.builder, *index)
        }
    }
}

pub trait ToU16 {
    fn to_u16(self) -> u16;
}

pub mod EnumList {
    use layout::*;
    use list::*;
    use common::Word;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T : FromPrimitive> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }

    }

    impl <'a, T : FromPrimitive> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(TWO_BYTES, default_value) }
        }
    }

    impl <'a, T : FromPrimitive> Index<uint, Option<T>> for Reader<'a, T> {
        fn index(&self, index : &uint) -> Option<T> {
            let result : u16 = PrimitiveElement::get(&self.reader, *index);
            FromPrimitive::from_u16(result)
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : ToU16 + FromPrimitive> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }

        pub fn set(&self, index : uint, value : T) {
            PrimitiveElement::set(&self.builder, index, value.to_u16());
        }
    }

    impl <'a, T : FromPrimitive> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(builder : PointerBuilder<'a>, size : uint) -> Builder<'a, T> {
            Builder { builder : builder.init_list(TWO_BYTES, size) }
        }
        fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Builder<'a, T> {
            Builder { builder : builder.get_list(TWO_BYTES, default_value) }
        }
    }

    impl <'a, T : ToU16 + FromPrimitive> Index<uint, Option<T>> for Builder<'a, T> {
        fn index(&self, index : &uint) -> Option<T> {
            let result : u16 = PrimitiveElement::get_from_builder(&self.builder, *index);
            FromPrimitive::from_u16(result)
        }
    }
}

pub mod StructList {
    use super::{FromPointerReader, FromPointerBuilder};
    use common::Word;
    use layout::*;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T : FromStructReader<'a>> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }
    }

    impl <'a, T : FromStructReader<'a>> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(INLINE_COMPOSITE, default_value) }
        }
    }

    impl <'a, T : FromStructReader<'a>> Index<uint, T> for Reader<'a, T> {
        fn index(&self, index : &uint) -> T {
            let result : T = FromStructReader::from_struct_reader(self.reader.get_struct_element(*index));
            result
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : FromStructBuilder<'a>> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }

//        pub fn set(&self, index : uint, value : T) {
//        }
    }

    impl <'a, T : FromStructBuilder<'a> + HasStructSize> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(builder : PointerBuilder<'a>, size : uint) -> Builder<'a, T> {
            Builder {
                builder : builder.init_struct_list(size, HasStructSize::struct_size(None::<T>))
            }
        }
        fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Builder<'a, T> {
            Builder {
                builder : builder.get_struct_list(HasStructSize::struct_size(None::<T>), default_value)
            }
        }
    }

    impl <'a, T : FromStructBuilder<'a>> Index<uint, T> for Builder<'a, T> {
        fn index(&self, index : &uint) -> T {
            let result : T =
                FromStructBuilder::from_struct_builder(self.builder.get_struct_element(*index));
            result
        }
    }
}

pub mod ListList {
    use super::{FromPointerReader, FromPointerBuilder};
    use std;
    use common::Word;
    use layout::*;

    pub struct Reader<'a, T> {
        reader : ListReader<'a>
    }

    impl <'a, T> Reader<'a, T> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b, T> {
            Reader::<'b, T> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }
    }

    impl <'a, T : FromPointerReader<'a>> FromPointerReader<'a> for Reader<'a, T> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a, T> {
            Reader { reader : reader.get_list(POINTER, default_value) }
        }
    }

    impl <'a, T : FromPointerReader<'a>> Index<uint, T> for Reader<'a, T> {
        fn index(&self, index : &uint) -> T {
            assert!(*index <  self.size());
            FromPointerReader::get_from_pointer(
                &self.reader.get_pointer_element(*index), std::ptr::null())
        }
    }

    pub struct Builder<'a, T> {
        builder : ListBuilder<'a>
    }

    impl <'a, T : FromPointerBuilder<'a>> Builder<'a, T> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a, T> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }
    }

    impl <'a, T : FromPointerBuilder<'a>> FromPointerBuilder<'a> for Builder<'a, T> {
        fn init_pointer(builder : PointerBuilder<'a>, size : uint) -> Builder<'a, T> {
            Builder {
                builder : builder.init_list(POINTER, size)
            }
        }
        fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Builder<'a, T> {
            Builder {
                builder : builder.get_list(POINTER, default_value)
            }
        }
    }

    impl <'a, T : FromPointerBuilder<'a>> Index<uint, T> for Builder<'a, T> {
        fn index(&self, index : &uint) -> T {
            let result : T =
                FromPointerBuilder::get_from_pointer(
                self.builder.get_pointer_element(*index),
                std::ptr::null());
            result
        }
    }

}

pub mod TextList {
    use super::{FromPointerReader, FromPointerBuilder};
    use std;
    use common::Word;
    use blob::Text;
    use layout::*;

    pub struct Reader<'a> {
        reader : ListReader<'a>
    }

    impl <'a> Reader<'a> {
        pub fn new<'b>(reader : ListReader<'b>) -> Reader<'b> {
            Reader::<'b> { reader : reader }
        }

        pub fn size(&self) -> uint { self.reader.size() }
    }

    impl <'a> FromPointerReader<'a> for Reader<'a> {
        fn get_from_pointer(reader : &PointerReader<'a>, default_value : *Word) -> Reader<'a> {
            Reader { reader : reader.get_list(POINTER, default_value) }
        }
    }

    impl <'a> Index<uint, Text::Reader<'a>> for Reader<'a> {
        fn index(&self, index : &uint) -> Text::Reader<'a> {
            assert!(*index <  self.size());
            self.reader.get_pointer_element(*index).get_text(std::ptr::null(), 0)
        }
    }

    pub struct Builder<'a> {
        builder : ListBuilder<'a>
    }

    impl <'a> Builder<'a> {
        pub fn new(builder : ListBuilder<'a>) -> Builder<'a> {
            Builder { builder : builder }
        }

        pub fn size(&self) -> uint { self.builder.size() }
    }

    impl <'a> FromPointerBuilder<'a> for Builder<'a> {
        fn init_pointer(builder : PointerBuilder<'a>, size : uint) -> Builder<'a> {
            Builder {
                builder : builder.init_list(POINTER, size)
            }
        }
        fn get_from_pointer(builder : PointerBuilder<'a>, default_value : *Word) -> Builder<'a> {
            Builder {
                builder : builder.get_list(POINTER, default_value)
            }
        }
    }

    impl <'a> Index<uint, Text::Builder<'a>> for Builder<'a> {
        fn index(&self, index : &uint) -> Text::Builder<'a> {
            self.builder.get_pointer_element(*index).get_text(std::ptr::null(), 0)
        }
    }

}
<|endoftext|>