<commit_before>use serialize::{Encodable, Encoder, Decodable, Decoder};

use std::hash;
use std::iter::FromIterator;
use std::iter::IntoIterator;
use std::ops::{
    Index,
    IndexMut,
};

use super::{Array, Dimension, Ix};

impl<'a, A, D: Dimension> Index<D> for Array<A, D>
{
    type Output = A;
    #[inline]
    /// Access the element at **index**.
    ///
    /// **Panics** if index is out of bounds.
    fn index(&self, index: &D) -> &A {
        self.at(index.clone()).expect("Array::index: out of bounds")
    }
}

impl<'a, A: Clone, D: Dimension> IndexMut<D> for Array<A, D>
{
    #[inline]
    /// Access the element at **index** mutably.
    ///
    /// **Panics** if index is out of bounds.
    fn index_mut(&mut self, index: &D) -> &mut A {
        self.at_mut(index.clone()).expect("Array::index_mut: out of bounds")
    }
}

impl<A: PartialEq, D: Dimension>
PartialEq for Array<A, D>
{
    /// Return `true` if the array shapes and all elements of `self` and
    /// `other` are equal. Return `false` otherwise.
    fn eq(&self, other: &Array<A, D>) -> bool
    {
        self.shape() == other.shape() &&
        self.iter().zip(other.iter()).all(|(a, b)| a == b)
    }
}

impl<A: Eq, D: Dimension>
Eq for Array<A, D> {}

impl<A> FromIterator<A> for Array<A, Ix>
{
    fn from_iter<I: IntoIterator<Item=A>>(it: I) -> Array<A, Ix>
    {
        Array::from_iter(it.into_iter())
    }
}

impl<A: hash::Hash, D: Dimension>
hash::Hash for Array<A, D>
{
    fn hash<S: hash::Hasher>(&self, state: &mut S)
    {
        self.shape().hash(state);
        for elt in self.iter() {
            elt.hash(state)
        }
    }
}

// Use version number so we can add a packed format later.
static ARRAY_FORMAT_VERSION: u8 = 1u8;

impl<A: Encodable, D: Dimension + Encodable> Encodable for Array<A, D>
{
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        s.emit_struct("Array", 3, |e| {
            try!(e.emit_struct_field("v", 0, |e| {
                ARRAY_FORMAT_VERSION.encode(e)
            }));
            // FIXME: Write self.dim as a slice (self.shape)
            // The problem is decoding it.
            try!(e.emit_struct_field("dim", 1,
                                           |e| self.dim.encode(e)));
            try!(e.emit_struct_field("data", 2, |e| {
                let sz = self.dim.size();
                e.emit_seq(sz, |e| {
                    for (i, elt) in self.iter().enumerate() {
                        try!(e.emit_seq_elt(i, |e| {
                            elt.encode(e)
                        }))
                    }
                    Ok(())
                })
            }));
            Ok(())
        })
    }
}

impl<A: Decodable, D: Dimension + Decodable>
    Decodable for Array<A, D>
{
    fn decode<S: Decoder>(d: &mut S) -> Result<Array<A, D>, S::Error>
    {
        d.read_struct("Array", 3, |d| {
            let version: u8 = try!(d.read_struct_field("v", 0, Decodable::decode));
            if version > ARRAY_FORMAT_VERSION {
                return Err(d.error("unknown array version"))
            }
            let dim: D = try!(d.read_struct_field("dim", 1, |d| {
                Decodable::decode(d)
            }));
            let elements = try!(
                d.read_struct_field("data", 2, |d| {
                    d.read_seq(|d, len| {
                        if len != dim.size() {
                            Err(d.error("data and dimension must match in size"))
                        } else {
                            let mut elements = Vec::with_capacity(len);
                            for i in (0..len) {
                                elements.push(try!(d.read_seq_elt::<A, _>(i, Decodable::decode)))
                            }
                            Ok(elements)
                        }
                    })
            }));
            unsafe {
                Ok(Array::from_vec_dim(dim, elements))
            }
        })
    }
}
<commit_msg>Update Index/IndexMut<commit_after>use serialize::{Encodable, Encoder, Decodable, Decoder};

use std::hash;
use std::iter::FromIterator;
use std::iter::IntoIterator;
use std::ops::{
    Index,
    IndexMut,
};

use super::{Array, Dimension, Ix};

impl<'a, A, D: Dimension> Index<D> for Array<A, D>
{
    type Output = A;
    #[inline]
    /// Access the element at **index**.
    ///
    /// **Panics** if index is out of bounds.
    fn index(&self, index: D) -> &A {
        self.at(index).expect("Array::index: out of bounds")
    }
}

impl<'a, A: Clone, D: Dimension> IndexMut<D> for Array<A, D>
{
    #[inline]
    /// Access the element at **index** mutably.
    ///
    /// **Panics** if index is out of bounds.
    fn index_mut(&mut self, index: D) -> &mut A {
        self.at_mut(index).expect("Array::index_mut: out of bounds")
    }
}

impl<A: PartialEq, D: Dimension>
PartialEq for Array<A, D>
{
    /// Return `true` if the array shapes and all elements of `self` and
    /// `other` are equal. Return `false` otherwise.
    fn eq(&self, other: &Array<A, D>) -> bool
    {
        self.shape() == other.shape() &&
        self.iter().zip(other.iter()).all(|(a, b)| a == b)
    }
}

impl<A: Eq, D: Dimension>
Eq for Array<A, D> {}

impl<A> FromIterator<A> for Array<A, Ix>
{
    fn from_iter<I: IntoIterator<Item=A>>(it: I) -> Array<A, Ix>
    {
        Array::from_iter(it.into_iter())
    }
}

impl<A: hash::Hash, D: Dimension>
hash::Hash for Array<A, D>
{
    fn hash<S: hash::Hasher>(&self, state: &mut S)
    {
        self.shape().hash(state);
        for elt in self.iter() {
            elt.hash(state)
        }
    }
}

// Use version number so we can add a packed format later.
static ARRAY_FORMAT_VERSION: u8 = 1u8;

impl<A: Encodable, D: Dimension + Encodable> Encodable for Array<A, D>
{
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        s.emit_struct("Array", 3, |e| {
            try!(e.emit_struct_field("v", 0, |e| {
                ARRAY_FORMAT_VERSION.encode(e)
            }));
            // FIXME: Write self.dim as a slice (self.shape)
            // The problem is decoding it.
            try!(e.emit_struct_field("dim", 1,
                                           |e| self.dim.encode(e)));
            try!(e.emit_struct_field("data", 2, |e| {
                let sz = self.dim.size();
                e.emit_seq(sz, |e| {
                    for (i, elt) in self.iter().enumerate() {
                        try!(e.emit_seq_elt(i, |e| {
                            elt.encode(e)
                        }))
                    }
                    Ok(())
                })
            }));
            Ok(())
        })
    }
}

impl<A: Decodable, D: Dimension + Decodable>
    Decodable for Array<A, D>
{
    fn decode<S: Decoder>(d: &mut S) -> Result<Array<A, D>, S::Error>
    {
        d.read_struct("Array", 3, |d| {
            let version: u8 = try!(d.read_struct_field("v", 0, Decodable::decode));
            if version > ARRAY_FORMAT_VERSION {
                return Err(d.error("unknown array version"))
            }
            let dim: D = try!(d.read_struct_field("dim", 1, |d| {
                Decodable::decode(d)
            }));
            let elements = try!(
                d.read_struct_field("data", 2, |d| {
                    d.read_seq(|d, len| {
                        if len != dim.size() {
                            Err(d.error("data and dimension must match in size"))
                        } else {
                            let mut elements = Vec::with_capacity(len);
                            for i in (0..len) {
                                elements.push(try!(d.read_seq_elt::<A, _>(i, Decodable::decode)))
                            }
                            Ok(elements)
                        }
                    })
            }));
            unsafe {
                Ok(Array::from_vec_dim(dim, elements))
            }
        })
    }
}
<|endoftext|>


<commit_before>extern crate nom;
extern crate num;

use std::mem;
use std::fmt;

use nom::{IResult, ErrorKind};
use num::bigint;
use num::bigint::ToBigInt;
use num::traits::{Zero, One};

static BERT_MAGIC_NUMBER: u8 = 131;
static SMALL_INTEGER_EXT: u8 = 97;
static INTEGER_EXT: u8 = 98;
static FLOAT_EXT: u8 = 99;
static ATOM_EXT: u8 = 100;
static SMALL_TUPLE_EXT: u8 = 104;
static LARGE_TUPLE_EXT: u8 = 105;
static NIL_EXT: u8 = 106;
static STRING_EXT: u8 = 107;
static LIST_EXT: u8 = 108;
static BINARY_EXT: u8 = 109;
static SMALL_BIG_EXT: u8 = 110;
static LARGE_BIG_EXT: u8 = 111;
static ATOM_UTF8_EXT: u8 = 118;
static SMALL_ATOM_UTF8_EXT: u8 = 119;
static NEW_FLOAT_EXT: u8 = 70;

