<commit_before>use std::error;
use std::fmt;
use std::io;
use std::result;

use ByteOrder;

/// A short-hand for `result::Result<T, byteorder::Error>`.
pub type Result<T> = result::Result<T, Error>;

/// An error type for reading bytes.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it
/// adds one additional error case: an unexpected EOF.
///
/// Note that this error is also used for the `write` methods to keep things
/// consistent.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Error {
    /// An unexpected EOF.
    ///
    /// This occurs when a call to the underlying reader returns `0` bytes,
    /// but more bytes are required to decode a meaningful value.
    UnexpectedEOF,
    /// Any underlying IO error that occurs while reading bytes.
    Io(io::Error),
}

impl error::FromError<io::Error> for Error {
    fn from_error(err: io::Error) -> Error { Error::Io(err) }
}

impl error::FromError<Error> for io::Error {
    fn from_error(err: Error) -> io::Error {
        match err {
            Error::Io(err) => err,
            Error::UnexpectedEOF => io::Error::new(io::ErrorKind::Other,
                                                   "unexpected EOF", None)
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::UnexpectedEOF => write!(f, "Unexpected end of file."),
            Error::Io(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnexpectedEOF => "Unexpected end of file.",
            Error::Io(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::UnexpectedEOF => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

/// Extends `Read` with methods for reading numbers. (For `std::io`.)
///
/// Most of the methods defined here have an unconstrained type parameter that
/// must be explicitly instantiated. Typically, it is instantiated with either
/// the `BigEndian` or `LittleEndian` types defined in this crate.
///
/// # Examples
///
/// Read unsigned 16 bit big-endian integers from a `Read`:
///
/// ```rust
/// use std::io::Cursor;
/// use byteorder::{BigEndian, ReadBytesExt};
///
/// let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
/// assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
/// assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
/// ```
pub trait ReadBytesExt: io::Read {
    /// Reads an unsigned 8 bit integer from the underlying reader.
    ///
    /// Note that since this reads a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn read_u8(&mut self) -> Result<u8> {
        let mut buf = [0; 1];
        try!(read_full(self, &mut buf));
        Ok(buf[0])
    }

    /// Reads a signed 8 bit integer from the underlying reader.
    ///
    /// Note that since this reads a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn read_i8(&mut self) -> Result<i8> {
        let mut buf = [0; 1];
        try!(read_full(self, &mut buf));
        Ok(buf[0] as i8)
    }

    /// Reads an unsigned 16 bit integer from the underlying reader.
    fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
        let mut buf = [0; 2];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_u16(&buf))
    }

    /// Reads a signed 16 bit integer from the underlying reader.
    fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> {
        let mut buf = [0; 2];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_i16(&buf))
    }

    /// Reads an unsigned 32 bit integer from the underlying reader.
    fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
        let mut buf = [0; 4];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_u32(&buf))
    }

    /// Reads a signed 32 bit integer from the underlying reader.
    fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
        let mut buf = [0; 4];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_i32(&buf))
    }

    /// Reads an unsigned 64 bit integer from the underlying reader.
    fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_u64(&buf))
    }

    /// Reads a signed 64 bit integer from the underlying reader.
    fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_i64(&buf))
    }

    /// Reads an unsigned n-bytes integer from the underlying reader.
    fn read_uint<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf[..nbytes]));
        Ok(<T as ByteOrder>::read_uint(&buf[..nbytes], nbytes))
    }

    /// Reads a signed n-bytes integer from the underlying reader.
    fn read_int<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf[..nbytes]));
        Ok(<T as ByteOrder>::read_int(&buf[..nbytes], nbytes))
    }

    /// Reads a IEEE754 single-precision (4 bytes) floating point number from
    /// the underlying reader.
    fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
        let mut buf = [0; 4];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_f32(&buf))
    }

    /// Reads a IEEE754 double-precision (8 bytes) floating point number from
    /// the underlying reader.
    fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_f64(&buf))
    }
}

/// All types that implement `Read` get methods defined in `ReadBytesExt`
/// for free.
impl<R: io::Read> ReadBytesExt for R {}

fn read_full<R: io::Read + ?Sized>(rdr: &mut R, buf: &mut [u8]) -> Result<()> {
    let mut nread = 0usize;
    while nread < buf.len() {
        match rdr.read(&mut buf[nread..]) {
            Ok(0) => return Err(Error::UnexpectedEOF),
            Ok(n) => nread += n,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
            Err(e) => return Err(error::FromError::from_error(e))
        }
    }
    Ok(())
}

fn write_all<W: io::Write + ?Sized>(wtr: &mut W, buf: &[u8]) -> Result<()> {
    wtr.write_all(buf).map_err(error::FromError::from_error)
}

/// Extends `Write` with methods for writing numbers. (For `std::io`.)
///
/// Most of the methods defined here have an unconstrained type parameter that
/// must be explicitly instantiated. Typically, it is instantiated with either
/// the `BigEndian` or `LittleEndian` types defined in this crate.
///
/// # Examples
///
/// Write unsigned 16 bit big-endian integers to a `Write`:
///
/// ```rust
/// use byteorder::{BigEndian, WriteBytesExt};
///
/// let mut wtr = vec![];
/// wtr.write_u16::<BigEndian>(517).unwrap();
/// wtr.write_u16::<BigEndian>(768).unwrap();
/// assert_eq!(wtr, vec![2, 5, 3, 0]);
/// ```
pub trait WriteBytesExt: io::Write {
    /// Writes an unsigned 8 bit integer to the underlying writer.
    ///
    /// Note that since this writes a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn write_u8(&mut self, n: u8) -> Result<()> {
        write_all(self, &[n])
    }

    /// Writes a signed 8 bit integer to the underlying writer.
    ///
    /// Note that since this writes a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn write_i8(&mut self, n: i8) -> Result<()> {
        write_all(self, &[n as u8])
    }

    /// Writes an unsigned 16 bit integer to the underlying writer.
    fn write_u16<T: ByteOrder>(&mut self, n: u16) -> Result<()> {
        let mut buf = [0; 2];
        <T as ByteOrder>::write_u16(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a signed 16 bit integer to the underlying writer.
    fn write_i16<T: ByteOrder>(&mut self, n: i16) -> Result<()> {
        let mut buf = [0; 2];
        <T as ByteOrder>::write_i16(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes an unsigned 32 bit integer to the underlying writer.
    fn write_u32<T: ByteOrder>(&mut self, n: u32) -> Result<()> {
        let mut buf = [0; 4];
        <T as ByteOrder>::write_u32(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a signed 32 bit integer to the underlying writer.
    fn write_i32<T: ByteOrder>(&mut self, n: i32) -> Result<()> {
        let mut buf = [0; 4];
        <T as ByteOrder>::write_i32(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes an unsigned 64 bit integer to the underlying writer.
    fn write_u64<T: ByteOrder>(&mut self, n: u64) -> Result<()> {
        let mut buf = [0; 8];
        <T as ByteOrder>::write_u64(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a signed 64 bit integer to the underlying writer.
    fn write_i64<T: ByteOrder>(&mut self, n: i64) -> Result<()> {
        let mut buf = [0; 8];
        <T as ByteOrder>::write_i64(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a IEEE754 single-precision (4 bytes) floating point number to
    /// the underlying writer.
    fn write_f32<T: ByteOrder>(&mut self, n: f32) -> Result<()> {
        let mut buf = [0; 4];
        <T as ByteOrder>::write_f32(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a IEEE754 double-precision (8 bytes) floating point number to
    /// the underlying writer.
    fn write_f64<T: ByteOrder>(&mut self, n: f64) -> Result<()> {
        let mut buf = [0; 8];
        <T as ByteOrder>::write_f64(&mut buf, n);
        write_all(self, &buf)
    }
}

/// All types that implement `Write` get methods defined in `WriteBytesExt`
/// for free.
impl<W: io::Write> WriteBytesExt for W {}
<commit_msg>Expand impl for unsized readers and writers<commit_after>use std::error;
use std::fmt;
use std::io;
use std::result;

use ByteOrder;

/// A short-hand for `result::Result<T, byteorder::Error>`.
pub type Result<T> = result::Result<T, Error>;

/// An error type for reading bytes.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it
/// adds one additional error case: an unexpected EOF.
///
/// Note that this error is also used for the `write` methods to keep things
/// consistent.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Error {
    /// An unexpected EOF.
    ///
    /// This occurs when a call to the underlying reader returns `0` bytes,
    /// but more bytes are required to decode a meaningful value.
    UnexpectedEOF,
    /// Any underlying IO error that occurs while reading bytes.
    Io(io::Error),
}

impl error::FromError<io::Error> for Error {
    fn from_error(err: io::Error) -> Error { Error::Io(err) }
}

impl error::FromError<Error> for io::Error {
    fn from_error(err: Error) -> io::Error {
        match err {
            Error::Io(err) => err,
            Error::UnexpectedEOF => io::Error::new(io::ErrorKind::Other,
                                                   "unexpected EOF", None)
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::UnexpectedEOF => write!(f, "Unexpected end of file."),
            Error::Io(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnexpectedEOF => "Unexpected end of file.",
            Error::Io(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::UnexpectedEOF => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

/// Extends `Read` with methods for reading numbers. (For `std::io`.)
///
/// Most of the methods defined here have an unconstrained type parameter that
/// must be explicitly instantiated. Typically, it is instantiated with either
/// the `BigEndian` or `LittleEndian` types defined in this crate.
///
/// # Examples
///
/// Read unsigned 16 bit big-endian integers from a `Read`:
///
/// ```rust
/// use std::io::Cursor;
/// use byteorder::{BigEndian, ReadBytesExt};
///
/// let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
/// assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
/// assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
/// ```
pub trait ReadBytesExt: io::Read {
    /// Reads an unsigned 8 bit integer from the underlying reader.
    ///
    /// Note that since this reads a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn read_u8(&mut self) -> Result<u8> {
        let mut buf = [0; 1];
        try!(read_full(self, &mut buf));
        Ok(buf[0])
    }

    /// Reads a signed 8 bit integer from the underlying reader.
    ///
    /// Note that since this reads a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn read_i8(&mut self) -> Result<i8> {
        let mut buf = [0; 1];
        try!(read_full(self, &mut buf));
        Ok(buf[0] as i8)
    }

    /// Reads an unsigned 16 bit integer from the underlying reader.
    fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
        let mut buf = [0; 2];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_u16(&buf))
    }

    /// Reads a signed 16 bit integer from the underlying reader.
    fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> {
        let mut buf = [0; 2];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_i16(&buf))
    }

    /// Reads an unsigned 32 bit integer from the underlying reader.
    fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
        let mut buf = [0; 4];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_u32(&buf))
    }

    /// Reads a signed 32 bit integer from the underlying reader.
    fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
        let mut buf = [0; 4];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_i32(&buf))
    }

    /// Reads an unsigned 64 bit integer from the underlying reader.
    fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_u64(&buf))
    }

    /// Reads a signed 64 bit integer from the underlying reader.
    fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_i64(&buf))
    }

    /// Reads an unsigned n-bytes integer from the underlying reader.
    fn read_uint<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf[..nbytes]));
        Ok(<T as ByteOrder>::read_uint(&buf[..nbytes], nbytes))
    }

    /// Reads a signed n-bytes integer from the underlying reader.
    fn read_int<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf[..nbytes]));
        Ok(<T as ByteOrder>::read_int(&buf[..nbytes], nbytes))
    }

    /// Reads a IEEE754 single-precision (4 bytes) floating point number from
    /// the underlying reader.
    fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
        let mut buf = [0; 4];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_f32(&buf))
    }

    /// Reads a IEEE754 double-precision (8 bytes) floating point number from
    /// the underlying reader.
    fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
        let mut buf = [0; 8];
        try!(read_full(self, &mut buf));
        Ok(<T as ByteOrder>::read_f64(&buf))
    }
}