#[derive(Debug, PartialEq)]
pub enum BertTerm {
    Int(i32),
    BigInt(bigint::BigInt),
    Float(f64),
    Atom(String),
    Tuple(Vec<BertTerm>),
    List(Vec<BertTerm>),
    Binary(Vec<u8>)
}

impl fmt::Display for BertTerm {
    #[allow(unused_must_use)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BertTerm::Int(n) => { write!(f, "{}", n) }
            BertTerm::BigInt(ref n) => { write!(f, "{}", n) }
            BertTerm::Float(x) => { write!(f, "{}", x) }
            BertTerm::Atom(ref s) => { write!(f, "{}", s) }
            BertTerm::Tuple(ref ts) => {
                write!(f, "{}", '{');
                let mut first = true;
                for t in ts {
                    if !first { write!(f, ", "); }
                    write!(f, "{}", t);
                    first = false;
                }
                write!(f, "{}", '}')
            }
            BertTerm::List(ref ts) => {
                write!(f, "[");
                let mut first = true;
                for t in ts {
                    if !first { write!(f, ", "); }
                    write!(f, "{}", t);
                    first = false;
                }
                write!(f, "]")
            }
            BertTerm::Binary(ref bytes) => {
                write!(f, "<<");
                let mut first = true;
                for b in bytes {
                    if !first { write!(f, ", "); }
                    write!(f, "{}", b);
                    first = false;
                }
                write!(f, ">>")
            }
        }
    }
}

#[derive(Debug)]
pub enum BertError {
    Unknown,
    InvalidMagicNumber
}

named!(bert_magic_number, tag!([BERT_MAGIC_NUMBER]));

fn small_integer(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_INTEGER_EXT]));
    let (i2, n) = try_parse!(i1, nom::be_u8);
    IResult::Done(i2, BertTerm::Int(n as i32))
}

#[test]
fn test_small_integer() {
    for i in 0 .. u8::max_value() {
        let buf = &[SMALL_INTEGER_EXT, i];
        let t = small_integer(buf);
        assert_eq!(t, IResult::Done(&b""[..], BertTerm::Int(i as i32)));
    }
}

fn integer(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([INTEGER_EXT]));
    let (i2, n) = try_parse!(i1, nom::be_i32);
    IResult::Done(i2, BertTerm::Int(n))
}

#[test]
fn test_integer() {
    let buf0 = &[INTEGER_EXT, 0, 0, 0, 1];
    let buf1 = &[INTEGER_EXT, 0, 0, 1, 0];
    let buf2 = &[INTEGER_EXT, 0, 1, 0, 0];
    let buf3 = &[INTEGER_EXT, 1, 0, 0, 0];

    assert_eq!(integer(buf0), IResult::Done(&b""[..], BertTerm::Int(1)));
    assert_eq!(integer(buf1), IResult::Done(&b""[..], BertTerm::Int(1 << 8)));
    assert_eq!(integer(buf2), IResult::Done(&b""[..], BertTerm::Int(1 << 16)));
    assert_eq!(integer(buf3), IResult::Done(&b""[..], BertTerm::Int(1 << 24)));
}

fn atom(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([ATOM_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

#[test]
fn test_atom() {
    let buf = &[ATOM_EXT, 0, 2, b'a', b'b'];
    assert_eq!(atom(buf), IResult::Done(&b""[..], BertTerm::Atom("ab".to_string())));
}

fn small_atom_utf8(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_ATOM_UTF8_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u8);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn atom_utf8(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([ATOM_UTF8_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn small_tuple(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_TUPLE_EXT]));
    let (i2, arity) = try_parse!(i1, nom::be_u8);
    let (i3, tuple) = try_parse!(i2, count!(bert_term, arity as usize));
    IResult::Done(i3, BertTerm::Tuple(tuple))
}

#[test]
fn test_small_tuple() {
    let buf = &[SMALL_TUPLE_EXT, 2, ATOM_EXT, 0, 2, b'o', b'k', SMALL_INTEGER_EXT, 42];
    assert_eq!(small_tuple(buf),
               IResult::Done(&b""[..],
                             BertTerm::Tuple(vec![BertTerm::Atom("ok".to_string()),
                                                  BertTerm::Int(42)])));
}

fn large_tuple(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([LARGE_TUPLE_EXT]));
    let (i2, arity) = try_parse!(i1, nom::be_u32);
    let (i3, tuple) = try_parse!(i2, count!(bert_term, arity as usize));
    IResult::Done(i3, BertTerm::Tuple(tuple))
}

fn nil(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([NIL_EXT]));
    IResult::Done(i1, BertTerm::List(vec![]))
}

#[test]
fn test_nil() {
    let buf = &[NIL_EXT];
    assert_eq!(nil(buf), IResult::Done(&b""[..], BertTerm::List(vec![])));
}

fn string_like_list(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([STRING_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, nums) = try_parse!(i2, take!(len as usize));
    let elements = nums.iter().map(|n| BertTerm::Int(*n as i32)).collect();
    IResult::Done(i3, BertTerm::List(elements))
}

#[test]
fn string_like_list_test() {
    use self::BertTerm::*;
    let buf = &[STRING_EXT, 0, 5, b'h', b'e', b'l', b'l', b'o'];
    assert_eq!(string_like_list(buf),
               IResult::Done(&b""[..], List(vec![Int(104), Int(101), Int(108), Int(108), Int(111)])));
}

fn list(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([LIST_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u32);
    let (i3, mut elements) = try_parse!(i2, count!(bert_term, len as usize));
    let (i4, tail) = try_parse!(i3, bert_term);
    match tail {
        BertTerm::List(_) => (),
        last_term => { elements.push(last_term); }
    };
    IResult::Done(i4, BertTerm::List(elements))
}

#[test]
fn test_list() {
    use self::BertTerm::*;
    let buf0 = &[
        LIST_EXT, 0, 0, 0, 2,
        SMALL_INTEGER_EXT, 42,
        INTEGER_EXT, 0, 1, 0, 0,
        NIL_EXT
    ];
    let buf1 = &[
        LIST_EXT, 0, 0, 0, 2,
        SMALL_INTEGER_EXT, 42,
        INTEGER_EXT, 0, 1, 0, 0,
        SMALL_INTEGER_EXT, 84
    ];
    assert_eq!(list(buf0), IResult::Done(&b""[..], List(vec![Int(42), Int(65536)])));
    assert_eq!(list(buf1), IResult::Done(&b""[..], List(vec![Int(42), Int(65536), Int(84)])));
}

fn binary(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([BINARY_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u32);
    let (i3, elements) = try_parse!(i2, count!(nom::be_u8, len as usize));
    IResult::Done(i3, BertTerm::Binary(elements))
}

#[test]
fn binary_test() {
    let buf = &[BINARY_EXT, 0, 0, 0, 4, 1, 3, 3, 7];
    assert_eq!(binary(buf), IResult::Done(&b""[..], BertTerm::Binary(vec![1,3,3,7])));
}

fn is_zero(b: u8) -> bool { b == 0 }
fn is_non_zero(b: u8) -> bool { b != 0 }

fn old_float(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([FLOAT_EXT]));
    let (i2, bytes) = try_parse!(i1, take_while!(is_non_zero));
    let (i3, _) = try_parse!(i2, take_while!(is_zero));
    let mut s = String::new();
    for b in bytes { s.push(*b as char); }
    let f = s.parse::<f64>().unwrap();
    IResult::Done(i3, BertTerm::Float(f))
}

fn new_float(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([NEW_FLOAT_EXT]));
    let (i2, raw_bytes) = try_parse!(i1, nom::be_u64);
    let f: f64 = unsafe { mem::transmute(raw_bytes) };
    IResult::Done(i2, BertTerm::Float(f))
}

fn compute_big_int(is_negative: bool, digits: &[u8]) -> bigint::BigInt {
    let mut sum: bigint::BigInt = Zero::zero();
    let mut pos: bigint::BigInt = One::one();
    for d in digits {
        let t = &pos * &(d.to_bigint().unwrap());
        sum = sum + &t;
        pos = pos * (256).to_bigint().unwrap();
    }
    if is_negative { sum = -sum; }
    return sum;
}

fn small_big_int(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_BIG_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u8);
    let (i3, sign) = try_parse!(i2, nom::be_u8);
    let (i4, digits) = try_parse!(i3, take!(len as usize));
    let b = compute_big_int(sign == 1, &digits);
    IResult::Done(i4, BertTerm::BigInt(b))
}

fn large_big_int(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([LARGE_BIG_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u32);
    let (i3, sign) = try_parse!(i2, nom::be_u8);
    let (i4, digits) = try_parse!(i3, take!(len as usize));
    let b = compute_big_int(sign == 1, &digits);
    IResult::Done(i4, BertTerm::BigInt(b))
}

named!(bert_term<&[u8], BertTerm>,
       alt!(small_integer
            | integer
            | atom
            | small_atom_utf8
            | atom_utf8
            | small_tuple
            | large_tuple
            | nil
            | list
            | string_like_list
            | binary
            | old_float
            | new_float
            | small_big_int
            | large_big_int
       )
);

pub fn parse(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, bert_magic_number);
    let (i2, t) = try_parse!(i1, bert_term);
    IResult::Done(i2, t)
}
<commit_msg>Rename input paramaters (i0, i1, ...) to simply i<commit_after>extern crate nom;
extern crate num;

use std::mem;
use std::fmt;

use nom::{IResult, ErrorKind};
use num::bigint;
use num::bigint::ToBigInt;
use num::traits::{Zero, One};

static BERT_MAGIC_NUMBER: u8 = 131;
static SMALL_INTEGER_EXT: u8 = 97;
static INTEGER_EXT: u8 = 98;
static FLOAT_EXT: u8 = 99;
static ATOM_EXT: u8 = 100;
static SMALL_TUPLE_EXT: u8 = 104;
static LARGE_TUPLE_EXT: u8 = 105;
static NIL_EXT: u8 = 106;
static STRING_EXT: u8 = 107;
static LIST_EXT: u8 = 108;
static BINARY_EXT: u8 = 109;
static SMALL_BIG_EXT: u8 = 110;
static LARGE_BIG_EXT: u8 = 111;
static ATOM_UTF8_EXT: u8 = 118;
static SMALL_ATOM_UTF8_EXT: u8 = 119;
static NEW_FLOAT_EXT: u8 = 70;

#[derive(Debug, PartialEq)]
pub enum BertTerm {
    Int(i32),
    BigInt(bigint::BigInt),
    Float(f64),
    Atom(String),
    Tuple(Vec<BertTerm>),
    List(Vec<BertTerm>),
    Binary(Vec<u8>)
}

impl fmt::Display for BertTerm {
    #[allow(unused_must_use)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BertTerm::Int(n) => { write!(f, "{}", n) }
            BertTerm::BigInt(ref n) => { write!(f, "{}", n) }
            BertTerm::Float(x) => { write!(f, "{}", x) }
            BertTerm::Atom(ref s) => { write!(f, "{}", s) }
            BertTerm::Tuple(ref ts) => {
                write!(f, "{}", '{');
                let mut first = true;
                for t in ts {
                    if !first { write!(f, ", "); }
                    write!(f, "{}", t);
                    first = false;
                }
                write!(f, "{}", '}')
            }
            BertTerm::List(ref ts) => {
                write!(f, "[");
                let mut first = true;
                for t in ts {
                    if !first { write!(f, ", "); }
                    write!(f, "{}", t);
                    first = false;
                }
                write!(f, "]")
            }
            BertTerm::Binary(ref bytes) => {
                write!(f, "<<");
                let mut first = true;
                for b in bytes {
                    if !first { write!(f, ", "); }
                    write!(f, "{}", b);
                    first = false;
                }
                write!(f, ">>")
            }
        }
    }
}

#[derive(Debug)]
pub enum BertError {
    Unknown,
    InvalidMagicNumber
}

named!(bert_magic_number, tag!([BERT_MAGIC_NUMBER]));

fn small_integer(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([SMALL_INTEGER_EXT]));
    let (i, n) = try_parse!(i, nom::be_u8);
    IResult::Done(i, BertTerm::Int(n as i32))
}

#[test]
fn test_small_integer() {
    for i in 0 .. u8::max_value() {
        let buf = &[SMALL_INTEGER_EXT, i];
        let t = small_integer(buf);
        assert_eq!(t, IResult::Done(&b""[..], BertTerm::Int(i as i32)));
    }
}

fn integer(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([INTEGER_EXT]));
    let (i, n) = try_parse!(i, nom::be_i32);
    IResult::Done(i, BertTerm::Int(n))
}

#[test]
fn test_integer() {
    let buf0 = &[INTEGER_EXT, 0, 0, 0, 1];
    let buf1 = &[INTEGER_EXT, 0, 0, 1, 0];
    let buf2 = &[INTEGER_EXT, 0, 1, 0, 0];
    let buf3 = &[INTEGER_EXT, 1, 0, 0, 0];

    assert_eq!(integer(buf0), IResult::Done(&b""[..], BertTerm::Int(1)));
    assert_eq!(integer(buf1), IResult::Done(&b""[..], BertTerm::Int(1 << 8)));
    assert_eq!(integer(buf2), IResult::Done(&b""[..], BertTerm::Int(1 << 16)));
    assert_eq!(integer(buf3), IResult::Done(&b""[..], BertTerm::Int(1 << 24)));
}

fn atom(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([ATOM_EXT]));
    let (i, len) = try_parse!(i, nom::be_u16);
    let (i, atom_name) = try_parse!(i, take_str!(len));
    IResult::Done(i, BertTerm::Atom(atom_name.to_string()))
}

#[test]
fn test_atom() {
    let buf = &[ATOM_EXT, 0, 2, b'a', b'b'];
    assert_eq!(atom(buf), IResult::Done(&b""[..], BertTerm::Atom("ab".to_string())));
}

fn small_atom_utf8(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([SMALL_ATOM_UTF8_EXT]));
    let (i, len) = try_parse!(i, nom::be_u8);
    let (i, atom_name) = try_parse!(i, take_str!(len));
    IResult::Done(i, BertTerm::Atom(atom_name.to_string()))
}

fn atom_utf8(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([ATOM_UTF8_EXT]));
    let (i, len) = try_parse!(i, nom::be_u16);
    let (i, atom_name) = try_parse!(i, take_str!(len));
    IResult::Done(i, BertTerm::Atom(atom_name.to_string()))
}

fn small_tuple(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([SMALL_TUPLE_EXT]));
    let (i, arity) = try_parse!(i, nom::be_u8);
    let (i, tuple) = try_parse!(i, count!(bert_term, arity as usize));
    IResult::Done(i, BertTerm::Tuple(tuple))
}

#[test]
fn test_small_tuple() {
    let buf = &[SMALL_TUPLE_EXT, 2, ATOM_EXT, 0, 2, b'o', b'k', SMALL_INTEGER_EXT, 42];
    assert_eq!(small_tuple(buf),
               IResult::Done(&b""[..],
                             BertTerm::Tuple(vec![BertTerm::Atom("ok".to_string()),
                                                  BertTerm::Int(42)])));
}

fn large_tuple(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([LARGE_TUPLE_EXT]));
    let (i, arity) = try_parse!(i, nom::be_u32);
    let (i, tuple) = try_parse!(i, count!(bert_term, arity as usize));
    IResult::Done(i, BertTerm::Tuple(tuple))
}

fn nil(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([NIL_EXT]));
    IResult::Done(i, BertTerm::List(vec![]))
}

#[test]
fn test_nil() {
    let buf = &[NIL_EXT];
    assert_eq!(nil(buf), IResult::Done(&b""[..], BertTerm::List(vec![])));
}

fn string_like_list(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([STRING_EXT]));
    let (i, len) = try_parse!(i, nom::be_u16);
    let (i, nums) = try_parse!(i, take!(len as usize));
    let elements = nums.iter().map(|n| BertTerm::Int(*n as i32)).collect();
    IResult::Done(i, BertTerm::List(elements))
}

#[test]
fn string_like_list_test() {
    use self::BertTerm::*;
    let buf = &[STRING_EXT, 0, 5, b'h', b'e', b'l', b'l', b'o'];
    assert_eq!(string_like_list(buf),
               IResult::Done(&b""[..], List(vec![Int(104), Int(101), Int(108), Int(108), Int(111)])));
}

fn list(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([LIST_EXT]));
    let (i, len) = try_parse!(i, nom::be_u32);
    let (i, mut elements) = try_parse!(i, count!(bert_term, len as usize));
    let (i, tail) = try_parse!(i, bert_term);
    match tail {
        BertTerm::List(_) => (),
        last_term => { elements.push(last_term); }
    };
    IResult::Done(i, BertTerm::List(elements))
}

#[test]
fn test_list() {
    use self::BertTerm::*;
    let buf0 = &[
        LIST_EXT, 0, 0, 0, 2,
        SMALL_INTEGER_EXT, 42,
        INTEGER_EXT, 0, 1, 0, 0,
        NIL_EXT
    ];
    let buf1 = &[
        LIST_EXT, 0, 0, 0, 2,
        SMALL_INTEGER_EXT, 42,
        INTEGER_EXT, 0, 1, 0, 0,
        SMALL_INTEGER_EXT, 84
    ];
    assert_eq!(list(buf0), IResult::Done(&b""[..], List(vec![Int(42), Int(65536)])));
    assert_eq!(list(buf1), IResult::Done(&b""[..], List(vec![Int(42), Int(65536), Int(84)])));
}

fn binary(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([BINARY_EXT]));
    let (i, len) = try_parse!(i, nom::be_u32);
    let (i, elements) = try_parse!(i, count!(nom::be_u8, len as usize));
    IResult::Done(i, BertTerm::Binary(elements))
}