/// All types that implement `Read` get methods defined in `ReadBytesExt`
/// for free.
impl<R: io::Read + ?Sized> ReadBytesExt for R {}

fn read_full<R: io::Read + ?Sized>(rdr: &mut R, buf: &mut [u8]) -> Result<()> {
    let mut nread = 0usize;
    while nread < buf.len() {
        match rdr.read(&mut buf[nread..]) {
            Ok(0) => return Err(Error::UnexpectedEOF),
            Ok(n) => nread += n,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
            Err(e) => return Err(error::FromError::from_error(e))
        }
    }
    Ok(())
}

fn write_all<W: io::Write + ?Sized>(wtr: &mut W, buf: &[u8]) -> Result<()> {
    wtr.write_all(buf).map_err(error::FromError::from_error)
}

/// Extends `Write` with methods for writing numbers. (For `std::io`.)
///
/// Most of the methods defined here have an unconstrained type parameter that
/// must be explicitly instantiated. Typically, it is instantiated with either
/// the `BigEndian` or `LittleEndian` types defined in this crate.
///
/// # Examples
///
/// Write unsigned 16 bit big-endian integers to a `Write`:
///
/// ```rust
/// use byteorder::{BigEndian, WriteBytesExt};
///
/// let mut wtr = vec![];
/// wtr.write_u16::<BigEndian>(517).unwrap();
/// wtr.write_u16::<BigEndian>(768).unwrap();
/// assert_eq!(wtr, vec![2, 5, 3, 0]);
/// ```
pub trait WriteBytesExt: io::Write {
    /// Writes an unsigned 8 bit integer to the underlying writer.
    ///
    /// Note that since this writes a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn write_u8(&mut self, n: u8) -> Result<()> {
        write_all(self, &[n])
    }

    /// Writes a signed 8 bit integer to the underlying writer.
    ///
    /// Note that since this writes a single byte, no byte order conversions
    /// are used. It is included for completeness.
    fn write_i8(&mut self, n: i8) -> Result<()> {
        write_all(self, &[n as u8])
    }

    /// Writes an unsigned 16 bit integer to the underlying writer.
    fn write_u16<T: ByteOrder>(&mut self, n: u16) -> Result<()> {
        let mut buf = [0; 2];
        <T as ByteOrder>::write_u16(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a signed 16 bit integer to the underlying writer.
    fn write_i16<T: ByteOrder>(&mut self, n: i16) -> Result<()> {
        let mut buf = [0; 2];
        <T as ByteOrder>::write_i16(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes an unsigned 32 bit integer to the underlying writer.
    fn write_u32<T: ByteOrder>(&mut self, n: u32) -> Result<()> {
        let mut buf = [0; 4];
        <T as ByteOrder>::write_u32(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a signed 32 bit integer to the underlying writer.
    fn write_i32<T: ByteOrder>(&mut self, n: i32) -> Result<()> {
        let mut buf = [0; 4];
        <T as ByteOrder>::write_i32(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes an unsigned 64 bit integer to the underlying writer.
    fn write_u64<T: ByteOrder>(&mut self, n: u64) -> Result<()> {
        let mut buf = [0; 8];
        <T as ByteOrder>::write_u64(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a signed 64 bit integer to the underlying writer.
    fn write_i64<T: ByteOrder>(&mut self, n: i64) -> Result<()> {
        let mut buf = [0; 8];
        <T as ByteOrder>::write_i64(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a IEEE754 single-precision (4 bytes) floating point number to
    /// the underlying writer.
    fn write_f32<T: ByteOrder>(&mut self, n: f32) -> Result<()> {
        let mut buf = [0; 4];
        <T as ByteOrder>::write_f32(&mut buf, n);
        write_all(self, &buf)
    }

    /// Writes a IEEE754 double-precision (8 bytes) floating point number to
    /// the underlying writer.
    fn write_f64<T: ByteOrder>(&mut self, n: f64) -> Result<()> {
        let mut buf = [0; 8];
        <T as ByteOrder>::write_f64(&mut buf, n);
        write_all(self, &buf)
    }
}

/// All types that implement `Write` get methods defined in `WriteBytesExt`
/// for free.
impl<W: io::Write + ?Sized> WriteBytesExt for W {}
<|endoftext|>


<commit_before>use address::{LENGTH, Address, Addressable};
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

struct NodeBucket<A: Addressable> {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, A>
}

impl<A: Addressable> NodeBucket<A> {
    pub fn new(k: usize) -> NodeBucket<A> {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn insert(&mut self, node: A) {
        let address = node.address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let partition = self.max.clone() / 2.to_biguint().unwrap();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::NodeBucket;

    #[derive(Clone,Copy,Debug,PartialEq,Eq)]
    struct Node {
        pub address: Address
    }

    impl Node {
        fn new(address: Address) -> Node {
            Node { address: address }
        }
    }

    impl Addressable for Node {
        fn address(&self) -> Address {
            self.address
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let node = Node::new(Address::for_content("some string"));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let a = Node::new(Address::for_content("node 1"));
        let b = Node::new(Address::for_content("node 2"));
        let c = Node::new(Address::for_content("node 1"));

        bucket.insert(a.clone());
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")], a);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        bucket.insert(Node::new(Address::for_content("node 3")));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        bucket.insert(Node::new(Address::for_content("node 1")));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket<Node> = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(4);
        let node_1 = Node::new(Address::from_str("0000000000000000000000000000000000000000"));
        let node_2 = Node::new(Address::from_str("7fffffffffffffffffffffffffffffffffffffff"));
        let node_3 = Node::new(Address::from_str("8000000000000000000000000000000000000000"));
        let node_4 = Node::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff"));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")], node_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")], node_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")], node_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")], node_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<commit_msg>Make NodeBucket struct public<commit_after>use address::{LENGTH, Address, Addressable};
use num::bigint::{BigUint, ToBigUint};
use std::collections::HashMap;
use num;

pub struct NodeBucket<A: Addressable> {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, A>
}

impl<A: Addressable> NodeBucket<A> {
    pub fn new(k: usize) -> NodeBucket<A> {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k)
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn insert(&mut self, node: A) {
        let address = node.address();
        if let Some(pos) = self.addresses.iter().position(|&a| a == address) {
            self.addresses.remove(pos);
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        } else if !self.is_full() {
            self.addresses.insert(0, address);
            self.nodes.insert(address, node);
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn split(&mut self) -> (Self, Self) {
        let partition = self.max.clone() / 2.to_biguint().unwrap();
        let addresses = self.addresses.clone();
        let (a_addresses, b_addresses): (Vec<Address>, Vec<Address>) = addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.drain() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min.clone(),
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes
        };
        let b = NodeBucket {
            k: self.k,
            min: partition.clone(),
            max: self.max.clone(),
            addresses: b_addresses,
            nodes: b_nodes
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::NodeBucket;

    #[derive(Clone,Copy,Debug,PartialEq,Eq)]
    struct Node {
        pub address: Address
    }

    impl Node {
        fn new(address: Address) -> Node {
            Node { address: address }
        }
    }

    impl Addressable for Node {
        fn address(&self) -> Address {
            self.address
        }
    }

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let node = Node::new(Address::for_content("some string"));
        bucket.insert(node);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        let a = Node::new(Address::for_content("node 1"));
        let b = Node::new(Address::for_content("node 2"));
        let c = Node::new(Address::for_content("node 1"));

        bucket.insert(a.clone());
        bucket.insert(b);
        bucket.insert(c);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")], a);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        bucket.insert(Node::new(Address::for_content("node 3")));
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Node::new(Address::for_content("node 1")));
        bucket.insert(Node::new(Address::for_content("node 2")));
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(8);
        bucket.insert(Node::new(Address::for_content("node 1")));
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket<Node> = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket<Node> = NodeBucket::new(4);
        let node_1 = Node::new(Address::from_str("0000000000000000000000000000000000000000"));
        let node_2 = Node::new(Address::from_str("7fffffffffffffffffffffffffffffffffffffff"));
        let node_3 = Node::new(Address::from_str("8000000000000000000000000000000000000000"));
        let node_4 = Node::new(Address::from_str("ffffffffffffffffffffffffffffffffffffffff"));

        bucket.insert(node_1);
        bucket.insert(node_2);
        bucket.insert(node_3);
        bucket.insert(node_4);

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")], node_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")], node_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")], node_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")], node_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use iron::modifiers::Header;
use self::super::{Options, Error};
use mime_guess::guess_mime_type_opt;
use self::super::util::{html_response, file_contains, ERROR_HTML, DIRECTORY_LISTING_HTML};
use iron::{headers, status, method, mime, IronResult, Listening, Response, Request, Handler, Iron};

#[derive(Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct HttpHandler {
    pub hosted_directory: (String, PathBuf),
    pub follow_symlinks: bool,
}

impl HttpHandler {
    pub fn new(opts: &Options) -> HttpHandler {
        HttpHandler {
            hosted_directory: opts.hosted_directory.clone(),
            follow_symlinks: opts.follow_symlinks,
        }
    }
}

impl Handler for HttpHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match req.method {
            method::Options => Ok(Response::with((status::Ok, Header(headers::Allow(vec![method::Options, method::Get]))))),
            method::Get => {
                let req_p = req.url.path().into_iter().filter(|p| !p.is_empty()).fold(self.hosted_directory.1.clone(), |cur, pp| cur.join(pp));
                if !req_p.exists() {
                    println!("{} requested nonexistant file {}", req.remote_addr, req_p.display());
                    Ok(Response::with((status::NotFound,
                                       "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                                       html_response(ERROR_HTML,
                                                     vec!["404 Not Found".to_string(),
                                                          format!("The requested entity \"{}\" doesn't exist.",
                                                                  &req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..]),
                                                          "".to_string()]))))
                } else if req_p.metadata().unwrap().file_type().is_symlink() && !self.follow_symlinks {
                    println!("{} requested nonexistant file {}", req.remote_addr, req_p.display());
                    Ok(Response::with((status::Forbidden,
                                       "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                                       html_response(ERROR_HTML,
                                                     vec!["403 Forbidden".to_string(),
                                                          format!("No permission to follow symlink \"{}\".",
                                                                  &req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..]),
                                                          "
\
                                                             Ask the server administrator to pass \"-s\" to <samp>http</samp> \
                                                             if you think this is unintended.\

"
                                                              .to_string()]))))
                } else if req_p.is_file() {
                    let mime_type = guess_mime_type_opt(&req_p).unwrap_or_else(|| if file_contains(&req_p, 0) {
                        "application/octet-stream".parse().unwrap()
                    } else {
                        "text/plain".parse().unwrap()
                    });
                    println!("{} was served file {} as {}", req.remote_addr, req_p.display(), mime_type);
                    Ok(Response::with((status::Ok, mime_type, req_p)))
                } else {
                    let relpath = (req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..].to_string() + "/").replace("//", "/");
                    println!("{} was served directory listing for {}", req.remote_addr, req_p.display());
                    Ok(Response::with((status::Ok,
                                       "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                                       html_response(DIRECTORY_LISTING_HTML,
                                                     vec![relpath.clone(),
                                                          req_p.read_dir().unwrap().map(Result::unwrap).fold("".to_string(), |cur, f| {
                        let fname = f.file_name().into_string().unwrap() +
                                    if !f.file_type().unwrap().is_file() {
                            "/"
                        } else {
                            ""
                        };
                        cur + "
" + &fname + "
\n"
                    })]))))
                }
            }
            ref m => {
                println!("{} used invalid request method {}", req.remote_addr, m);
                Ok(Response::with((status::NotImplemented,
                                   "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                                   html_response(ERROR_HTML,
                                                 vec!["501 Not Implemented".to_string(),
                                                      "This operation was not implemented.".to_string(),
                                                      format!("
Unsupported request method: {}.
Supported methods: OPTIONS and GET.
", m)]))))
            }
        }
    }
}

pub fn try_ports<H: Handler + Clone>(hndlr: H, from: u16, up_to: u16) -> Result<Listening, Error> {
    for port in from..up_to {
        match Iron::new(hndlr.clone()).http(("0.0.0.0", port)) {
            Ok(server) => return Ok(server),
            Err(error) => {
                if !error.to_string().contains("port") {
                    return Err(Error::Io {
                        desc: "server",
                        op: "start",
                        more: None,
                    });
                }
            }
        }
    }

    Err(Error::Io {
        desc: "server",
        op: "start",
        more: Some("no free ports"),
    })
}
<commit_msg>Extract each handle() match arm into function<commit_after>use std::path::PathBuf;
use iron::modifiers::Header;
use self::super::{Options, Error};
use mime_guess::guess_mime_type_opt;
use self::super::util::{html_response, file_contains, ERROR_HTML, DIRECTORY_LISTING_HTML};
use iron::{headers, status, method, mime, IronResult, Listening, Response, Request, Handler, Iron};

#[derive(Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct HttpHandler {
    pub hosted_directory: (String, PathBuf),
    pub follow_symlinks: bool,
}

impl HttpHandler {
    pub fn new(opts: &Options) -> HttpHandler {
        HttpHandler {
            hosted_directory: opts.hosted_directory.clone(),
            follow_symlinks: opts.follow_symlinks,
        }
    }
}

impl Handler for HttpHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match req.method {
            method::Options => self.handle_options(req),
            method::Get => {
                let req_p = req.url.path().into_iter().filter(|p| !p.is_empty()).fold(self.hosted_directory.1.clone(), |cur, pp| cur.join(pp));
                if !req_p.exists() {
                    self.handle_get_nonexistant(req, req_p)
                } else if req_p.metadata().unwrap().file_type().is_symlink() && !self.follow_symlinks {
                    self.handle_get_unfollowable_symlink(req, req_p)
                } else if req_p.is_file() {
                    self.handle_get_file(req, req_p)
                } else {
                    self.handle_get_dir(req, req_p)
                }
            }
            _ => self.handle_bad_method(req),
        }
    }
}

impl HttpHandler {
    fn handle_options(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} asked for options", req.remote_addr);
        Ok(Response::with((status::Ok, Header(headers::Allow(vec![method::Options, method::Get])))))
    }

    fn handle_get_nonexistant(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        println!("{} requested nonexistant file {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::NotFound,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["404 Not Found".to_string(),
                                              format!("The requested entity \"{}\" doesn't exist.",
                                                      &req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..]),
                                              "".to_string()]))))
    }

    fn handle_get_unfollowable_symlink(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        println!("{} requested unfollowable symlink {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::Forbidden,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["403 Forbidden".to_string(),
                                              format!("No permission to follow symlink \"{}\".",
                                                      &req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..]),
                                              "
Ask the server administrator to pass \"-s\" to <samp>http</samp> if you think this is unintended.
"
                                                  .to_string()]))))
    }

    fn handle_get_file(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        let mime_type = guess_mime_type_opt(&req_p).unwrap_or_else(|| if file_contains(&req_p, 0) {
            "application/octet-stream".parse().unwrap()
        } else {
            "text/plain".parse().unwrap()
        });
        println!("{} was served file {} as {}", req.remote_addr, req_p.display(), mime_type);
        Ok(Response::with((status::Ok, mime_type, req_p)))
    }

    fn handle_get_dir(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        let relpath = (req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..].to_string() + "/").replace("//", "/");
        println!("{} was served directory listing for {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::Ok,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(DIRECTORY_LISTING_HTML,
                                         vec![relpath.clone(),
                                              req_p.read_dir().unwrap().map(Result::unwrap).fold("".to_string(), |cur, f| {
            let fname = f.file_name().into_string().unwrap() +
                        if !f.file_type().unwrap().is_file() {
                "/"
            } else {
                ""
            };
            cur + "
" + &fname + "
\n"
        })]))))
    }

    fn handle_bad_method(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} used invalid request method {}", req.remote_addr, req.method);
        Ok(Response::with((status::NotImplemented,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["501 Not Implemented".to_string(),
                                              "This operation was not implemented.".to_string(),
                                              format!("
Unsupported request method: {}.
Supported methods: OPTIONS and GET.
", req.method)]))))
    }
}

pub fn try_ports<H: Handler + Clone>(hndlr: H, from: u16, up_to: u16) -> Result<Listening, Error> {
    for port in from..up_to {
        match Iron::new(hndlr.clone()).http(("0.0.0.0", port)) {
            Ok(server) => return Ok(server),
            Err(error) => {
                if !error.to_string().contains("port") {
                    return Err(Error::Io {
                        desc: "server",
                        op: "start",
                        more: None,
                    });
                }
            }
        }
    }

    Err(Error::Io {
        desc: "server",
        op: "start",
        more: Some("no free ports"),
    })
}
<|endoftext|>


<commit_before>//! Rust representations of docker json structures

use std::collections::HashMap;

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct SearchResult {
    pub description: String,
    pub is_official: bool,
    pub is_automated: bool,
    pub name: String,
    pub star_count: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Image {
    pub Created: u64,
    pub Id: String,
    pub ParentId: String,
    pub Labels: Option<HashMap<String, String>>,
    pub RepoTags: Option<Vec<String>>,
    pub RepoDigests: Option<Vec<String>>,
    pub VirtualSize: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ImageDetails {
    pub Architecture: String,
    pub Author: String,
    pub Comment: String,
    pub Config: Config,
    pub Created: String,
    pub DockerVersion: String,
    pub Id: String,
    pub Os: String,
    pub Parent: String,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Container {
    pub Created: u64,
    pub Command: String,
    pub Id: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    pub Names: Vec<String>,
    pub Ports: Vec<Port>,
    pub Status: String,
    pub SizeRw: Option<u64>,
    pub SizeRootFs: Option<u64>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct ContainerDetails {
    pub AppArmorProfile: String,
    pub Args: Vec<String>,
    pub Config: Config,
    pub Created: String,
    pub Driver: String,
    // pub ExecIDs: ??
    pub HostConfig: HostConfig,
    pub HostnamePath: String,
    pub HostsPath: String,
    pub LogPath: String,
    pub Id: String,
    pub Image: String,
    pub MountLabel: String,
    pub Name: String,
    pub NetworkSettings: NetworkSettings,
    pub Path: String,
    pub ProcessLabel: String,
    pub ResolvConfPath: String,
    pub RestartCount: u64,
    pub State: State,
    pub Mounts: Vec<Mount>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct Mount {
    pub Source: String,
    pub Destination: String,
    pub Mode: String,
    pub RW: bool,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct State {
    pub Error: String,
    pub ExitCode: u64,
    pub FinishedAt: String,
    pub OOMKilled: bool,
    pub Paused: bool,
    pub Pid: u64,
    pub Restarting: bool,
    pub Running: bool,
    pub StartedAt: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct NetworkSettings {
    pub Bridge: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub MacAddress: String, /*    pub PortMapping: Option<???>,
                             *   pub Ports: Option<???> */
    pub Networks: HashMap<String, NetworkEntry>
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct NetworkEntry {
    pub NetworkID: String,
    pub EndpointID: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub IPv6Gateway: String,
    pub GlobalIPv6Address: String,
    pub GlobalIPv6PrefixLen: u64,
    pub MacAddress: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct HostConfig {
    pub CgroupParent: Option<String>,
    pub ContainerIDFile: String,
    pub CpuShares: Option<u64>,
    pub CpusetCpus: Option<String>,
    pub Memory: Option<u64>,
    pub MemorySwap: Option<i64>,
    pub NetworkMode: String,
    pub PidMode: Option<String>,
    // pub PortBindings: ???
    pub Privileged: bool,
    pub PublishAllPorts: bool,
    pub ReadonlyRootfs: Option<bool>, /* pub RestartPolicy: ???
                                       * pub SecurityOpt: Option<???>,
                                       * pub Ulimits: Option<???>
                                       * pub VolumesFrom: Option<??/> */
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct Config {
    pub AttachStderr: bool,
    pub AttachStdin: bool,
    pub AttachStdout: bool,
    pub Cmd: Option<Vec<String>>,
    pub Domainname: String,
    pub Entrypoint: Option<Vec<String>>,
    pub Env: Option<Vec<String>>,
    // ExposedPorts
    pub Hostname: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    // pub MacAddress: String,
    pub OnBuild: Option<Vec<String>>,
    // pub NetworkDisabled: bool,
    pub OpenStdin: bool,
    pub StdinOnce: bool,
    pub Tty: bool,
    pub User: String,
    pub WorkingDir: String,
}

impl Config {
    pub fn env(&self) -> HashMap<String, String> {
        let mut map = HashMap::new();
        match self.Env {
            Some(ref vars) => {
                for e in vars {
                    let pair: Vec<&str> = e.split("=").collect();
                    map.insert(pair[0].to_owned(), pair[1].to_owned());
                }
            }
            _ => (),
        };
        map
    }
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Port {
    pub IP: Option<String>,
    pub PrivatePort: u64,
    pub PublicPort: Option<u64>,
    pub Type: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Stats {
    pub read: String,
    pub networks: HashMap<String, Network>,
    pub memory_stats: MemoryStats,
    pub blkio_stats: BlkioStats,
    pub cpu_stats: CpuStats,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Network {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct IPAM {
    pub Driver: String,
    pub Config: Vec<HashMap<String, String>>,
    pub Options: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkDetails {
    pub Name: String,
    pub Id: String,
    pub Scope: String,
    pub Driver: String,
    pub EnableIPv6: bool,
    pub IPAM: IPAM,
    pub Internal: bool,
    pub Attachable: bool,
    pub Containers: HashMap<String, NetworkContainerDetails>,
    pub Options: Option<HashMap<String, String>>,
    pub Labels: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkContainerDetails {
    pub EndpointID: String,
    pub MacAddress: String,
    pub IPv4Address: String,
    pub IPv6Address: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkCreateInfo {
    pub Id: String,
    pub Warning: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStats {
    pub max_usage: u64,
    pub usage: u64,
    pub failcnt: Option<u64>,
    pub limit: u64,
    pub stats: MemoryStat,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStat {
    pub total_pgmajfault: u64,
    pub cache: u64,
    pub mapped_file: u64,
    pub total_inactive_file: u64,
    pub pgpgout: u64,
    pub rss: u64,
    pub total_mapped_file: u64,
    pub writeback: u64,
    pub unevictable: u64,
    pub pgpgin: u64,
    pub total_unevictable: u64,
    pub pgmajfault: u64,
    pub total_rss: u64,
    pub total_rss_huge: u64,
    pub total_writeback: u64,
    pub total_inactive_anon: u64,
    pub rss_huge: u64,
    pub hierarchical_memory_limit: u64,
    pub hierarchical_memsw_limit: u64,
    pub total_pgfault: u64,
    pub total_active_file: u64,
    pub active_anon: u64,
    pub total_active_anon: u64,
    pub total_pgpgout: u64,
    pub total_cache: u64,
    pub inactive_anon: u64,
    pub active_file: u64,
    pub pgfault: u64,
    pub inactive_file: u64,
    pub total_pgpgin: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct CpuStats {
    pub cpu_usage: CpuUsage,
    pub system_cpu_usage: u64,
    pub throttling_data: ThrottlingData,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct CpuUsage {
    pub percpu_usage: Vec<u64>,
    pub usage_in_usermode: u64,
    pub total_usage: u64,
    pub usage_in_kernelmode: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ThrottlingData {
    pub periods: u64,
    pub throttled_periods: u64,
    pub throttled_time: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStats {
    pub io_service_bytes_recursive: Vec<BlkioStat>,
    pub io_serviced_recursive: Vec<BlkioStat>,
    pub io_queue_recursive: Vec<BlkioStat>,
    pub io_service_time_recursive: Vec<BlkioStat>,
    pub io_wait_time_recursive: Vec<BlkioStat>,
    pub io_merged_recursive: Vec<BlkioStat>,
    pub io_time_recursive: Vec<BlkioStat>,
    pub sectors_recursive: Vec<BlkioStat>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStat {
    pub major: u64,
    pub minor: u64,
    pub op: String,
    pub value: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Change {
    pub Kind: u64,
    pub Path: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Top {
    pub Titles: Vec<String>,
    pub Processes: Vec<Vec<String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Version {
    pub ApiVersion: String,
    pub Version: String,
    pub GitCommit: String,
    pub GoVersion: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Info {
    pub Containers: u64,
    pub Images: u64,
    pub Driver: String,
    pub DockerRootDir: String,
    pub DriverStatus: Vec<Vec<String>>,
    pub ID: String,
    pub KernelVersion: String,
    // pub Labels: Option<???>,
    pub MemTotal: u64,
    pub MemoryLimit: bool,
    pub NCPU: u64,
    pub NEventsListener: u64,
    pub NGoroutines: u64,
    pub Name: String,
    pub OperatingSystem: String,
    // pub RegistryConfig:???
    pub SwapLimit: bool,
    pub SystemTime: Option<String>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerCreateInfo {
    pub Id: String,
    pub Warnings: Option<Vec<String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct History {
    pub Id: String,
    pub Created: u64,
    pub CreatedBy: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Exit {
    pub StatusCode: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Event {
    pub Type: String,
    pub Action: String,
    pub Actor: Actor,
    pub status: Option<String>,
    pub id: Option<String>,
    pub from: Option<String>,
    pub time: u64,
    pub timeNano: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Actor {
    pub ID: String,
    pub Attributes: HashMap<String, String>,
}

#[derive(Clone, Debug)]
pub enum Status {
    Untagged(String),
    Deleted(String),
}
<commit_msg>Fixes a crash when the Docker API returns the 'Labels' value as 'null'<commit_after>//! Rust representations of docker json structures

use std::collections::HashMap;

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct SearchResult {
    pub description: String,
    pub is_official: bool,
    pub is_automated: bool,
    pub name: String,
    pub star_count: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Image {
    pub Created: u64,
    pub Id: String,
    pub ParentId: String,
    pub Labels: Option<HashMap<String, String>>,
    pub RepoTags: Option<Vec<String>>,
    pub RepoDigests: Option<Vec<String>>,
    pub VirtualSize: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ImageDetails {
    pub Architecture: String,
    pub Author: String,
    pub Comment: String,
    pub Config: Config,
    pub Created: String,
    pub DockerVersion: String,
    pub Id: String,
    pub Os: String,
    pub Parent: String,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Container {
    pub Created: u64,
    pub Command: String,
    pub Id: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    pub Names: Vec<String>,
    pub Ports: Vec<Port>,
    pub Status: String,
    pub SizeRw: Option<u64>,
    pub SizeRootFs: Option<u64>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct ContainerDetails {
    pub AppArmorProfile: String,
    pub Args: Vec<String>,
    pub Config: Config,
    pub Created: String,
    pub Driver: String,
    // pub ExecIDs: ??
    pub HostConfig: HostConfig,
    pub HostnamePath: String,
    pub HostsPath: String,
    pub LogPath: String,
    pub Id: String,
    pub Image: String,
    pub MountLabel: String,
    pub Name: String,
    pub NetworkSettings: NetworkSettings,
    pub Path: String,
    pub ProcessLabel: String,
    pub ResolvConfPath: String,
    pub RestartCount: u64,
    pub State: State,
    pub Mounts: Vec<Mount>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct Mount {
    pub Source: String,
    pub Destination: String,
    pub Mode: String,
    pub RW: bool,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct State {
    pub Error: String,
    pub ExitCode: u64,
    pub FinishedAt: String,
    pub OOMKilled: bool,
    pub Paused: bool,
    pub Pid: u64,
    pub Restarting: bool,
    pub Running: bool,
    pub StartedAt: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct NetworkSettings {
    pub Bridge: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub MacAddress: String, /*    pub PortMapping: Option<???>,
                             *   pub Ports: Option<???> */
    pub Networks: HashMap<String, NetworkEntry>
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct NetworkEntry {
    pub NetworkID: String,
    pub EndpointID: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub IPv6Gateway: String,
    pub GlobalIPv6Address: String,
    pub GlobalIPv6PrefixLen: u64,
    pub MacAddress: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct HostConfig {
    pub CgroupParent: Option<String>,
    pub ContainerIDFile: String,
    pub CpuShares: Option<u64>,
    pub CpusetCpus: Option<String>,
    pub Memory: Option<u64>,
    pub MemorySwap: Option<i64>,
    pub NetworkMode: String,
    pub PidMode: Option<String>,
    // pub PortBindings: ???
    pub Privileged: bool,
    pub PublishAllPorts: bool,
    pub ReadonlyRootfs: Option<bool>, /* pub RestartPolicy: ???
                                       * pub SecurityOpt: Option<???>,
                                       * pub Ulimits: Option<???>
                                       * pub VolumesFrom: Option<??/> */
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)]
#[allow(non_snake_case)]
pub struct Config {
    pub AttachStderr: bool,
    pub AttachStdin: bool,
    pub AttachStdout: bool,
    pub Cmd: Option<Vec<String>>,
    pub Domainname: String,
    pub Entrypoint: Option<Vec<String>>,
    pub Env: Option<Vec<String>>,
    // ExposedPorts
    pub Hostname: String,
    pub Image: String,
    pub Labels: Option<HashMap<String, String>>,
    // pub MacAddress: String,
    pub OnBuild: Option<Vec<String>>,
    // pub NetworkDisabled: bool,
    pub OpenStdin: bool,
    pub StdinOnce: bool,
    pub Tty: bool,
    pub User: String,
    pub WorkingDir: String,
}

impl Config {
    pub fn env(&self) -> HashMap<String, String> {
        let mut map = HashMap::new();
        match self.Env {
            Some(ref vars) => {
                for e in vars {
                    let pair: Vec<&str> = e.split("=").collect();
                    map.insert(pair[0].to_owned(), pair[1].to_owned());
                }
            }
            _ => (),
        };
        map
    }
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Port {
    pub IP: Option<String>,
    pub PrivatePort: u64,
    pub PublicPort: Option<u64>,
    pub Type: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Stats {
    pub read: String,
    pub networks: HashMap<String, Network>,
    pub memory_stats: MemoryStats,
    pub blkio_stats: BlkioStats,
    pub cpu_stats: CpuStats,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Network {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct IPAM {
    pub Driver: String,
    pub Config: Vec<HashMap<String, String>>,
    pub Options: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkDetails {
    pub Name: String,
    pub Id: String,
    pub Scope: String,
    pub Driver: String,
    pub EnableIPv6: bool,
    pub IPAM: IPAM,
    pub Internal: bool,
    pub Attachable: bool,
    pub Containers: HashMap<String, NetworkContainerDetails>,
    pub Options: Option<HashMap<String, String>>,
    pub Labels: Option<HashMap<String, String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkContainerDetails {
    pub EndpointID: String,
    pub MacAddress: String,
    pub IPv4Address: String,
    pub IPv6Address: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkCreateInfo {
    pub Id: String,
    pub Warning: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStats {
    pub max_usage: u64,
    pub usage: u64,
    pub failcnt: Option<u64>,
    pub limit: u64,
    pub stats: MemoryStat,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStat {
    pub total_pgmajfault: u64,
    pub cache: u64,
    pub mapped_file: u64,
    pub total_inactive_file: u64,
    pub pgpgout: u64,
    pub rss: u64,
    pub total_mapped_file: u64,
    pub writeback: u64,
    pub unevictable: u64,
    pub pgpgin: u64,
    pub total_unevictable: u64,
    pub pgmajfault: u64,
    pub total_rss: u64,
    pub total_rss_huge: u64,
    pub total_writeback: u64,
    pub total_inactive_anon: u64,
    pub rss_huge: u64,
    pub hierarchical_memory_limit: u64,
    pub hierarchical_memsw_limit: u64,
    pub total_pgfault: u64,
    pub total_active_file: u64,
    pub active_anon: u64,
    pub total_active_anon: u64,
    pub total_pgpgout: u64,
    pub total_cache: u64,
    pub inactive_anon: u64,
    pub active_file: u64,
    pub pgfault: u64,
    pub inactive_file: u64,
    pub total_pgpgin: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct CpuStats {
    pub cpu_usage: CpuUsage,
    pub system_cpu_usage: u64,
    pub throttling_data: ThrottlingData,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct CpuUsage {
    pub percpu_usage: Vec<u64>,
    pub usage_in_usermode: u64,
    pub total_usage: u64,
    pub usage_in_kernelmode: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ThrottlingData {
    pub periods: u64,
    pub throttled_periods: u64,
    pub throttled_time: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStats {
    pub io_service_bytes_recursive: Vec<BlkioStat>,
    pub io_serviced_recursive: Vec<BlkioStat>,
    pub io_queue_recursive: Vec<BlkioStat>,
    pub io_service_time_recursive: Vec<BlkioStat>,
    pub io_wait_time_recursive: Vec<BlkioStat>,
    pub io_merged_recursive: Vec<BlkioStat>,
    pub io_time_recursive: Vec<BlkioStat>,
    pub sectors_recursive: Vec<BlkioStat>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStat {
    pub major: u64,
    pub minor: u64,
    pub op: String,
    pub value: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Change {
    pub Kind: u64,
    pub Path: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Top {
    pub Titles: Vec<String>,
    pub Processes: Vec<Vec<String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Version {
    pub ApiVersion: String,
    pub Version: String,
    pub GitCommit: String,
    pub GoVersion: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Info {
    pub Containers: u64,
    pub Images: u64,
    pub Driver: String,
    pub DockerRootDir: String,
    pub DriverStatus: Vec<Vec<String>>,
    pub ID: String,
    pub KernelVersion: String,
    // pub Labels: Option<???>,
    pub MemTotal: u64,
    pub MemoryLimit: bool,
    pub NCPU: u64,
    pub NEventsListener: u64,
    pub NGoroutines: u64,
    pub Name: String,
    pub OperatingSystem: String,
    // pub RegistryConfig:???
    pub SwapLimit: bool,
    pub SystemTime: Option<String>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerCreateInfo {
    pub Id: String,
    pub Warnings: Option<Vec<String>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct History {
    pub Id: String,
    pub Created: u64,
    pub CreatedBy: String,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Exit {
    pub StatusCode: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Event {
    pub Type: String,
    pub Action: String,
    pub Actor: Actor,
    pub status: Option<String>,
    pub id: Option<String>,
    pub from: Option<String>,
    pub time: u64,
    pub timeNano: u64,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Actor {
    pub ID: String,
    pub Attributes: HashMap<String, String>,
}

#[derive(Clone, Debug)]
pub enum Status {
    Untagged(String),
    Deleted(String),
}
<|endoftext|>


<commit_before>use libc::*;
use sdl2_sys;
use std::ffi::CString;

pub fn get_proc_address(name: &str) -> *const c_void {
    unsafe {
        sdl2_sys::SDL_GL_GetProcAddress(CString::new(name)
                                            .expect("could not convert name to a CString")
                                            .as_ptr())
    }
}

pub fn get_current_context() -> u32 {
    unsafe { sdl2_sys::SDL_GL_GetCurrentContext() as u32 }
}
<commit_msg>Fix undefined behaviour in sdl::get_proc_address()<commit_after>use libc::*;
use sdl2_sys;
use std::ffi::CString;

pub fn get_proc_address(name: &str) -> *const c_void {
    let cstring = CString::new(name).expect("could not convert name to a CString");
    unsafe { sdl2_sys::SDL_GL_GetProcAddress(cstring.as_ptr()) }
}

pub fn get_current_context() -> u32 {
    unsafe { sdl2_sys::SDL_GL_GetCurrentContext() as u32 }
}
<|endoftext|>


<commit_before>use std::*;
use std::iter::*;
use std::sync::atomic::*;
use rand::{Rng, XorShiftRng};
use types::*;
use config::*;
use player::*;
use field::*;

#[unsafe_no_drop_flag]
struct UctNode {
  wins: AtomicUsize,
  draws: AtomicUsize,
  visits: AtomicUsize,
  pos: Pos,
  child: AtomicPtr<UctNode>,
  sibling: Option<Box<UctNode>>
}

unsafe impl Send for UctNode { }

impl Drop for UctNode {
  fn drop(&mut self) {
    self.clear_child();
  }
}

impl UctNode {
  pub fn new(pos: Pos) -> UctNode {
    UctNode {
      wins: AtomicUsize::new(0),
      draws: AtomicUsize::new(0),
      visits: AtomicUsize::new(0),
      pos: pos,
      child: AtomicPtr::new(ptr::null_mut()),
      sibling: None
    }
  }

  pub fn get_pos(&self) -> Pos {
    self.pos
  }

  pub fn set_pos(&mut self, pos: Pos) {
    self.pos = pos;
  }

  pub fn get_sibling(&mut self) -> Option<Box<UctNode>> {
    mem::replace(&mut self.sibling, None)
  }

  pub fn get_sibling_ref<'a>(&'a self) -> Option<&'a UctNode> {
    self.sibling.as_ref().map(|b| &**b)
  }

  pub fn get_sibling_mut<'a>(&'a mut self) -> Option<&'a mut UctNode> {
    self.sibling.as_mut().map(|b| &mut **b)
  }

  pub fn clear_sibling(&mut self) {
    self.sibling = None;
  }

  pub fn set_sibling(&mut self, sibling: Box<UctNode>) {
    self.sibling = Some(sibling);
  }

  pub fn set_sibling_option(&mut self, sibling: Option<Box<UctNode>>) {
    self.sibling = sibling;
  }

  pub fn get_child(&self) -> Option<Box<UctNode>> {
    let ptr = self.child.swap(ptr::null_mut(), Ordering::Relaxed);
    if !ptr.is_null() {
      Some(unsafe { mem::transmute(ptr) })
    } else {
      None
    }
  }

  pub fn get_child_ref<'a>(&'a self) -> Option<&'a UctNode> {
    let ptr = self.child.load(Ordering::Relaxed);
    if !ptr.is_null() {
      Some(unsafe { &*ptr })
    } else {
      None
    }
  }

  pub fn get_child_mut<'a>(&'a mut self) -> Option<&'a mut UctNode> {
    let ptr = self.child.load(Ordering::Relaxed);
    if !ptr.is_null() {
      Some(unsafe { &mut *ptr })
    } else {
      None
    }
  }

  pub fn clear_child(&self) {
    let ptr = self.child.swap(ptr::null_mut(), Ordering::Relaxed);
    if !ptr.is_null() {
      drop::<Box<UctNode>>(unsafe { mem::transmute(ptr) });
    }
  }

  pub fn set_child(&self, child: Box<UctNode>) {
    let ptr = self.child.swap(unsafe { mem::transmute(child) }, Ordering::Relaxed);
    if !ptr.is_null() {
      drop::<Box<UctNode>>(unsafe { mem::transmute(ptr) });
    }
  }

  pub fn set_child_if_empty(&self, child: Box<UctNode>) {
    let child_ptr = unsafe { mem::transmute(child) };
    let ptr = self.child.compare_and_swap(ptr::null_mut(), child_ptr, Ordering::Relaxed);
    if !ptr.is_null() {
      drop::<Box<UctNode>>(unsafe { mem::transmute(child_ptr) });
    }
  }

  pub fn get_visits(&self) -> usize {
    self.visits.load(Ordering::Relaxed)
  }

  pub fn get_wins(&self) -> usize {
    self.wins.load(Ordering::Relaxed)
  }

  pub fn get_draws(&self) -> usize {
    self.draws.load(Ordering::Relaxed)
  }

  pub fn add_win(&self) {
    self.visits.fetch_add(1, Ordering::Relaxed);
    self.wins.fetch_add(1, Ordering::Relaxed);
  }

  pub fn add_draw(&self) {
    self.visits.fetch_add(1, Ordering::Relaxed);
    self.draws.fetch_add(1, Ordering::Relaxed);
  }

  pub fn add_loose(&self) {
    self.visits.fetch_add(1, Ordering::Relaxed);
  }

  pub fn clear_stats(&self) {
    self.wins.store(0, Ordering::Relaxed);
    self.draws.store(0, Ordering::Relaxed);
    self.visits.store(0, Ordering::Relaxed);
  }
}

pub struct UctRoot {
  node: Option<Box<UctNode>>,
  moves: Vec<Pos>,
  moves_field: Vec<Pos>,
  player: Player,
  moves_count: usize,
  hash: u64
}

impl UctRoot {
  fn clear(&mut self) {
    self.node = None;
    self.moves.clear();
    for i in self.moves_field.iter_mut() {
      *i = 0;
    }
    self.player = Player::Red;
    self.moves_count = 0;
    self.hash = 0;
  }

  fn init(&mut self, field: &Field, player: Player) {
    self.node = Some(Box::new(UctNode::new(0)));
    self.player = player;
    let width = field.width();
    for &start_pos in field.points_seq() {
      wave(width, start_pos, |pos| {
        if self.moves_field[pos] != start_pos && field.is_putting_allowed(pos) && manhattan(width, start_pos, pos) <= UCT_RADIUS {
          if self.moves_field[pos] == 0 {
            self.moves.push(pos);
          }
          self.moves_field[pos] = start_pos;
          true
        } else {
          false
        }
      });
    }
  }

  fn expand_node(node: &mut UctNode, moves: &Vec<Pos>) {
    if node.get_child_ref().is_none() {
      if node.get_visits() == usize::max_value() {
        node.clear_stats();
      }
    } else {
      let mut next = node.get_child_mut();
      while next.as_ref().unwrap().get_sibling_ref().is_some() {
        UctRoot::expand_node(*next.as_mut().unwrap(), moves);
        next = next.unwrap().get_sibling_mut();
      }
      UctRoot::expand_node(*next.as_mut().unwrap(), moves);
      for &pos in moves {
        next.as_mut().unwrap().set_sibling(Box::new(UctNode::new(pos)));
        next = next.unwrap().get_sibling_mut();
      }
    }
  }

  fn update(&mut self, field: &Field, player: Player) {
    if self.node.is_some() && field.hash_at(self.moves_count) != Some(self.hash) {
      self.clear();
    }
    if self.node.is_none() {
      self.init(field, player);
    } else {
      let points_seq = field.points_seq();
      let moves_count = field.moves_count();
      loop {
        if self.moves_count == moves_count {
          break;
        }
        let next_pos = points_seq[self.moves_count];
        if !field.is_players_point(next_pos, self.player) {
          self.clear();
          self.init(field, player);
          break;
        }
        let mut next = self.node.as_ref().unwrap().get_child();
        while next.is_some() && next.as_ref().unwrap().pos != next_pos {
          next = next.unwrap().get_sibling();
        }
        match next.as_mut() {
          Some(node) => {
            node.clear_sibling();
          },
          None => {
            self.clear();
            self.init(field, player);
            break;
          }
        }
        self.node = next;
        let moves_field = &mut self.moves_field;
        self.moves.retain(|&pos| {
          if field.is_putting_allowed(pos) {
            true
          } else {
            moves_field[pos] = 0;
            false
          }
        });
        let mut added_moves = Vec::new();
        let width = field.width();
        wave(width, next_pos, |pos| {
          if moves_field[pos] != next_pos && field.is_putting_allowed(pos) && manhattan(width, next_pos, pos) <= UCT_RADIUS {
            if moves_field[pos] == 0 {
              added_moves.push(pos);
            }
            moves_field[pos] = next_pos;
            true
          } else {
            false
          }
        });
        UctRoot::expand_node(self.node.as_mut().unwrap(), &added_moves);
        self.moves_count += 1;
        self.player = self.player.next();
      }
    }
  }

  pub fn new(length: Pos) -> UctRoot {
    UctRoot {
      node: None,
      moves: Vec::with_capacity(length),
      moves_field: repeat(0).take(length).collect(),
      player: Player::Red,
      moves_count: 0,
      hash: 0
    }
  }

  fn play_random_game<T: Rng>(field: &mut Field, mut player: Player, rng: &mut T, possible_moves: &mut Vec<Pos>) -> Option<Player> {
    rng.shuffle(possible_moves);
    let mut putted: CoordProd = 0;
    for &pos in possible_moves.iter() {
      if field.is_putting_allowed(pos) && !field.is_empty_base(pos) {
        field.put_point(pos, player);
        player = player.next();
        putted += 1;
      }
    }
    let red_score = field.score(Player::Red);
    let result = if red_score > 0 {
      Some(Player::Red)
    } else if red_score < 0 {
      Some(Player::Black)
    } else {
      None
    };
    for _ in 0 .. putted {
      field.undo();
    }
    result
  }

  fn ucb(parent: &UctNode, node: &UctNode) -> f32 {
    let wins = node.get_wins() as f32;
    let draws = node.get_draws() as f32;
    let visits = node.get_visits() as f32;
    let parent_visits = parent.get_visits() as f32;
    let win_rate = (wins + draws * UCT_DRAW_WEIGHT) / visits;
    let uct = match UCB_TYPE {
      UcbType::Ucb1 => UCTK * f32::sqrt(2.0 * f32::ln(parent_visits) / visits),
      UcbType::Ucb1Tuned => {
        let v = (wins + draws * UCT_DRAW_WEIGHT * UCT_DRAW_WEIGHT) / visits - win_rate * win_rate + f32::sqrt(2.0 * f32::ln(parent_visits) / visits);
        UCTK * f32::sqrt(v.min(0.25) * f32::ln(parent_visits) / visits)
      }
    };
    win_rate + uct
  }

  fn create_children(field: &Field, possible_moves: &Vec<Pos>, node: &UctNode) {
    let mut children = None;
    for &pos in possible_moves {
      if field.is_putting_allowed(pos) {
        let mut cur_child = Box::new(UctNode::new(pos));
        cur_child.set_sibling_option(children);
        children = Some(cur_child);
      }
    }
    for child in children {
      node.set_child_if_empty(child)
    }
  }

  fn uct_select<'a, T: Rng>(node: &'a UctNode, rng: &mut T) -> Option<&'a UctNode> {
    let mut best_uct = 0f32;
    let mut result = None;
    let mut next = node.get_child_ref();
    while next.is_some() {
      let next_node = next.unwrap();
      let visits = next_node.get_visits();
      let wins = next_node.get_wins();
      let uct_value = if visits == usize::max_value() {
        if wins == usize::max_value() {
          100000.0
        } else {
          -1.0
        }
      } else if visits > 0 {
        UctRoot::ucb(node, next_node)
      } else {
        10000.0 + (rng.gen::<u16>() % 1000) as f32
      };
      if uct_value > best_uct {
        best_uct = uct_value;
        result = Some(next_node);
      }
      next = next_node.get_sibling_ref();
    }
    result
  }

  fn play_simulation_rec<T: Rng>(field: &mut Field, node: &UctNode, possible_moves: &mut Vec<Pos>, rng: &mut T, depth: Depth) {

  }

  fn play_simulation<T: Rng>(field: &mut Field, rng: &mut T) {

  }

  fn best_move_generic<T: Rng>(&mut self, field: &Field, player: Player, rng: &mut T, should_stop: &AtomicBool) -> Option<Pos> {
    self.update(field, player);
    let mut guards = Vec::with_capacity(4);
    for _ in 0 .. 4 {
      let xor_shift_rng = rng.gen::<XorShiftRng>();
      guards.push(thread::scoped(|| {
        let mut local_field = field.clone();
        let mut local_rng = xor_shift_rng;
        while !should_stop.load(Ordering::Relaxed) {
          UctRoot::play_simulation(&mut local_field, &mut local_rng);
        }
      }));
    }
    drop(guards);
    let mut best_uct = 0f32;
    let mut result = None;
    for root in self.node.as_ref() {
      let mut next = root.get_child_ref();
      loop {
        match next {
          Some(next_node) => {
            let uct_value = UctRoot::ucb(root, next_node);
            if uct_value > best_uct {
              best_uct = uct_value;
              result = Some(next_node.get_pos());
            }
            next = next_node.get_sibling_ref();
          },
          None => break
        }
      }
    }
    result
  }

  pub fn best_move<T: Rng>(&mut self, field: &Field, player: Player, rng: &mut T, time: Time) -> Option<Pos> {
    let should_stop = AtomicBool::new(false);
    let guard = thread::scoped(|| {
      thread::sleep_ms(time);
      should_stop.store(true, Ordering::Relaxed);
    });
    let result = self.best_move_generic(field, player, rng, &should_stop);
    drop(guard);
    result
  }

  //pub fn estimates
}
<commit_msg>Small refactoring.<commit_after>use std::*;
use std::iter::*;
use std::sync::atomic::*;
use rand::{Rng, XorShiftRng};
use types::*;
use config::*;
use player::*;
use field::*;

#[unsafe_no_drop_flag]
struct UctNode {
  wins: AtomicUsize,
  draws: AtomicUsize,
  visits: AtomicUsize,
  pos: Pos,
  child: AtomicPtr<UctNode>,
  sibling: Option<Box<UctNode>>
}

unsafe impl Send for UctNode { }

impl Drop for UctNode {
  fn drop(&mut self) {
    self.clear_child();
  }
}

impl UctNode {
  pub fn new(pos: Pos) -> UctNode {
    UctNode {
      wins: AtomicUsize::new(0),
      draws: AtomicUsize::new(0),
      visits: AtomicUsize::new(0),
      pos: pos,
      child: AtomicPtr::new(ptr::null_mut()),
      sibling: None
    }
  }

  pub fn get_pos(&self) -> Pos {
    self.pos
  }

  pub fn set_pos(&mut self, pos: Pos) {
    self.pos = pos;
  }

  pub fn get_sibling(&mut self) -> Option<Box<UctNode>> {
    mem::replace(&mut self.sibling, None)
  }

  pub fn get_sibling_ref<'a>(&'a self) -> Option<&'a UctNode> {
    self.sibling.as_ref().map(|b| &**b)
  }

  pub fn get_sibling_mut<'a>(&'a mut self) -> Option<&'a mut UctNode> {
    self.sibling.as_mut().map(|b| &mut **b)
  }

  pub fn clear_sibling(&mut self) {
    self.sibling = None;
  }

  pub fn set_sibling(&mut self, sibling: Box<UctNode>) {
    self.sibling = Some(sibling);
  }

  pub fn set_sibling_option(&mut self, sibling: Option<Box<UctNode>>) {
    self.sibling = sibling;
  }

  pub fn get_child(&self) -> Option<Box<UctNode>> {
    let ptr = self.child.swap(ptr::null_mut(), Ordering::Relaxed);
    if !ptr.is_null() {
      Some(unsafe { mem::transmute(ptr) })
    } else {
      None
    }
  }

  pub fn get_child_ref<'a>(&'a self) -> Option<&'a UctNode> {
    let ptr = self.child.load(Ordering::Relaxed);
    if !ptr.is_null() {
      Some(unsafe { &*ptr })
    } else {
      None
    }
  }

  pub fn get_child_mut<'a>(&'a mut self) -> Option<&'a mut UctNode> {
    let ptr = self.child.load(Ordering::Relaxed);
    if !ptr.is_null() {
      Some(unsafe { &mut *ptr })
    } else {
      None
    }
  }

  pub fn clear_child(&self) {
    let ptr = self.child.swap(ptr::null_mut(), Ordering::Relaxed);
    if !ptr.is_null() {
      drop::<Box<UctNode>>(unsafe { mem::transmute(ptr) });
    }
  }

  pub fn set_child(&self, child: Box<UctNode>) {
    let ptr = self.child.swap(unsafe { mem::transmute(child) }, Ordering::Relaxed);
    if !ptr.is_null() {
      drop::<Box<UctNode>>(unsafe { mem::transmute(ptr) });
    }
  }

  pub fn set_child_if_empty(&self, child: Box<UctNode>) {
    let child_ptr = unsafe { mem::transmute(child) };
    let ptr = self.child.compare_and_swap(ptr::null_mut(), child_ptr, Ordering::Relaxed);
    if !ptr.is_null() {
      drop::<Box<UctNode>>(unsafe { mem::transmute(child_ptr) });
    }
  }

  pub fn get_visits(&self) -> usize {
    self.visits.load(Ordering::Relaxed)
  }

  pub fn get_wins(&self) -> usize {
    self.wins.load(Ordering::Relaxed)
  }

  pub fn get_draws(&self) -> usize {
    self.draws.load(Ordering::Relaxed)
  }

  pub fn add_win(&self) {
    self.visits.fetch_add(1, Ordering::Relaxed);
    self.wins.fetch_add(1, Ordering::Relaxed);
  }

  pub fn add_draw(&self) {
    self.visits.fetch_add(1, Ordering::Relaxed);
    self.draws.fetch_add(1, Ordering::Relaxed);
  }

  pub fn add_loose(&self) {
    self.visits.fetch_add(1, Ordering::Relaxed);
  }

  pub fn clear_stats(&self) {
    self.wins.store(0, Ordering::Relaxed);
    self.draws.store(0, Ordering::Relaxed);
    self.visits.store(0, Ordering::Relaxed);
  }
}

pub struct UctRoot {
  node: Option<Box<UctNode>>,
  moves: Vec<Pos>,
  moves_field: Vec<Pos>,
  player: Player,
  moves_count: usize,
  hash: u64
}

impl UctRoot {
  fn clear(&mut self) {
    self.node = None;
    self.moves.clear();
    for i in self.moves_field.iter_mut() {
      *i = 0;
    }
    self.player = Player::Red;
    self.moves_count = 0;
    self.hash = 0;
  }

  fn init(&mut self, field: &Field, player: Player) {
    self.node = Some(Box::new(UctNode::new(0)));
    self.player = player;
    let width = field.width();
    for &start_pos in field.points_seq() {
      wave(width, start_pos, |pos| {
        if self.moves_field[pos] != start_pos && field.is_putting_allowed(pos) && manhattan(width, start_pos, pos) <= UCT_RADIUS {
          if self.moves_field[pos] == 0 {
            self.moves.push(pos);
          }
          self.moves_field[pos] = start_pos;
          true
        } else {
          false
        }
      });
    }
  }

  fn expand_node(node: &mut UctNode, moves: &Vec<Pos>) {
    if node.get_child_ref().is_none() {
      if node.get_visits() == usize::max_value() {
        node.clear_stats();
      }
    } else {
      let mut next = node.get_child_mut();
      while next.as_ref().unwrap().get_sibling_ref().is_some() {
        UctRoot::expand_node(*next.as_mut().unwrap(), moves);
        next = next.unwrap().get_sibling_mut();
      }
      UctRoot::expand_node(*next.as_mut().unwrap(), moves);
      for &pos in moves {
        next.as_mut().unwrap().set_sibling(Box::new(UctNode::new(pos)));
        next = next.unwrap().get_sibling_mut();
      }
    }
  }

  fn update(&mut self, field: &Field, player: Player) {
    if self.node.is_some() && field.hash_at(self.moves_count) != Some(self.hash) {
      self.clear();
    }
    if self.node.is_none() {
      self.init(field, player);
    } else {
      let points_seq = field.points_seq();
      let moves_count = field.moves_count();
      loop {
        if self.moves_count == moves_count {
          break;
        }
        let next_pos = points_seq[self.moves_count];
        if !field.is_players_point(next_pos, self.player) {
          self.clear();
          self.init(field, player);
          break;
        }
        let mut next = self.node.as_ref().unwrap().get_child();
        while next.is_some() && next.as_ref().unwrap().pos != next_pos {
          next = next.unwrap().get_sibling();
        }
        match next.as_mut() {
          Some(node) => {
            node.clear_sibling();
          },
          None => {
            self.clear();
            self.init(field, player);
            break;
          }
        }
        self.node = next;
        let moves_field = &mut self.moves_field;
        self.moves.retain(|&pos| {
          if field.is_putting_allowed(pos) {
            true
          } else {
            moves_field[pos] = 0;
            false
          }
        });
        let mut added_moves = Vec::new();
        let width = field.width();
        wave(width, next_pos, |pos| {
          if moves_field[pos] != next_pos && field.is_putting_allowed(pos) && manhattan(width, next_pos, pos) <= UCT_RADIUS {
            if moves_field[pos] == 0 {
              added_moves.push(pos);
            }
            moves_field[pos] = next_pos;
            true
          } else {
            false
          }
        });
        UctRoot::expand_node(self.node.as_mut().unwrap(), &added_moves);
        self.moves_count += 1;
        self.player = self.player.next();
      }
    }
  }

  pub fn new(length: Pos) -> UctRoot {
    UctRoot {
      node: None,
      moves: Vec::with_capacity(length),
      moves_field: repeat(0).take(length).collect(),
      player: Player::Red,
      moves_count: 0,
      hash: 0
    }
  }

  fn play_random_game<T: Rng>(field: &mut Field, mut player: Player, rng: &mut T, possible_moves: &mut Vec<Pos>) -> Option<Player> {
    rng.shuffle(possible_moves);
    let mut putted: CoordProd = 0;
    for &pos in possible_moves.iter() {
      if field.is_putting_allowed(pos) && !field.is_empty_base(pos) {
        field.put_point(pos, player);
        player = player.next();
        putted += 1;
      }
    }
    let red_score = field.score(Player::Red);
    let result = if red_score > 0 {
      Some(Player::Red)
    } else if red_score < 0 {
      Some(Player::Black)
    } else {
      None
    };
    for _ in 0 .. putted {
      field.undo();
    }
    result
  }

  fn ucb(parent: &UctNode, node: &UctNode) -> f32 {
    let wins = node.get_wins() as f32;
    let draws = node.get_draws() as f32;
    let visits = node.get_visits() as f32;
    let parent_visits = parent.get_visits() as f32;
    let win_rate = (wins + draws * UCT_DRAW_WEIGHT) / visits;
    let uct = match UCB_TYPE {
      UcbType::Ucb1 => UCTK * f32::sqrt(2.0 * f32::ln(parent_visits) / visits),
      UcbType::Ucb1Tuned => {
        let v = (wins + draws * UCT_DRAW_WEIGHT * UCT_DRAW_WEIGHT) / visits - win_rate * win_rate + f32::sqrt(2.0 * f32::ln(parent_visits) / visits);
        UCTK * f32::sqrt(v.min(0.25) * f32::ln(parent_visits) / visits)
      }
    };
    win_rate + uct
  }

  fn create_children(field: &Field, possible_moves: &Vec<Pos>, node: &UctNode) {
    let mut children = None;
    for &pos in possible_moves {
      if field.is_putting_allowed(pos) {
        let mut cur_child = Box::new(UctNode::new(pos));
        cur_child.set_sibling_option(children);
        children = Some(cur_child);
      }
    }
    for child in children {
      node.set_child_if_empty(child)
    }
  }

  fn uct_select<'a, T: Rng>(node: &'a UctNode, rng: &mut T) -> Option<&'a UctNode> {
    let mut best_uct = 0f32;
    let mut result = None;
    let mut next = node.get_child_ref();
    loop {
      match next {
        Some(next_node) => {
          let visits = next_node.get_visits();
          let wins = next_node.get_wins();
          let uct_value = if visits == usize::max_value() {
            if wins == usize::max_value() {
              100000.0
            } else {
              -1.0
            }
          } else if visits > 0 {
            UctRoot::ucb(node, next_node)
          } else {
            10000.0 + (rng.gen::<u16>() % 1000) as f32
          };
          if uct_value > best_uct {
            best_uct = uct_value;
            result = Some(next_node);
          }
          next = next_node.get_sibling_ref();
        },
        None => break
      }
    }
    result
  }

  fn play_simulation_rec<T: Rng>(field: &mut Field, node: &UctNode, possible_moves: &mut Vec<Pos>, rng: &mut T, depth: Depth) {

  }

  fn play_simulation<T: Rng>(field: &mut Field, rng: &mut T) {

  }

  fn best_move_generic<T: Rng>(&mut self, field: &Field, player: Player, rng: &mut T, should_stop: &AtomicBool) -> Option<Pos> {
    self.update(field, player);
    let mut guards = Vec::with_capacity(4);
    for _ in 0 .. 4 {
      let xor_shift_rng = rng.gen::<XorShiftRng>();
      guards.push(thread::scoped(|| {
        let mut local_field = field.clone();
        let mut local_rng = xor_shift_rng;
        while !should_stop.load(Ordering::Relaxed) {
          UctRoot::play_simulation(&mut local_field, &mut local_rng);
        }
      }));
    }
    drop(guards);
    let mut best_uct = 0f32;
    let mut result = None;
    for root in self.node.as_ref() {
      let mut next = root.get_child_ref();
      loop {
        match next {
          Some(next_node) => {
            let uct_value = UctRoot::ucb(root, next_node);
            if uct_value > best_uct {
              best_uct = uct_value;
              result = Some(next_node.get_pos());
            }
            next = next_node.get_sibling_ref();
          },
          None => break
        }
      }
    }
    result
  }

  pub fn best_move<T: Rng>(&mut self, field: &Field, player: Player, rng: &mut T, time: Time) -> Option<Pos> {
    let should_stop = AtomicBool::new(false);
    let guard = thread::scoped(|| {
      thread::sleep_ms(time);
      should_stop.store(true, Ordering::Relaxed);
    });
    let result = self.best_move_generic(field, player, rng, &should_stop);
    drop(guard);
    result
  }

  //pub fn estimates
}
<|endoftext|>


<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]

pub mod authentication;
pub mod keys;
pub mod status;
pub mod tos;
<commit_msg>identity-service-api: Add crate-level docs and warn on missing docs<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! (De)serializable types for the Matrix Identity Service API.

#![warn(missing_docs)]

pub mod authentication;
pub mod keys;
pub mod status;
pub mod tos;
<|endoftext|>


<commit_before>extern crate num;

use num::One;

use std::ops::Add;

struct RangeFinder<'a, T: 'a> {
    index: usize,
    length: usize,
    arr: &'a [T],
}

impl<'a, T> Iterator for RangeFinder<'a, T>
where
    T: PartialEq + Add<T, Output = T> + Copy + One,
{
    type Item = (T, Option<T>);
    fn next(&mut self) -> Option<Self::Item> {
        if self.index == self.length {
            return None;
        }
        let lo = self.index;
        while self.index < self.length - 1
            && self.arr[self.index + 1] == self.arr[self.index] + T::one()
        {
            self.index += 1
        }
        let hi = self.index;
        self.index += 1;
        if hi - lo > 1 {
            Some((self.arr[lo], Some(self.arr[hi])))
        } else {
            if hi - lo == 1 {
                self.index -= 1
            }
            Some((self.arr[lo], None))
        }
    }
}

impl<'a, T> RangeFinder<'a, T> {
    fn new(a: &'a [T]) -> Self {
        RangeFinder {
            index: 0,
            arr: a,
            length: a.len(),
        }
    }
}

fn main() {
    let n = &[
        0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29,
        30, 31, 32, 33, 35, 36, 37, 38, 39,
    ];

    for (i, (lo, hi)) in RangeFinder::new(n).enumerate() {
        if i > 0 {
            print!(", ")
        }
        print!("{}", lo);
        if hi.is_some() {
            print!("-{}", hi.unwrap())
        }
    }
    println!();
}
<commit_msg>range-extraction: added test<commit_after>extern crate num;

use num::One;

use std::ops::Add;

struct RangeFinder<'a, T: 'a> {
    index: usize,
    length: usize,
    arr: &'a [T],
}

impl<'a, T> Iterator for RangeFinder<'a, T>
where
    T: PartialEq + Add<T, Output = T> + Copy + One,
{
    type Item = (T, Option<T>);
    fn next(&mut self) -> Option<Self::Item> {
        if self.index == self.length {
            return None;
        }
        let lo = self.index;
        while self.index < self.length - 1
            && self.arr[self.index + 1] == self.arr[self.index] + T::one()
        {
            self.index += 1
        }
        let hi = self.index;
        self.index += 1;
        if hi - lo > 1 {
            Some((self.arr[lo], Some(self.arr[hi])))
        } else {
            if hi - lo == 1 {
                self.index -= 1
            }
            Some((self.arr[lo], None))
        }
    }
}

impl<'a, T> RangeFinder<'a, T> {
    fn new(a: &'a [T]) -> Self {
        RangeFinder {
            index: 0,
            arr: a,
            length: a.len(),
        }
    }
}

fn main() {
    let n = &[
        0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29,
        30, 31, 32, 33, 35, 36, 37, 38, 39,
    ];

    for (i, (lo, hi)) in RangeFinder::new(n).enumerate() {
        if i > 0 {
            print!(", ")
        }
        print!("{}", lo);
        if hi.is_some() {
            print!("-{}", hi.unwrap())
        }
    }
    println!();
}

#[test]
fn test_solution() {
    let n: &[u8] = &[
        0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29,
        30, 31, 32, 33, 35, 36, 37, 38, 39,
    ];

    let actual: Vec<(u8, Option<u8>)> = RangeFinder::new(n).collect();
    let expected = &[
        (0, Some(2)),
        (4, None),
        (6, Some(8)),
        (11, None),
        (12, None),
        (14, Some(25)),
        (27, Some(33)),
        (35, Some(39)),
    ];

    assert_eq!(&actual, expected);
}
<|endoftext|>