#[test]
fn binary_test() {
    let buf = &[BINARY_EXT, 0, 0, 0, 4, 1, 3, 3, 7];
    assert_eq!(binary(buf), IResult::Done(&b""[..], BertTerm::Binary(vec![1,3,3,7])));
}

fn is_zero(b: u8) -> bool { b == 0 }
fn is_non_zero(b: u8) -> bool { b != 0 }

fn old_float(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([FLOAT_EXT]));
    let (i, bytes) = try_parse!(i, take_while!(is_non_zero));
    let (i, _) = try_parse!(i, take_while!(is_zero));
    let mut s = String::new();
    for b in bytes { s.push(*b as char); }
    let f = s.parse::<f64>().unwrap();
    IResult::Done(i, BertTerm::Float(f))
}

fn new_float(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([NEW_FLOAT_EXT]));
    let (i, raw_bytes) = try_parse!(i, nom::be_u64);
    let f: f64 = unsafe { mem::transmute(raw_bytes) };
    IResult::Done(i, BertTerm::Float(f))
}

fn compute_big_int(is_negative: bool, digits: &[u8]) -> bigint::BigInt {
    let mut sum: bigint::BigInt = Zero::zero();
    let mut pos: bigint::BigInt = One::one();
    for d in digits {
        let t = &pos * &(d.to_bigint().unwrap());
        sum = sum + &t;
        pos = pos * (256).to_bigint().unwrap();
    }
    if is_negative { sum = -sum; }
    return sum;
}

fn small_big_int(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([SMALL_BIG_EXT]));
    let (i, len) = try_parse!(i, nom::be_u8);
    let (i, sign) = try_parse!(i, nom::be_u8);
    let (i, digits) = try_parse!(i, take!(len as usize));
    let b = compute_big_int(sign == 1, &digits);
    IResult::Done(i, BertTerm::BigInt(b))
}

fn large_big_int(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, tag!([LARGE_BIG_EXT]));
    let (i, len) = try_parse!(i, nom::be_u32);
    let (i, sign) = try_parse!(i, nom::be_u8);
    let (i, digits) = try_parse!(i, take!(len as usize));
    let b = compute_big_int(sign == 1, &digits);
    IResult::Done(i, BertTerm::BigInt(b))
}

named!(bert_term<&[u8], BertTerm>,
       alt!(small_integer
            | integer
            | atom
            | small_atom_utf8
            | atom_utf8
            | small_tuple
            | large_tuple
            | nil
            | list
            | string_like_list
            | binary
            | old_float
            | new_float
            | small_big_int
            | large_big_int
       )
);

pub fn parse(i: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i, _) = try_parse!(i, bert_magic_number);
    let (i, t) = try_parse!(i, bert_term);
    IResult::Done(i, t)
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

use progress::Graph;
use progress::subgraph::{Source, Target};

use communication::Observer;
use communication::Communicator;
use communication::Data;
use communication::channels::OutputPort;

// pub trait StreamTrait {
//     type Data:         Data;
//     type Graph:        Graph;
//     type Communicator: Communicator;
// }

pub struct Stream<G: Graph, D:Data> {
    pub name:       Source,                         // used to name the source in the host graph.
    pub ports:      OutputPort<G::Timestamp, D>,    // used to register interest in the output.
    pub graph:      G,                              // graph builder for connecting edges, etc.
    pub allocator:  Rc<RefCell<CommunicatorEnum>>,      // for allocating communication channels
}

impl<G: Graph, D:Data> Stream<G, D> {
    pub fn add_observer<O: Observer<Time=G::Timestamp, Data=D>+'static>(&mut self, observer: O) {
        self.ports.shared.borrow_mut().push(Box::new(observer));
    }

    pub fn clone_with<D2: Data>(&self, source: Source, targets: OutputPort<G::Timestamp, D2>) -> Stream<G, D2> {
        Stream {
            name: source,
            ports: targets,
            graph: self.graph.clone(),
            allocator: self.allocator.clone(),
        }
    }

    pub fn connect_to<O: Observer<Time=G::Timestamp, Data=D>+'static>(&mut self, target: Target, observer: O) {
        self.graph.connect(self.name, target);
        self.add_observer(observer);
    }
}
<commit_msg>more logic moved to unary<commit_after>use std::rc::Rc;
use std::cell::RefCell;

use progress::Graph;
use progress::subgraph::{Source, Target};

use communication::Observer;
use communication::Communicator;
use communication::Data;
use communication::channels::OutputPort;

// pub trait StreamTrait {
//     type Data:         Data;
//     type Graph:        Graph;
//     type Communicator: Communicator;
// }

pub struct Stream<G: Graph, D:Data> {
    pub name:       Source,                         // used to name the source in the host graph.
    pub ports:      OutputPort<G::Timestamp, D>,    // used to register interest in the output.
    pub graph:      G,                              // graph builder for connecting edges, etc.
    pub allocator:  Rc<RefCell<Communicator>>,      // for allocating communication channels
}

impl<G: Graph, D:Data> Stream<G, D> {
    pub fn add_observer<O: Observer<Time=G::Timestamp, Data=D>+'static>(&mut self, observer: O) {
        self.ports.shared.borrow_mut().push(Box::new(observer));
    }

    pub fn clone_with<D2: Data>(&self, source: Source, targets: OutputPort<G::Timestamp, D2>) -> Stream<G, D2> {
        Stream {
            name: source,
            ports: targets,
            graph: self.graph.clone(),
            allocator: self.allocator.clone(),
        }
    }

    pub fn connect_to<O: Observer<Time=G::Timestamp, Data=D>+'static>(&mut self, target: Target, observer: O) {
        self.graph.connect(self.name, target);
        self.add_observer(observer);
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Four_bit_adder
extern crate arena;

use arena::Arena;

static TRUE: bool = true;
static FALSE: bool = false;

trait Gate {
  fn get(&self) -> bool;
}

impl Gate for bool {
  fn get(&self) -> bool {
    *self
  }
}

struct NotGate<'a>{
  inp: &'a Gate,
}

impl<'a> Gate for NotGate<'a> {
 fn get(&self) -> bool {
    !self.inp.get()
  }
}

struct OrGate<'a>{
  inp1: &'a Gate,
  inp2: &'a Gate,
}

impl<'a> Gate for OrGate<'a> {
  fn get(&self) -> bool {
    self.inp1.get() || self.inp2.get()
  }
}

struct AndGate<'a>{
  inp1: &'a Gate,
  inp2: &'a Gate,
}

impl<'a> Gate for AndGate<'a> {
  fn get(&self) -> bool {
    self.inp1.get() && self.inp2.get()
  }
}

fn not<'a>(ar: &'a Arena, inp: &'a Gate) -> &'a Gate {
  ar.alloc(||NotGate{inp:inp}) as &'a Gate
}

fn or<'a>(ar: &'a Arena, inp1: &'a Gate, inp2: &'a Gate) -> &'a Gate {
  ar.alloc(||OrGate{inp1:inp1,inp2:inp2}) as &'a Gate
}

fn and<'a>(ar: &'a Arena, inp1: &'a Gate, inp2: &'a Gate) -> &'a Gate {
  ar.alloc(||AndGate{inp1:inp1,inp2:inp2}) as &'a Gate
}

fn xor<'a>(ar: &'a Arena, inp1: &'a Gate, inp2: &'a Gate) -> &'a Gate {
  or(ar,and(ar,inp1,not(ar,inp2)),and(ar,not(ar,inp1),inp2))
}

fn half_add<'a>(ar: &'a Arena, inp1: &'a Gate, inp2: &'a Gate) -> (&'a Gate, &'a Gate) {
  (xor(ar,inp1,inp2),and(ar,inp1,inp2))
}

fn full_add<'a>(ar: &'a Arena, inp1: &'a Gate, inp2: &'a Gate, inp3: &'a Gate)
    -> (&'a Gate, &'a Gate) {
  let (ha1_s,ha1_c) = half_add(ar,inp1, inp3);
  let (ha2_s,ha2_c) = half_add(ar,ha1_s,inp2);
  (ha2_s,or(ar,ha1_c,ha2_c))
}

type Nibble<'a> = (&'a Gate, &'a Gate, &'a Gate, &'a Gate);

fn four_bit_adder<'a>(ar: &'a Arena, a: Nibble<'a>, b: Nibble<'a>, ci: &'a Gate)
    -> (&'a Gate, Nibble<'a>) {
  let (a4,a3,a2,a1) = a;
  let (b4,b3,b2,b1) = b;
  let (fa1_s,fa1_c) = full_add(ar,a1,b1,ci);
  let (fa2_s,fa2_c) = full_add(ar,a2,b2,fa1_c);
  let (fa3_s,fa3_c) = full_add(ar,a3,b3,fa2_c);
  let (fa4_s,fa4_c) = full_add(ar,a4,b4,fa3_c);
  (fa4_c, (fa4_s,fa3_s,fa2_s,fa1_s))
}

#[cfg(not(test))]
fn main() {
  fn show_nibble<'a>(nib: Nibble<'a>) -> (bool,bool,bool,bool) {
    let (n4,n3,n2,n1) = nib;
    (n4.get(),n3.get(),n2.get(),n1.get())
  }
  fn show_result<'a>((c,nib): (&'a Gate,Nibble<'a>)) -> (bool,(bool,bool,bool,bool)) {
    (c.get(), show_nibble(nib))
  }
  let ref ar = Arena::new();
  let gTrue = &TRUE as &Gate;
  let gFalse = &FALSE as &Gate;
  let inp1 = (gTrue,gFalse,gTrue,gTrue);
  let inp2 = (gFalse,gTrue,gTrue,gFalse);
  let (oflow,res) = show_result(four_bit_adder(ar,inp1,inp2,gFalse));
  println!("{} + {} = {}, overflow: {}", show_nibble(inp1), show_nibble(inp2), res, oflow);
}

#[test]
fn test_not() {
  let ref ar = Arena::new();
  let gTrue = &TRUE as &Gate;
  let gFalse = &FALSE as &Gate;
  assert_eq!(true, not(ar,gFalse).get());
  assert_eq!(false, not(ar,gTrue).get());
}

#[test]
fn test_or() {
  let ref ar = Arena::new();
  let gTrue = &TRUE as &Gate;
  let gFalse = &FALSE as &Gate;
  assert_eq!(false, or(ar,gFalse,gFalse).get());
  assert_eq!(true, or(ar,gTrue,gFalse).get());
  assert_eq!(true, or(ar,gFalse,gTrue).get());
  assert_eq!(true, or(ar,gTrue,gTrue).get());
}

#[test]
fn test_and() {
  let ref ar = Arena::new();
  let gTrue = &TRUE as &Gate;
  let gFalse = &FALSE as &Gate;
  assert_eq!(false, and(ar,gFalse,gFalse).get());
  assert_eq!(false, and(ar,gFalse,gTrue).get());
  assert_eq!(false, and(ar,gTrue,gFalse).get());
  assert_eq!(true, and(ar,gTrue,gTrue).get());
}

#[test]
fn test_xor() {
  let ref ar = Arena::new();
  let gTrue = &TRUE as &Gate;
  let gFalse = &FALSE as &Gate;
  assert_eq!(false, xor(ar,gFalse,gFalse).get());
  assert_eq!(true, xor(ar,gFalse,gTrue).get());
  assert_eq!(true, xor(ar,gTrue,gFalse).get());
  assert_eq!(false, xor(ar,gTrue,gTrue).get());
}

#[test]
fn test_full_add() {
  let ref ar = Arena::new();
  let gTrue = &TRUE as &Gate;
  let gFalse = &FALSE as &Gate;
  fn eval((a,b): (&Gate,&Gate)) -> (bool,bool) { (a.get(),b.get()) }
  assert_eq!( (false,false), eval(full_add(ar,gFalse,gFalse,gFalse)) );
  assert_eq!( (true,false), eval(full_add(ar,gFalse,gFalse,gTrue)) );
  assert_eq!( (true,false), eval(full_add(ar,gFalse,gTrue,gFalse)) );
  assert_eq!( (true,false), eval(full_add(ar,gTrue,gFalse,gFalse)) );
  assert_eq!( (false,true), eval(full_add(ar,gFalse,gTrue,gTrue)) );
  assert_eq!( (false,true), eval(full_add(ar,gTrue,gFalse,gTrue)) );
  assert_eq!( (false,true), eval(full_add(ar,gTrue,gTrue,gFalse)) );
  assert_eq!( (true,true), eval(full_add(ar,gTrue,gTrue,gTrue)) );
}

#[test]
fn test_full_add4() {
 fn to_nib(n:u8)->(Nibble){
    let (gt,gf) = (&TRUE as &Gate, &FALSE as &Gate);
    (
      if n&8!=0 {gt} else {gf},
      if n&4!=0 {gt} else {gf},
      if n&2!=0 {gt} else {gf},
      if n&1!=0 {gt} else {gf}
    )
  }
  fn from_result<'a>((c,(n4,n3,n2,n1)): (&'a Gate,Nibble<'a>)) -> u8 {
    let mut n = 0u8;
    if c.get()  { n += 16};
    if n4.get() { n += 8 };
    if n3.get() { n += 4 };
    if n2.get() { n += 2 };
    if n1.get() { n += 1 };
    n
  }
  let ref ar = Arena::new();
  let gTrue = &TRUE as &Gate;
  let gFalse = &FALSE as &Gate;
  for n in range(0,std::u8::MAX) {
    let (nib1,nib2) = (n >> 4,n & 15);
    assert_eq!( nib1+nib2, from_result(four_bit_adder(ar,to_nib(nib1),to_nib(nib2),gFalse)) );
    assert_eq!(nib1+nib2+1,from_result(four_bit_adder(ar,to_nib(nib1),to_nib(nib2),gTrue )) );
  }
}
<commit_msg>four_bit_adder: Remove Trait Object and Arena usage.<commit_after>// Implements http://rosettacode.org/wiki/Four_bit_adder
use std::{fmt, num};

// primitive gates
fn not(a: bool) -> bool { !a }
fn or(a: bool, b: bool) -> bool { a || b }
fn and(a: bool, b: bool) -> bool { a && b }

// xor gate [2x not, 2x and, 1x or]
// (A & !B) | (B & !A)
fn xor(a: bool, b: bool) -> bool { or(and(a, not(b)), and(b, not(a))) }

// half adder [1x xor, 1x and]
// S = A ^ B, C = A & B
fn half_adder(a: bool, b: bool) -> (bool, bool) { (xor(a, b), and(a, b)) }

// full adder [2x half_adder, 1x or]
// t = (C0 + A), t2 = t.S + B
// S = t2.S, C = t.C | t2.C
fn full_adder(a: bool, b: bool, carry: bool) -> (bool, bool) {
  let (s0, c0) = half_adder(carry, a);
  let (s1, c1) = half_adder(s0, b);

  (s1, or(c0, c1))
}

struct Nibble([bool,.. 4]);
impl Nibble {
  fn new(arr: [u8,.. 4]) -> Nibble {
    Nibble([arr[0] != 0, arr[1] != 0, arr[2] != 0, arr[3] != 0])
  }

  fn from_u8(n: u8) -> Nibble {
    Nibble::new([n & 8, n & 4, n & 2, n & 1])
  }

  fn to_u8(&self, carry: bool) -> u8 {
    match num::from_str_radix::<u8>(format!("{}", self).as_slice(), 2) {
      Some(n) if carry => n + 16,
      Some(n) => n,
      None => unreachable!()
    }
  }
}

impl fmt::Show for Nibble {
  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::FormatError> {
    write!(f, "{}", self.iter().map(|&b| if b { '1' } else { '0' }).collect::<String>())
  }
}

// We implement Deref so we can index the Nibble easily
impl<'a> Deref<[bool,.. 4]> for Nibble {
  fn deref<'a>(&'a self) -> &'a [bool,.. 4] {
    let Nibble(ref inner) = *self;
    inner
  }
}

// 4bit adder [4x full_adder]
// calculate each bit of the sum, propogate the carry
fn four_bit_adder(a: Nibble, b: Nibble, carry: bool) -> (Nibble, bool) {
  let (s0, carry) = full_adder(a[3], b[3], carry);
  let (s1, carry) = full_adder(a[2], b[2], carry);
  let (s2, carry) = full_adder(a[1], b[1], carry);
  let (s3, carry) = full_adder(a[0], b[0], carry);

  (Nibble([s3, s2, s1, s0]), carry)
}

#[cfg(not(test))]
fn main() {
  let nib_a = Nibble::new([1u8, 0, 1, 1]);
  let a = nib_a.to_u8(false);
  let b = 6;
  let nib_b = Nibble::from_u8(b);
  let (result, carry) = four_bit_adder(nib_a, nib_b, false);
  println!("{} + {} = {} | {} + {} = {} | overflow: {}",
            a, b, result.to_u8(carry), nib_a, nib_b, result, carry)
}

#[test]
fn test_not() {
  assert_eq!(true, not(false));
  assert_eq!(false, not(true));
}

#[test]
fn test_or() {
  assert_eq!(false, or(false, false));
  assert_eq!(true, or(true, false));
  assert_eq!(true, or(false, true));
  assert_eq!(true, or(true, true));
}

#[test]
fn test_and() {
  assert_eq!(false, and(false, false));
  assert_eq!(false, and(false, true));
  assert_eq!(false, and(true, false));
  assert_eq!(true, and(true, true));
}

#[test]
fn test_xor() {
  assert_eq!(false, xor(false, false));
  assert_eq!(true, xor(false, true));
  assert_eq!(true, xor(true, false));
  assert_eq!(false, xor(true, true));
}

#[test]
fn test_full_add() {
  assert_eq!((false, false), full_adder(false, false, false));
  assert_eq!((true, false), full_adder(false, false, true));
  assert_eq!((true, false), full_adder(false, true, false));
  assert_eq!((true, false), full_adder(true, false, false));
  assert_eq!((false, true), full_adder(false, true, true));
  assert_eq!((false, true), full_adder(true, false, true));
  assert_eq!((false, true), full_adder(true, true, false));
  assert_eq!((true, true), full_adder(true, true, true));
}

#[test]
fn test_four_bit_adder() {
  for (a, b) in range(0, std::u8::MAX).map(|n| (n >> 4, n & 15)) {
    let nib_a = Nibble::from_u8(a);
    let nib_b = Nibble::from_u8(b);

    let (result, carry) = four_bit_adder(nib_a, nib_b, false);
    assert_eq!(a + b, result.to_u8(carry));
    let (result, carry) = four_bit_adder(nib_a, nib_b, true);
    assert_eq!(a + b + 1, result.to_u8(carry));
  }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate std;

use super::liblua;
use { Lua, ConsumeReadable, CopyReadable, LoadedVariable, ExecutionError, ExecError };

pub struct LuaFunction<'a> {
    variable: LoadedVariable<'a>
}

struct ReadData {
    reader: Box<std::io::Reader>,
    buffer: [u8, ..128]
}

extern fn reader(_: *mut liblua::lua_State, dataRaw: *mut libc::c_void, size: *mut libc::size_t) -> *const libc::c_char {
    let data: &mut ReadData = unsafe { std::mem::transmute(dataRaw) };

    match data.reader.read(data.buffer.as_mut_slice()) {
        Ok(len) => unsafe { (*size) = len as libc::size_t },
        Err(_) => unsafe { (*size) = 0 }
    };

    data.buffer.as_ptr() as *libc::c_char
}

impl<'a> LuaFunction<'a> {
    pub fn call<V: CopyReadable>(&mut self) -> Result<V, ExecutionError> {
        // calling pcall pops the parameters and pushes output
        let pcallReturnValue = unsafe { liblua::lua_pcall(self.variable.lua.lua, 0, 1, 0) };     // TODO:

        // if pcall succeeded, returning
        if pcallReturnValue == 0 {
            return match CopyReadable::read_from_lua(self.variable.lua, -1) {
                None => fail!("Wrong type"),       // TODO: add to executionerror
                Some(x) => Ok(x)
            };
        }

        // an error occured during execution
        if pcallReturnValue == liblua::LUA_ERRMEM {
            fail!("lua_pcall returned LUA_ERRMEM");
        }

        if pcallReturnValue == liblua::LUA_ERRRUN {
            let errorMsg: String = CopyReadable::read_from_lua(self.variable.lua, -1).unwrap();
            unsafe { liblua::lua_pop(self.variable.lua.lua, 1) };
            return Err(ExecError(errorMsg));
        }

        fail!("Unknown error code returned by lua_pcall: {}", pcallReturnValue)
    }

    pub fn load_from_reader<'a, R: std::io::Reader + 'static>(lua: &'a mut Lua, code: R)
        -> Result<LuaFunction<'a>, super::ExecutionError>
    {
        let readdata = ReadData { reader: box code, buffer: unsafe { std::mem::uninitialized() } };

        let loadReturnValue = "chunk".with_c_str(|chunk|
            unsafe { liblua::lua_load(lua.lua, reader, std::mem::transmute(&readdata), chunk, std::ptr::null()) }
        );

        if loadReturnValue == 0 {
            return Ok(LuaFunction{
                variable: LoadedVariable{
                    lua: lua,
                    size: 1
                }
            });
        }

        let errorMsg: String = CopyReadable::read_from_lua(lua, -1).unwrap();
        unsafe { liblua::lua_pop(lua.lua, 1) };

        if loadReturnValue == liblua::LUA_ERRMEM {
            fail!("LUA_ERRMEM");
        }
        if loadReturnValue == liblua::LUA_ERRSYNTAX {
            return Err(super::SyntaxError(errorMsg));
        }

        fail!("Unknown error while calling lua_load");
    }

    pub fn load<'a>(lua: &'a mut Lua, code: &str)
        -> Result<LuaFunction<'a>, super::ExecutionError>
    {
        let reader = std::io::MemReader::new(code.to_c_str().as_bytes().init().to_owned());
        LuaFunction::load_from_reader(lua, reader)
    }
}

// TODO: return Result<Ret, ExecutionError> instead
impl<'a, Ret: CopyReadable> std::ops::FnMut<(), Ret> for LuaFunction<'a> {
    fn call_mut(&mut self, _: ()) -> Ret {
        self.call().unwrap()
    }
}

impl<'a> ConsumeReadable<'a> for LuaFunction<'a> {
    fn read_from_variable(var: LoadedVariable<'a>)
        -> Result<LuaFunction<'a>, LoadedVariable<'a>>
    {
        if unsafe { liblua::lua_isfunction(var.lua.lua, -1) } {
            Ok(LuaFunction{ variable: var })
        } else {
            Err(var)
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn basic() {
        let mut lua = super::super::Lua::new();

        let mut f = super::LuaFunction::load(&mut lua, "return 5;").unwrap();

        let val: int = f.call().unwrap();
        assert_eq!(val, 5);
    }

    #[test]
    fn syntax_error() {
        let mut lua = super::super::Lua::new();

        assert!(super::LuaFunction::load(&mut lua, "azerazer").is_err());
    }

    #[test]
    fn execution_error() {
        let mut lua = super::super::Lua::new();

        let mut f = super::LuaFunction::load(&mut lua, "return a:hello()").unwrap();

        let val: Result<int, super::super::ExecutionError> = f.call();
        assert!(val.is_err());
    }
}
<commit_msg>Replace .unwrap() by .expect() where appropriate<commit_after>extern crate libc;
extern crate std;

use super::liblua;
use { Lua, ConsumeReadable, CopyReadable, LoadedVariable, ExecutionError, ExecError };

pub struct LuaFunction<'a> {
    variable: LoadedVariable<'a>
}

struct ReadData {
    reader: Box<std::io::Reader>,
    buffer: [u8, ..128]
}

extern fn reader(_: *mut liblua::lua_State, dataRaw: *mut libc::c_void, size: *mut libc::size_t) -> *const libc::c_char {
    let data: &mut ReadData = unsafe { std::mem::transmute(dataRaw) };

    match data.reader.read(data.buffer.as_mut_slice()) {
        Ok(len) => unsafe { (*size) = len as libc::size_t },
        Err(_) => unsafe { (*size) = 0 }
    };

    data.buffer.as_ptr() as *libc::c_char
}

impl<'a> LuaFunction<'a> {
    pub fn call<V: CopyReadable>(&mut self) -> Result<V, ExecutionError> {
        // calling pcall pops the parameters and pushes output
        let pcallReturnValue = unsafe { liblua::lua_pcall(self.variable.lua.lua, 0, 1, 0) };     // TODO:

        // if pcall succeeded, returning
        if pcallReturnValue == 0 {
            return match CopyReadable::read_from_lua(self.variable.lua, -1) {
                None => fail!("Wrong type"),       // TODO: add to executionerror
                Some(x) => Ok(x)
            };
        }

        // an error occured during execution
        if pcallReturnValue == liblua::LUA_ERRMEM {
            fail!("lua_pcall returned LUA_ERRMEM");
        }

        if pcallReturnValue == liblua::LUA_ERRRUN {
            let errorMsg: String = CopyReadable::read_from_lua(self.variable.lua, -1).expect("can't find error message at the top of the Lua stack");
            unsafe { liblua::lua_pop(self.variable.lua.lua, 1) };
            return Err(ExecError(errorMsg));
        }

        fail!("Unknown error code returned by lua_pcall: {}", pcallReturnValue)
    }

    pub fn load_from_reader<'a, R: std::io::Reader + 'static>(lua: &'a mut Lua, code: R)
        -> Result<LuaFunction<'a>, super::ExecutionError>
    {
        let readdata = ReadData { reader: box code, buffer: unsafe { std::mem::uninitialized() } };

        let loadReturnValue = "chunk".with_c_str(|chunk|
            unsafe { liblua::lua_load(lua.lua, reader, std::mem::transmute(&readdata), chunk, std::ptr::null()) }
        );

        if loadReturnValue == 0 {
            return Ok(LuaFunction{
                variable: LoadedVariable{
                    lua: lua,
                    size: 1
                }
            });
        }

        let errorMsg: String = CopyReadable::read_from_lua(lua, -1).expect("can't find error message at the top of the Lua stack");
        unsafe { liblua::lua_pop(lua.lua, 1) };

        if loadReturnValue == liblua::LUA_ERRMEM {
            fail!("LUA_ERRMEM");
        }
        if loadReturnValue == liblua::LUA_ERRSYNTAX {
            return Err(super::SyntaxError(errorMsg));
        }

        fail!("Unknown error while calling lua_load");
    }

    pub fn load<'a>(lua: &'a mut Lua, code: &str)
        -> Result<LuaFunction<'a>, super::ExecutionError>
    {
        let reader = std::io::MemReader::new(code.to_c_str().as_bytes().init().to_owned());
        LuaFunction::load_from_reader(lua, reader)
    }
}

// TODO: return Result<Ret, ExecutionError> instead
impl<'a, Ret: CopyReadable> std::ops::FnMut<(), Ret> for LuaFunction<'a> {
    fn call_mut(&mut self, _: ()) -> Ret {
        self.call().unwrap()
    }
}

impl<'a> ConsumeReadable<'a> for LuaFunction<'a> {
    fn read_from_variable(var: LoadedVariable<'a>)
        -> Result<LuaFunction<'a>, LoadedVariable<'a>>
    {
        if unsafe { liblua::lua_isfunction(var.lua.lua, -1) } {
            Ok(LuaFunction{ variable: var })
        } else {
            Err(var)
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn basic() {
        let mut lua = super::super::Lua::new();

        let mut f = super::LuaFunction::load(&mut lua, "return 5;").unwrap();

        let val: int = f.call().unwrap();
        assert_eq!(val, 5);
    }

    #[test]
    fn syntax_error() {
        let mut lua = super::super::Lua::new();

        assert!(super::LuaFunction::load(&mut lua, "azerazer").is_err());
    }

    #[test]
    fn execution_error() {
        let mut lua = super::super::Lua::new();

        let mut f = super::LuaFunction::load(&mut lua, "return a:hello()").unwrap();

        let val: Result<int, super::super::ExecutionError> = f.call();
        assert!(val.is_err());
    }
}
<|endoftext|>


<commit_before>use c_ares;
use futures;
use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};

use crate::error::Error;
use crate::host::HostResults;
use crate::nameinfo::NameInfoResult;
use crate::resolver::{Options, Resolver};

/// The type of future returned by methods on the `FutureResolver`.
pub struct CAresFuture<T> {
    inner: futures::channel::oneshot::Receiver<c_ares::Result<T>>,
    _resolver: Arc<Resolver>,
}

impl<T> CAresFuture<T> {
    fn new(
        promise: futures::channel::oneshot::Receiver<c_ares::Result<T>>,
        resolver: Arc<Resolver>,
    ) -> Self {
        CAresFuture {
            inner: promise,
            _resolver: resolver,
        }
    }

    fn pin_get_inner(
        self: Pin<&mut Self>,
    ) -> Pin<&mut futures::channel::oneshot::Receiver<c_ares::Result<T>>> {
        unsafe { self.map_unchecked_mut(|s| &mut s.inner) }
    }
}

impl<T> Future for CAresFuture<T> {
    type Output = Result<T, c_ares::Error>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        match self.pin_get_inner().poll(cx) {
            Poll::Pending => Poll::Pending,
            Poll::Ready(Err(_)) => Poll::Ready(Err(c_ares::Error::ECANCELLED)),
            Poll::Ready(Ok(result)) => Poll::Ready(result),
        }
    }
}

/// An asynchronous DNS resolver, which returns results as `futures::Future`s.
///
/// Note that dropping the `FutureResolver` does *not* cause outstanding queries to fail - contrast
/// the `Resolver` - because the returned futures hold a reference to the underlying resolver.
pub struct FutureResolver {
    inner: Arc<Resolver>,
}

// Most query implementations follow the same pattern: call through to the `Resolver`, arranging
// that the callback completes a future.
macro_rules! futurize {
    ($resolver:expr, $query:ident, $question:expr) => {{
        let (sender, receiver) = futures::channel::oneshot::channel();
        $resolver.$query($question, move |result| {
            let _ = sender.send(result);
        });
        let resolver = Arc::clone(&$resolver);
        CAresFuture::new(receiver, resolver)
    }};
}

impl FutureResolver {
    /// Create a new `FutureResolver`, using default `Options`.
    pub fn new() -> Result<Self, Error> {
        let options = Options::default();
        Self::with_options(options)
    }

    /// Create a new `FutureResolver`, with the given `Options`.
    pub fn with_options(options: Options) -> Result<FutureResolver, Error> {
        let inner = Resolver::with_options(options)?;
        let resolver = FutureResolver {
            inner: Arc::new(inner),
        };
        Ok(resolver)
    }

    /// Set the list of servers to contact, instead of the servers specified in resolv.conf or the
    /// local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require square brackets eg
    /// `[2001:4860:4860::8888]:53`.
    pub fn set_servers(&self, servers: &[&str]) -> Result<&Self, c_ares::Error> {
        self.inner.set_servers(servers)?;
        Ok(self)
    }

    /// Set the local IPv4 address from which to make queries.
    pub fn set_local_ipv4(&self, ipv4: Ipv4Addr) -> &Self {
        self.inner.set_local_ipv4(ipv4);
        self
    }

    /// Set the local IPv6 address from which to make queries.
    pub fn set_local_ipv6(&self, ipv6: &Ipv6Addr) -> &Self {
        self.inner.set_local_ipv6(ipv6);
        self
    }

    /// Set the local device from which to make queries.
    pub fn set_local_device(&self, device: &str) -> &Self {
        self.inner.set_local_device(device);
        self
    }

    /// Look up the A records associated with `name`.
    pub fn query_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, query_a, name)
    }

    /// Search for the A records associated with `name`.
    pub fn search_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, search_a, name)
    }

    /// Look up the AAAA records associated with `name`.
    pub fn query_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, query_aaaa, name)
    }

    /// Search for the AAAA records associated with `name`.
    pub fn search_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, search_aaaa, name)
    }

    /// Look up the CNAME records associated with `name`.
    pub fn query_cname(&self, name: &str) -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, query_cname, name)
    }

    /// Search for the CNAME records associated with `name`.
    pub fn search_cname(&self, name: &str) -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, search_cname, name)
    }

    /// Look up the MX records associated with `name`.
    pub fn query_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, query_mx, name)
    }

    /// Search for the MX records associated with `name`.
    pub fn search_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, search_mx, name)
    }

    /// Look up the NAPTR records associated with `name`.
    pub fn query_naptr(&self, name: &str) -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, query_naptr, name)
    }

    /// Search for the NAPTR records associated with `name`.
    pub fn search_naptr(&self, name: &str) -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, search_naptr, name)
    }

    /// Look up the NS records associated with `name`.
    pub fn query_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, query_ns, name)
    }

    /// Search for the NS records associated with `name`.
    pub fn search_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, search_ns, name)
    }

    /// Look up the PTR records associated with `name`.
    pub fn query_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, query_ptr, name)
    }

    /// Search for the PTR records associated with `name`.
    pub fn search_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, search_ptr, name)
    }

    /// Look up the SOA records associated with `name`.
    pub fn query_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, query_soa, name)
    }

    /// Search for the SOA records associated with `name`.
    pub fn search_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, search_soa, name)
    }

    /// Look up the SRV records associated with `name`.
    pub fn query_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, query_srv, name)
    }

    /// Search for the SRV records associated with `name`.
    pub fn search_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, search_srv, name)
    }

    /// Look up the TXT records associated with `name`.
    pub fn query_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, query_txt, name)
    }

    /// Search for the TXT records associated with `name`.
    pub fn search_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, search_txt, name)
    }

    /// Perform a host query by address.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    pub fn get_host_by_address(&self, address: &IpAddr) -> CAresFuture<HostResults> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner.get_host_by_address(address, move |result| {
            let _ = sender.send(result.map(std::convert::Into::into));
        });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Perform a host query by name.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    pub fn get_host_by_name(
        &self,
        name: &str,
        family: c_ares::AddressFamily,
    ) -> CAresFuture<HostResults> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner.get_host_by_name(name, family, move |result| {
            let _ = sender.send(result.map(std::convert::Into::into));
        });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Address-to-nodename translation in protocol-independent manner.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    pub fn get_name_info<F>(
        &self,
        address: &SocketAddr,
        flags: c_ares::NIFlags,
    ) -> CAresFuture<NameInfoResult> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner.get_name_info(address, flags, move |result| {
            let _ = sender.send(result.map(std::convert::Into::into));
        });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Initiate a single-question DNS query for `name`.  The class and type of the query are per
    /// the provided parameters, taking values as defined in `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    ///
    /// This method is provided so that users can query DNS types for which `c-ares` does not
    /// provide a parser; or in case a third-party parser is preferred.  Usually, if a suitable
    /// `query_xxx()` is available, that should be used.
    pub fn query(&self, name: &str, dns_class: u16, query_type: u16) -> CAresFuture<Vec<u8>> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner
            .query(name, dns_class, query_type, move |result| {
                let _ = sender.send(result.map(std::borrow::ToOwned::to_owned));
            });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Initiate a series of single-question DNS queries for `name`.  The class and type of the
    /// query are per the provided parameters, taking values as defined in `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    ///
    /// This method is provided so that users can search DNS types for which `c-ares` does not
    /// provide a parser; or in case a third-party parser is preferred.  Usually, if a suitable
    /// `search_xxx()` is available, that should be used.
    pub fn search(&self, name: &str, dns_class: u16, query_type: u16) -> CAresFuture<Vec<u8>> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner
            .search(name, dns_class, query_type, move |result| {
                let _ = sender.send(result.map(std::borrow::ToOwned::to_owned));
            });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Cancel all requests made on this `FutureResolver`.
    pub fn cancel(&self) {
        self.inner.cancel()
    }
}
<commit_msg>More compact code in the Future implementation<commit_after>use c_ares;
use futures;
use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};

use crate::error::Error;
use crate::host::HostResults;
use crate::nameinfo::NameInfoResult;
use crate::resolver::{Options, Resolver};

/// The type of future returned by methods on the `FutureResolver`.
pub struct CAresFuture<T> {
    inner: futures::channel::oneshot::Receiver<c_ares::Result<T>>,
    _resolver: Arc<Resolver>,
}

impl<T> CAresFuture<T> {
    fn new(
        promise: futures::channel::oneshot::Receiver<c_ares::Result<T>>,
        resolver: Arc<Resolver>,
    ) -> Self {
        CAresFuture {
            inner: promise,
            _resolver: resolver,
        }
    }

    fn pin_get_inner(
        self: Pin<&mut Self>,
    ) -> Pin<&mut futures::channel::oneshot::Receiver<c_ares::Result<T>>> {
        unsafe { self.map_unchecked_mut(|s| &mut s.inner) }
    }
}

impl<T> Future for CAresFuture<T> {
    type Output = Result<T, c_ares::Error>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        self.pin_get_inner().poll(cx).map(|result|
            result.unwrap_or(Err(c_ares::Error::ECANCELLED))
        )
    }
}

/// An asynchronous DNS resolver, which returns results as `futures::Future`s.
///
/// Note that dropping the `FutureResolver` does *not* cause outstanding queries to fail - contrast
/// the `Resolver` - because the returned futures hold a reference to the underlying resolver.
pub struct FutureResolver {
    inner: Arc<Resolver>,
}

// Most query implementations follow the same pattern: call through to the `Resolver`, arranging
// that the callback completes a future.
macro_rules! futurize {
    ($resolver:expr, $query:ident, $question:expr) => {{
        let (sender, receiver) = futures::channel::oneshot::channel();
        $resolver.$query($question, move |result| {
            let _ = sender.send(result);
        });
        let resolver = Arc::clone(&$resolver);
        CAresFuture::new(receiver, resolver)
    }};
}

impl FutureResolver {
    /// Create a new `FutureResolver`, using default `Options`.
    pub fn new() -> Result<Self, Error> {
        let options = Options::default();
        Self::with_options(options)
    }

    /// Create a new `FutureResolver`, with the given `Options`.
    pub fn with_options(options: Options) -> Result<FutureResolver, Error> {
        let inner = Resolver::with_options(options)?;
        let resolver = FutureResolver {
            inner: Arc::new(inner),
        };
        Ok(resolver)
    }

    /// Set the list of servers to contact, instead of the servers specified in resolv.conf or the
    /// local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require square brackets eg
    /// `[2001:4860:4860::8888]:53`.
    pub fn set_servers(&self, servers: &[&str]) -> Result<&Self, c_ares::Error> {
        self.inner.set_servers(servers)?;
        Ok(self)
    }

    /// Set the local IPv4 address from which to make queries.
    pub fn set_local_ipv4(&self, ipv4: Ipv4Addr) -> &Self {
        self.inner.set_local_ipv4(ipv4);
        self
    }

    /// Set the local IPv6 address from which to make queries.
    pub fn set_local_ipv6(&self, ipv6: &Ipv6Addr) -> &Self {
        self.inner.set_local_ipv6(ipv6);
        self
    }

    /// Set the local device from which to make queries.
    pub fn set_local_device(&self, device: &str) -> &Self {
        self.inner.set_local_device(device);
        self
    }

    /// Look up the A records associated with `name`.
    pub fn query_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, query_a, name)
    }

    /// Search for the A records associated with `name`.
    pub fn search_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        futurize!(self.inner, search_a, name)
    }

    /// Look up the AAAA records associated with `name`.
    pub fn query_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, query_aaaa, name)
    }

    /// Search for the AAAA records associated with `name`.
    pub fn search_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        futurize!(self.inner, search_aaaa, name)
    }

    /// Look up the CNAME records associated with `name`.
    pub fn query_cname(&self, name: &str) -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, query_cname, name)
    }

    /// Search for the CNAME records associated with `name`.
    pub fn search_cname(&self, name: &str) -> CAresFuture<c_ares::CNameResults> {
        futurize!(self.inner, search_cname, name)
    }

    /// Look up the MX records associated with `name`.
    pub fn query_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, query_mx, name)
    }

    /// Search for the MX records associated with `name`.
    pub fn search_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        futurize!(self.inner, search_mx, name)
    }

    /// Look up the NAPTR records associated with `name`.
    pub fn query_naptr(&self, name: &str) -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, query_naptr, name)
    }

    /// Search for the NAPTR records associated with `name`.
    pub fn search_naptr(&self, name: &str) -> CAresFuture<c_ares::NAPTRResults> {
        futurize!(self.inner, search_naptr, name)
    }

    /// Look up the NS records associated with `name`.
    pub fn query_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, query_ns, name)
    }

    /// Search for the NS records associated with `name`.
    pub fn search_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        futurize!(self.inner, search_ns, name)
    }

    /// Look up the PTR records associated with `name`.
    pub fn query_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, query_ptr, name)
    }

    /// Search for the PTR records associated with `name`.
    pub fn search_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        futurize!(self.inner, search_ptr, name)
    }

    /// Look up the SOA records associated with `name`.
    pub fn query_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, query_soa, name)
    }

    /// Search for the SOA records associated with `name`.
    pub fn search_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        futurize!(self.inner, search_soa, name)
    }

    /// Look up the SRV records associated with `name`.
    pub fn query_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, query_srv, name)
    }

    /// Search for the SRV records associated with `name`.
    pub fn search_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        futurize!(self.inner, search_srv, name)
    }

    /// Look up the TXT records associated with `name`.
    pub fn query_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, query_txt, name)
    }

    /// Search for the TXT records associated with `name`.
    pub fn search_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        futurize!(self.inner, search_txt, name)
    }

    /// Perform a host query by address.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    pub fn get_host_by_address(&self, address: &IpAddr) -> CAresFuture<HostResults> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner.get_host_by_address(address, move |result| {
            let _ = sender.send(result.map(std::convert::Into::into));
        });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Perform a host query by name.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    pub fn get_host_by_name(
        &self,
        name: &str,
        family: c_ares::AddressFamily,
    ) -> CAresFuture<HostResults> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner.get_host_by_name(name, family, move |result| {
            let _ = sender.send(result.map(std::convert::Into::into));
        });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Address-to-nodename translation in protocol-independent manner.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    pub fn get_name_info<F>(
        &self,
        address: &SocketAddr,
        flags: c_ares::NIFlags,
    ) -> CAresFuture<NameInfoResult> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner.get_name_info(address, flags, move |result| {
            let _ = sender.send(result.map(std::convert::Into::into));
        });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Initiate a single-question DNS query for `name`.  The class and type of the query are per
    /// the provided parameters, taking values as defined in `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    ///
    /// This method is provided so that users can query DNS types for which `c-ares` does not
    /// provide a parser; or in case a third-party parser is preferred.  Usually, if a suitable
    /// `query_xxx()` is available, that should be used.
    pub fn query(&self, name: &str, dns_class: u16, query_type: u16) -> CAresFuture<Vec<u8>> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner
            .query(name, dns_class, query_type, move |result| {
                let _ = sender.send(result.map(std::borrow::ToOwned::to_owned));
            });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Initiate a series of single-question DNS queries for `name`.  The class and type of the
    /// query are per the provided parameters, taking values as defined in `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs strictly more
    /// allocation than the underlying `c-ares` code.  If this is a problem for you, you should
    /// prefer to use the analogous method on the `Resolver`.
    ///
    /// This method is provided so that users can search DNS types for which `c-ares` does not
    /// provide a parser; or in case a third-party parser is preferred.  Usually, if a suitable
    /// `search_xxx()` is available, that should be used.
    pub fn search(&self, name: &str, dns_class: u16, query_type: u16) -> CAresFuture<Vec<u8>> {
        let (sender, receiver) = futures::channel::oneshot::channel();
        self.inner
            .search(name, dns_class, query_type, move |result| {
                let _ = sender.send(result.map(std::borrow::ToOwned::to_owned));
            });
        let resolver = Arc::clone(&self.inner);
        CAresFuture::new(receiver, resolver)
    }

    /// Cancel all requests made on this `FutureResolver`.
    pub fn cancel(&self) {
        self.inner.cancel()
    }
}
<|endoftext|>