<commit_before>use crate::Map;
use std::fmt;
use std::io;

use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};

use error::{Error, Result};
use raw;

/// Values which can be represented in the Named Binary Tag format.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum Value {
    Byte(i8),
    Short(i16),
    Int(i32),
    Long(i64),
    Float(f32),
    Double(f64),
    ByteArray(Vec<i8>),
    String(String),
    List(Vec<Value>),
    Compound(Map<String, Value>),
    IntArray(Vec<i32>),
    LongArray(Vec<i64>),
}

impl Value {
    /// The type ID of this `Value`, which is a single byte in the range
    /// `0x01` to `0x0b`.
    pub fn id(&self) -> u8 {
        match *self {
            Value::Byte(_) => 0x01,
            Value::Short(_) => 0x02,
            Value::Int(_) => 0x03,
            Value::Long(_) => 0x04,
            Value::Float(_) => 0x05,
            Value::Double(_) => 0x06,
            Value::ByteArray(_) => 0x07,
            Value::String(_) => 0x08,
            Value::List(_) => 0x09,
            Value::Compound(_) => 0x0a,
            Value::IntArray(_) => 0x0b,
            Value::LongArray(_) => 0x0c,
        }
    }

    /// A string representation of this tag.
    pub fn tag_name(&self) -> &str {
        match *self {
            Value::Byte(_) => "TAG_Byte",
            Value::Short(_) => "TAG_Short",
            Value::Int(_) => "TAG_Int",
            Value::Long(_) => "TAG_Long",
            Value::Float(_) => "TAG_Float",
            Value::Double(_) => "TAG_Double",
            Value::ByteArray(_) => "TAG_ByteArray",
            Value::String(_) => "TAG_String",
            Value::List(_) => "TAG_List",
            Value::Compound(_) => "TAG_Compound",
            Value::IntArray(_) => "TAG_IntArray",
            Value::LongArray(_) => "TAG_LongArray",
        }
    }

    /// Writes the payload of this `Value` to an `io::Write` destination.
    pub fn to_writer<W>(&self, mut dst: &mut W) -> Result<()>
    where
        W: io::Write,
    {
        match *self {
            Value::Byte(val) => raw::write_bare_byte(dst, val),
            Value::Short(val) => raw::write_bare_short(dst, val),
            Value::Int(val) => raw::write_bare_int(dst, val),
            Value::Long(val) => raw::write_bare_long(dst, val),
            Value::Float(val) => raw::write_bare_float(dst, val),
            Value::Double(val) => raw::write_bare_double(dst, val),
            Value::ByteArray(ref vals) => raw::write_bare_byte_array(dst, &vals[..]),
            Value::String(ref val) => raw::write_bare_string(dst, &val),
            Value::List(ref vals) => {
                // This is a bit of a trick: if the list is empty, don't bother
                // checking its type.
                if vals.is_empty() {
                    dst.write_u8(0)?; // TAG_End
                    dst.write_i32::<BigEndian>(0)?;
                } else {
                    // Otherwise, use the first element of the list.
                    let first_id = vals[0].id();
                    dst.write_u8(first_id)?;
                    dst.write_i32::<BigEndian>(vals.len() as i32)?;
                    for nbt in vals {
                        // Ensure that all of the tags are the same type.
                        if nbt.id() != first_id {
                            return Err(Error::HeterogeneousList);
                        }
                        nbt.to_writer(dst)?;
                    }
                }
                Ok(())
            }
            Value::Compound(ref vals) => {
                for (name, ref nbt) in vals {
                    // Write the header for the tag.
                    dst.write_u8(nbt.id())?;
                    raw::write_bare_string(dst, name)?;
                    nbt.to_writer(dst)?;
                }
                raw::close_nbt(&mut dst)
            }
            Value::IntArray(ref vals) => raw::write_bare_int_array(dst, &vals[..]),
            Value::LongArray(ref vals) => raw::write_bare_long_array(dst, &vals[..]),
        }
    }

    /// Reads the payload of an `Value` with a given type ID from an
    /// `io::Read` source.
    pub fn from_reader<R>(id: u8, src: &mut R) -> Result<Value>
    where
        R: io::Read,
    {
        match id {
            0x01 => Ok(Value::Byte(raw::read_bare_byte(src)?)),
            0x02 => Ok(Value::Short(raw::read_bare_short(src)?)),
            0x03 => Ok(Value::Int(raw::read_bare_int(src)?)),
            0x04 => Ok(Value::Long(raw::read_bare_long(src)?)),
            0x05 => Ok(Value::Float(raw::read_bare_float(src)?)),
            0x06 => Ok(Value::Double(raw::read_bare_double(src)?)),
            0x07 => Ok(Value::ByteArray(raw::read_bare_byte_array(src)?)),
            0x08 => Ok(Value::String(raw::read_bare_string(src)?)),
            0x09 => {
                // List
                let id = src.read_u8()?;
                let len = src.read_i32::<BigEndian>()? as usize;
                let mut buf = Vec::with_capacity(len);
                for _ in 0..len {
                    buf.push(Value::from_reader(id, src)?);
                }
                Ok(Value::List(buf))
            }
            0x0a => {
                // Compound
                let mut buf = Map::new();
                loop {
                    let (id, name) = raw::emit_next_header(src)?;
                    if id == 0x00 {
                        break;
                    }
                    let tag = Value::from_reader(id, src)?;
                    buf.insert(name, tag);
                }
                Ok(Value::Compound(buf))
            }
            0x0b => Ok(Value::IntArray(raw::read_bare_int_array(src)?)),
            0x0c => Ok(Value::LongArray(raw::read_bare_long_array(src)?)),
            e => Err(Error::InvalidTypeId(e)),
        }
    }

    pub fn print(&self, f: &mut fmt::Formatter, offset: usize) -> fmt::Result {
        match *self {
            Value::Byte(v) => write!(f, "{}", v),
            Value::Short(v) => write!(f, "{}", v),
            Value::Int(v) => write!(f, "{}", v),
            Value::Long(v) => write!(f, "{}", v),
            Value::Float(v) => write!(f, "{}", v),
            Value::Double(v) => write!(f, "{}", v),
            Value::ByteArray(ref v) => write!(f, "{:?}", v),
            Value::String(ref v) => write!(f, "{}", v),
            Value::IntArray(ref v) => write!(f, "{:?}", v),
            Value::LongArray(ref v) => write!(f, "{:?}", v),
            Value::List(ref v) => {
                if v.is_empty() {
                    write!(f, "zero entries")
                } else {
                    write!(
                        f,
                        "{} entries of type {}\n{:>width$}\n",
                        v.len(),
                        v[0].tag_name(),
                        "{",
                        width = offset + 1
                    )?;
                    for tag in v {
                        let new_offset = offset + 2;
                        write!(
                            f,
                            "{:>width$}(None): ",
                            tag.tag_name(),
                            width = new_offset + tag.tag_name().len()
                        )?;
                        tag.print(f, new_offset)?;
                        writeln!(f)?;
                    }
                    write!(f, "{:>width$}", "}", width = offset + 1)
                }
            }
            Value::Compound(ref v) => {
                write!(
                    f,
                    "{} entry(ies)\n{:>width$}\n",
                    v.len(),
                    "{",
                    width = offset + 1
                )?;
                for (name, tag) in v {
                    let new_offset = offset + 2;
                    write!(
                        f,
                        "{:>width$}({}): ",
                        tag.tag_name(),
                        name,
                        width = new_offset + tag.tag_name().len()
                    )?;
                    tag.print(f, new_offset)?;
                    writeln!(f)?;
                }
                write!(f, "{:>width$}", "}", width = offset + 1)
            }
        }
    }

    /// The number of bytes this value serializes to, before compression
    pub fn len_bytes(&self) -> usize {
        1 /* type ID */ + self.len_payload()
    }

    /// Serialized size of an entry within a TAG_COMPOUND
    /// Also used by Blob, so crate visible
    pub(crate) fn size_of_compound_entry((key, value): (&String, &Value)) -> usize {
        let key_len = 2 + key.len();
        let value_len = value.len_bytes();
        key_len + value_len
    }

    // The serialized size of the payload specifically, without tag IDs or names prepended.
    fn len_payload(&self) -> usize {
        use std::mem::size_of;
        match self {
            Value::Byte(_) => 1,
            Value::Short(_) => 2,
            Value::Int(_) => 4,
            Value::Long(_) => 8,
            Value::Float(_) => 4,
            Value::Double(_) => 8,
            Value::String(s) => 2 /* string size */ + s.len(),
            Value::List(v) => {
                1 /* item tag */ + 4 /* arr size */ + v.iter().map(Self::len_payload).sum::<usize>()
            }
            Value::Compound(hm) => {
                hm.iter().map(Self::size_of_compound_entry).sum::<usize>() + 1usize
            }
            Value::ByteArray(ba) => 4 /* arr size */ + size_of::<i8>()*ba.len(),
            Value::IntArray(ia) => 4 /* arr size */ + size_of::<i32>()*ia.len(),
            Value::LongArray(la) => 4 /* arr size */ + size_of::<i64>()*la.len(),
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.print(f, 0)
    }
}

impl From<i8> for Value {
    fn from(t: i8) -> Value {
        Value::Byte(t)
    }
}

impl From<i16> for Value {
    fn from(t: i16) -> Value {
        Value::Short(t)
    }
}

impl From<i32> for Value {
    fn from(t: i32) -> Value {
        Value::Int(t)
    }
}

impl From<i64> for Value {
    fn from(t: i64) -> Value {
        Value::Long(t)
    }
}

impl From<f32> for Value {
    fn from(t: f32) -> Value {
        Value::Float(t)
    }
}

impl From<f64> for Value {
    fn from(t: f64) -> Value {
        Value::Double(t)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(t: &'a str) -> Value {
        Value::String(t.into())
    }
}

impl From<String> for Value {
    fn from(t: String) -> Value {
        Value::String(t)
    }
}

impl From<Vec<i8>> for Value {
    fn from(t: Vec<i8>) -> Value {
        Value::ByteArray(t)
    }
}

impl<'a> From<&'a [i8]> for Value {
    fn from(t: &'a [i8]) -> Value {
        Value::ByteArray(t.into())
    }
}

impl From<Vec<i32>> for Value {
    fn from(t: Vec<i32>) -> Value {
        Value::IntArray(t)
    }
}

impl<'a> From<&'a [i32]> for Value {
    fn from(t: &'a [i32]) -> Value {
        Value::IntArray(t.into())
    }
}

impl From<Vec<i64>> for Value {
    fn from(t: Vec<i64>) -> Value {
        Value::LongArray(t)
    }
}

impl<'a> From<&'a [i64]> for Value {
    fn from(t: &'a [i64]) -> Value {
        Value::LongArray(t.into())
    }
}
<commit_msg>Fix array value serialization <commit_after>use crate::Map;
use std::fmt;
use std::io;

use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};

use error::{Error, Result};
use raw;

/// Values which can be represented in the Named Binary Tag format.
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[cfg_attr(feature = "serde", derive(Deserialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum Value {
    Byte(i8),
    Short(i16),
    Int(i32),
    Long(i64),
    Float(f32),
    Double(f64),
    ByteArray(Vec<i8>),
    String(String),
    List(Vec<Value>),
    Compound(Map<String, Value>),
    #[cfg_attr(feature = "serde", serde(serialize_with = "crate::i32_array"))]
    IntArray(Vec<i32>),
    #[cfg_attr(feature = "serde", serde(serialize_with = "crate::i64_array"))]
    LongArray(Vec<i64>),
}

impl Value {
    /// The type ID of this `Value`, which is a single byte in the range
    /// `0x01` to `0x0b`.
    pub fn id(&self) -> u8 {
        match *self {
            Value::Byte(_) => 0x01,
            Value::Short(_) => 0x02,
            Value::Int(_) => 0x03,
            Value::Long(_) => 0x04,
            Value::Float(_) => 0x05,
            Value::Double(_) => 0x06,
            Value::ByteArray(_) => 0x07,
            Value::String(_) => 0x08,
            Value::List(_) => 0x09,
            Value::Compound(_) => 0x0a,
            Value::IntArray(_) => 0x0b,
            Value::LongArray(_) => 0x0c,
        }
    }

    /// A string representation of this tag.
    pub fn tag_name(&self) -> &str {
        match *self {
            Value::Byte(_) => "TAG_Byte",
            Value::Short(_) => "TAG_Short",
            Value::Int(_) => "TAG_Int",
            Value::Long(_) => "TAG_Long",
            Value::Float(_) => "TAG_Float",
            Value::Double(_) => "TAG_Double",
            Value::ByteArray(_) => "TAG_ByteArray",
            Value::String(_) => "TAG_String",
            Value::List(_) => "TAG_List",
            Value::Compound(_) => "TAG_Compound",
            Value::IntArray(_) => "TAG_IntArray",
            Value::LongArray(_) => "TAG_LongArray",
        }
    }

    /// Writes the payload of this `Value` to an `io::Write` destination.
    pub fn to_writer<W>(&self, mut dst: &mut W) -> Result<()>
    where
        W: io::Write,
    {
        match *self {
            Value::Byte(val) => raw::write_bare_byte(dst, val),
            Value::Short(val) => raw::write_bare_short(dst, val),
            Value::Int(val) => raw::write_bare_int(dst, val),
            Value::Long(val) => raw::write_bare_long(dst, val),
            Value::Float(val) => raw::write_bare_float(dst, val),
            Value::Double(val) => raw::write_bare_double(dst, val),
            Value::ByteArray(ref vals) => raw::write_bare_byte_array(dst, &vals[..]),
            Value::String(ref val) => raw::write_bare_string(dst, &val),
            Value::List(ref vals) => {
                // This is a bit of a trick: if the list is empty, don't bother
                // checking its type.
                if vals.is_empty() {
                    dst.write_u8(0)?; // TAG_End
                    dst.write_i32::<BigEndian>(0)?;
                } else {
                    // Otherwise, use the first element of the list.
                    let first_id = vals[0].id();
                    dst.write_u8(first_id)?;
                    dst.write_i32::<BigEndian>(vals.len() as i32)?;
                    for nbt in vals {
                        // Ensure that all of the tags are the same type.
                        if nbt.id() != first_id {
                            return Err(Error::HeterogeneousList);
                        }
                        nbt.to_writer(dst)?;
                    }
                }
                Ok(())
            }
            Value::Compound(ref vals) => {
                for (name, ref nbt) in vals {
                    // Write the header for the tag.
                    dst.write_u8(nbt.id())?;
                    raw::write_bare_string(dst, name)?;
                    nbt.to_writer(dst)?;
                }
                raw::close_nbt(&mut dst)
            }
            Value::IntArray(ref vals) => raw::write_bare_int_array(dst, &vals[..]),
            Value::LongArray(ref vals) => raw::write_bare_long_array(dst, &vals[..]),
        }
    }

    /// Reads the payload of an `Value` with a given type ID from an
    /// `io::Read` source.
    pub fn from_reader<R>(id: u8, src: &mut R) -> Result<Value>
    where
        R: io::Read,
    {
        match id {
            0x01 => Ok(Value::Byte(raw::read_bare_byte(src)?)),
            0x02 => Ok(Value::Short(raw::read_bare_short(src)?)),
            0x03 => Ok(Value::Int(raw::read_bare_int(src)?)),
            0x04 => Ok(Value::Long(raw::read_bare_long(src)?)),
            0x05 => Ok(Value::Float(raw::read_bare_float(src)?)),
            0x06 => Ok(Value::Double(raw::read_bare_double(src)?)),
            0x07 => Ok(Value::ByteArray(raw::read_bare_byte_array(src)?)),
            0x08 => Ok(Value::String(raw::read_bare_string(src)?)),
            0x09 => {
                // List
                let id = src.read_u8()?;
                let len = src.read_i32::<BigEndian>()? as usize;
                let mut buf = Vec::with_capacity(len);
                for _ in 0..len {
                    buf.push(Value::from_reader(id, src)?);
                }
                Ok(Value::List(buf))
            }
            0x0a => {
                // Compound
                let mut buf = Map::new();
                loop {
                    let (id, name) = raw::emit_next_header(src)?;
                    if id == 0x00 {
                        break;
                    }
                    let tag = Value::from_reader(id, src)?;
                    buf.insert(name, tag);
                }
                Ok(Value::Compound(buf))
            }
            0x0b => Ok(Value::IntArray(raw::read_bare_int_array(src)?)),
            0x0c => Ok(Value::LongArray(raw::read_bare_long_array(src)?)),
            e => Err(Error::InvalidTypeId(e)),
        }
    }

    pub fn print(&self, f: &mut fmt::Formatter, offset: usize) -> fmt::Result {
        match *self {
            Value::Byte(v) => write!(f, "{}", v),
            Value::Short(v) => write!(f, "{}", v),
            Value::Int(v) => write!(f, "{}", v),
            Value::Long(v) => write!(f, "{}", v),
            Value::Float(v) => write!(f, "{}", v),
            Value::Double(v) => write!(f, "{}", v),
            Value::ByteArray(ref v) => write!(f, "{:?}", v),
            Value::String(ref v) => write!(f, "{}", v),
            Value::IntArray(ref v) => write!(f, "{:?}", v),
            Value::LongArray(ref v) => write!(f, "{:?}", v),
            Value::List(ref v) => {
                if v.is_empty() {
                    write!(f, "zero entries")
                } else {
                    write!(
                        f,
                        "{} entries of type {}\n{:>width$}\n",
                        v.len(),
                        v[0].tag_name(),
                        "{",
                        width = offset + 1
                    )?;
                    for tag in v {
                        let new_offset = offset + 2;
                        write!(
                            f,
                            "{:>width$}(None): ",
                            tag.tag_name(),
                            width = new_offset + tag.tag_name().len()
                        )?;
                        tag.print(f, new_offset)?;
                        writeln!(f)?;
                    }
                    write!(f, "{:>width$}", "}", width = offset + 1)
                }
            }
            Value::Compound(ref v) => {
                write!(
                    f,
                    "{} entry(ies)\n{:>width$}\n",
                    v.len(),
                    "{",
                    width = offset + 1
                )?;
                for (name, tag) in v {
                    let new_offset = offset + 2;
                    write!(
                        f,
                        "{:>width$}({}): ",
                        tag.tag_name(),
                        name,
                        width = new_offset + tag.tag_name().len()
                    )?;
                    tag.print(f, new_offset)?;
                    writeln!(f)?;
                }
                write!(f, "{:>width$}", "}", width = offset + 1)
            }
        }
    }

    /// The number of bytes this value serializes to, before compression
    pub fn len_bytes(&self) -> usize {
        1 /* type ID */ + self.len_payload()
    }

    /// Serialized size of an entry within a TAG_COMPOUND
    /// Also used by Blob, so crate visible
    pub(crate) fn size_of_compound_entry((key, value): (&String, &Value)) -> usize {
        let key_len = 2 + key.len();
        let value_len = value.len_bytes();
        key_len + value_len
    }

    // The serialized size of the payload specifically, without tag IDs or names prepended.
    fn len_payload(&self) -> usize {
        use std::mem::size_of;
        match self {
            Value::Byte(_) => 1,
            Value::Short(_) => 2,
            Value::Int(_) => 4,
            Value::Long(_) => 8,
            Value::Float(_) => 4,
            Value::Double(_) => 8,
            Value::String(s) => 2 /* string size */ + s.len(),
            Value::List(v) => {
                1 /* item tag */ + 4 /* arr size */ + v.iter().map(Self::len_payload).sum::<usize>()
            }
            Value::Compound(hm) => {
                hm.iter().map(Self::size_of_compound_entry).sum::<usize>() + 1usize
            }
            Value::ByteArray(ba) => 4 /* arr size */ + size_of::<i8>()*ba.len(),
            Value::IntArray(ia) => 4 /* arr size */ + size_of::<i32>()*ia.len(),
            Value::LongArray(la) => 4 /* arr size */ + size_of::<i64>()*la.len(),
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.print(f, 0)
    }
}

impl From<i8> for Value {
    fn from(t: i8) -> Value {
        Value::Byte(t)
    }
}

impl From<i16> for Value {
    fn from(t: i16) -> Value {
        Value::Short(t)
    }
}

impl From<i32> for Value {
    fn from(t: i32) -> Value {
        Value::Int(t)
    }
}

impl From<i64> for Value {
    fn from(t: i64) -> Value {
        Value::Long(t)
    }
}

impl From<f32> for Value {
    fn from(t: f32) -> Value {
        Value::Float(t)
    }
}

impl From<f64> for Value {
    fn from(t: f64) -> Value {
        Value::Double(t)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(t: &'a str) -> Value {
        Value::String(t.into())
    }
}

impl From<String> for Value {
    fn from(t: String) -> Value {
        Value::String(t)
    }
}

impl From<Vec<i8>> for Value {
    fn from(t: Vec<i8>) -> Value {
        Value::ByteArray(t)
    }
}

impl<'a> From<&'a [i8]> for Value {
    fn from(t: &'a [i8]) -> Value {
        Value::ByteArray(t.into())
    }
}

impl From<Vec<i32>> for Value {
    fn from(t: Vec<i32>) -> Value {
        Value::IntArray(t)
    }
}

impl<'a> From<&'a [i32]> for Value {
    fn from(t: &'a [i32]) -> Value {
        Value::IntArray(t.into())
    }
}

impl From<Vec<i64>> for Value {
    fn from(t: Vec<i64>) -> Value {
        Value::LongArray(t)
    }
}

impl<'a> From<&'a [i64]> for Value {
    fn from(t: &'a [i64]) -> Value {
        Value::LongArray(t.into())
    }
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use std::collections::HashMap;
use std::fmt;
use rand::random;

pub type Point = (isize, isize);

#[derive(Debug, Clone)]
pub struct World {
    width: isize,
    height: isize,
    generation: Vec<Point>,
    age: usize,
}

impl World {
    pub fn new(width: isize, height: isize)  -> World {
        World { width: width, height: height, age: 0, generation: vec![] }
    }

    pub fn seed(mut self) -> World {
        self.generation = (0..self.width).cartesian_product(0..self.height)
            .filter(|_| random())
            .collect::<Vec<Point>>();
        self
    }

    pub fn evolve(&mut self) -> &World {
        let mut neighbours_counts = HashMap::new();
        for &(x, y) in &self.generation[..] {
            let neighbours = (-1..2).cartesian_product(-1..2)
                                    .filter(|&(dx, dy)| dx != 0 || dy != 0)
                                    .map(|(dx, dy)| (dx + x, dy + y));
            for n in neighbours {
                let counts = neighbours_counts.entry(n).or_insert(0);
                *counts = *counts + 1;
            }
        }
        self.generation = neighbours_counts.iter()
            .filter(|&(n, c)| if self.generation.contains(n) { *c == 3 || *c == 2 } else { *c == 3 })
            .map(|(n, _)| *n)
            .collect::<Vec<Point>>();
        self.age += 1;
        self
    }
}

impl fmt::Display for World {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buf = String::with_capacity(((self.width + 2) * (self.height + 2) + 50) as usize);
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '┌' } else if x == self.width + 1 { '┐' } else { '─' });
        }
        buf.push('\n');
        for y in 0..self.height {
            buf.push('│');
            for x in 0..self.width {
                buf.push(if self.generation.contains(&(x, y)) { '*' } else { ' ' });
            }
            buf.push('|');
            if y == 0 {
                buf.push_str(&format!(" cells: {}", self.generation.len()));
            }
            if y == 1 {
                buf.push_str(&format!(" age: {}", self.age));
            }
            buf.push('\n');
        }
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '└' } else if x == self.width + 1 { '┘' } else { '─' });
        }
        write!(f, "{}", buf)
    }
}
<commit_msg>Improve lookup performance using HashSet instead of Vec<commit_after>use itertools::Itertools;
use std::collections::{HashMap, HashSet};
use std::fmt;
use rand::random;

pub type Point = (isize, isize);

#[derive(Debug, Clone)]
pub struct World {
    width: isize,
    height: isize,
    generation: HashSet<Point>,
    age: usize,
}

impl World {
    pub fn new(width: isize, height: isize)  -> World {
        World { width: width, height: height, age: 0,
                generation: HashSet::new() }
    }

    pub fn seed(mut self) -> World {
        self.generation = (0..self.width).cartesian_product(0..self.height)
            .filter(|_| random())
            .collect::<HashSet<Point>>();
        self
    }

    pub fn evolve(&mut self) -> &World {
        let mut neighbours_counts = HashMap::new();
        for &(x, y) in self.generation.iter() {
            let neighbours = (-1..2).cartesian_product(-1..2)
                                    .filter(|&(dx, dy)| dx != 0 || dy != 0)
                                    .map(|(dx, dy)| (dx + x, dy + y));
            for n in neighbours {
                let counts = neighbours_counts.entry(n).or_insert(0);
                *counts = *counts + 1;
            }
        }
        self.generation = neighbours_counts.iter()
            .filter(|&(n, c)| if self.generation.contains(n) { *c == 3 || *c == 2 } else { *c == 3 })
            .map(|(n, _)| *n)
            .collect::<HashSet<Point>>();
        self.age += 1;
        self
    }
}

impl fmt::Display for World {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buf = String::with_capacity(((self.width + 2) * (self.height + 2) + 50) as usize);
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '┌' } else if x == self.width + 1 { '┐' } else { '─' });
        }
        buf.push('\n');
        for y in 0..self.height {
            buf.push('│');
            for x in 0..self.width {
                buf.push(if self.generation.contains(&(x, y)) { '*' } else { ' ' });
            }
            buf.push('|');
            if y == 0 {
                buf.push_str(&format!(" cells: {}", self.generation.len()));
            }
            if y == 1 {
                buf.push_str(&format!(" age: {}", self.age));
            }
            buf.push('\n');
        }
        for x in 0..self.width + 2 {
            buf.push(if x == 0 { '└' } else if x == self.width + 1 { '┘' } else { '─' });
        }
        write!(f, "{}", buf)
    }
}
<|endoftext|>


<commit_before>/* Cymbalum, Molecular Simulation in Rust - Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 */

//! While running a simulation, we often want to have control over some
//! simulation parameters: the temperature, the pressure, etc. This is the goal
//! of the control algorithms, all implmenting of the `Control` trait.

use universe::Universe;

/// Trait for controling some parameters in an universe during a simulation.
pub trait Control {
    /// Function called once at the beggining of the simulation, which allow
    /// for some setup of the control algorithm if needed.
    fn setup(&mut self, _: &Universe) {}

    /// Do your job, control algorithm!
    fn control(&mut self, universe: &mut Universe);

    /// Function called once at the end of the simulation.
    fn finish(&mut self, _: &Universe) {}
}

/******************************************************************************/
/// Velocity rescaling thermostat.
///
/// The velocity rescale algorithm controls the temperature by rescaling all
/// the velocities when the temperature differs exceedingly from the desired
/// temperature. A tolerance parameter prevent this algorithm from running too
/// often: if tolerance is 10K and the target temperature is 300K, the algorithm
/// will only run if the instant temperature is below 290K or above 310K.
pub struct RescaleThermostat {
    /// Target temperature
    T: f64,
    /// Tolerance in temperature
    tol: f64,
}

impl RescaleThermostat {
    /// Create a new `RescaleThermostat` acting at temperature `T`, with a
    /// tolerance of `5% T`.
    pub fn new(T: f64) -> RescaleThermostat {
        let tol = 0.05 * T;
        RescaleThermostat::with_tolerance(T, tol)
    }

    /// Create a new `RescaleThermostat` acting at temperature `T`, with a
    /// tolerance of `tol`. For rescaling all the steps, use `tol = 0`.
    pub fn with_tolerance(T: f64, tol: f64) -> RescaleThermostat {
        RescaleThermostat{T: T, tol: tol}
    }
}

impl Control for RescaleThermostat {
    fn control(&mut self, universe: &mut Universe) {
        let T_inst = universe.temperature();
        if f64::abs(T_inst - self.T) > self.tol {
            let factor = f64::sqrt(self.T / T_inst);
            for particle in universe {
                particle.velocity = factor * particle.velocity;
            }
        }
    }
}

/******************************************************************************/
/// Berendsen thermostat.
///
/// The berendsen thermostat sets the simulation temperature by exponentially
/// relaxing to a desired temperature. A more complete description of this
/// algorithm can be found in the original article [1].
///
/// [1] H.J.C. Berendsen, et al. J. Chem Phys 81, 3684 (1984); doi: 10.1063/1.448118
pub struct BerendsenThermostat {
    /// Target temperature
    T: f64,
    /// Timestep of the thermostat, expressed as a multiplicative factor of the
    /// integrator timestep.
    tau: f64,
}

impl BerendsenThermostat {
    /// Create a new `BerendsenThermostat` acting at temperature `T`, with a
    /// timestep of `tau` times the integrator timestep.
    pub fn new(T: f64, tau: f64) -> BerendsenThermostat {
        BerendsenThermostat{T: T, tau: tau}
    }
}

impl Control for BerendsenThermostat {
    fn control(&mut self, universe: &mut Universe) {
        let T_inst = universe.temperature();
        let factor = f64::sqrt(1.0 + 1.0 / self.tau * (self.T / T_inst - 1.0));
        for particle in universe {
            particle.velocity = factor * particle.velocity;
        }
    }
}

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

    fn testing_universe() -> Universe {
        let mut universe = Universe::from_cell(UnitCell::cubic(20.0));;

        for i in 0..10 {
            for j in 0..10 {
                for k in 0..10 {
                    let mut p = Particle::new("Cl");
                    p.position = Vector3D::new(i as f64*2.0, j as f64*2.0, k as f64*2.0);
                    universe.add_particle(p);
                }
            }
        }

        let mut velocities = BoltzmanVelocities::new(300.0);
        velocities.init(&mut universe);
        return universe;
    }

    #[test]
    fn rescale_thermostat() {
        let mut universe = testing_universe();
        let T0 = universe.temperature();
        assert_approx_eq!(T0, 300.0, 1e-12);

        let mut thermostat = RescaleThermostat::with_tolerance(250.0, 100.0);
        thermostat.control(&mut universe);
        let T1 = universe.temperature();
        assert_approx_eq!(T1, 300.0, 1e-12);

        let mut thermostat = RescaleThermostat::with_tolerance(250.0, 10.0);
        thermostat.control(&mut universe);
        let T2 = universe.temperature();
        assert_approx_eq!(T2, 250.0, 1e-12);
    }

    #[test]
    fn berendsen_thermostat() {
        let mut universe = testing_universe();
        let T0 = universe.temperature();
        assert_approx_eq!(T0, 300.0, 1e-12);

        let mut thermostat = BerendsenThermostat::new(250.0, 100.0);
        for _ in 0..1000 {
            thermostat.control(&mut universe);
        }
        let T1 = universe.temperature();
        assert_approx_eq!(T1, 250.0, 1e-2);
    }

}
<commit_msg>Check that the temperature is positive in thermostats<commit_after>/* Cymbalum, Molecular Simulation in Rust - Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 */

//! While running a simulation, we often want to have control over some
//! simulation parameters: the temperature, the pressure, etc. This is the goal
//! of the control algorithms, all implmenting of the `Control` trait.

use universe::Universe;

/// Trait for controling some parameters in an universe during a simulation.
pub trait Control {
    /// Function called once at the beggining of the simulation, which allow
    /// for some setup of the control algorithm if needed.
    fn setup(&mut self, _: &Universe) {}

    /// Do your job, control algorithm!
    fn control(&mut self, universe: &mut Universe);

    /// Function called once at the end of the simulation.
    fn finish(&mut self, _: &Universe) {}
}

/******************************************************************************/
/// Velocity rescaling thermostat.
///
/// The velocity rescale algorithm controls the temperature by rescaling all
/// the velocities when the temperature differs exceedingly from the desired
/// temperature. A tolerance parameter prevent this algorithm from running too
/// often: if tolerance is 10K and the target temperature is 300K, the algorithm
/// will only run if the instant temperature is below 290K or above 310K.
pub struct RescaleThermostat {
    /// Target temperature
    T: f64,
    /// Tolerance in temperature
    tol: f64,
}

impl RescaleThermostat {
    /// Create a new `RescaleThermostat` acting at temperature `T`, with a
    /// tolerance of `5% T`.
    pub fn new(T: f64) -> RescaleThermostat {
        assert!(T >= 0.0, "The temperature must be positive in thermostats.");
        let tol = 0.05 * T;
        RescaleThermostat::with_tolerance(T, tol)
    }

    /// Create a new `RescaleThermostat` acting at temperature `T`, with a
    /// tolerance of `tol`. For rescaling all the steps, use `tol = 0`.
    pub fn with_tolerance(T: f64, tol: f64) -> RescaleThermostat {
        RescaleThermostat{T: T, tol: tol}
    }
}

impl Control for RescaleThermostat {
    fn control(&mut self, universe: &mut Universe) {
        let T_inst = universe.temperature();
        if f64::abs(T_inst - self.T) > self.tol {
            let factor = f64::sqrt(self.T / T_inst);
            for particle in universe {
                particle.velocity = factor * particle.velocity;
            }
        }
    }
}

/******************************************************************************/
/// Berendsen thermostat.
///
/// The berendsen thermostat sets the simulation temperature by exponentially
/// relaxing to a desired temperature. A more complete description of this
/// algorithm can be found in the original article [1].
///
/// [1] H.J.C. Berendsen, et al. J. Chem Phys 81, 3684 (1984); doi: 10.1063/1.448118
pub struct BerendsenThermostat {
    /// Target temperature
    T: f64,
    /// Timestep of the thermostat, expressed as a multiplicative factor of the
    /// integrator timestep.
    tau: f64,
}

impl BerendsenThermostat {
    /// Create a new `BerendsenThermostat` acting at temperature `T`, with a
    /// timestep of `tau` times the integrator timestep.
    pub fn new(T: f64, tau: f64) -> BerendsenThermostat {
        assert!(T >= 0.0, "The temperature must be positive in thermostats.");
        assert!(tau >= 0.0, "The timestep must be positive in berendsen thermostat.");
        BerendsenThermostat{T: T, tau: tau}
    }
}

impl Control for BerendsenThermostat {
    fn control(&mut self, universe: &mut Universe) {
        let T_inst = universe.temperature();
        let factor = f64::sqrt(1.0 + 1.0 / self.tau * (self.T / T_inst - 1.0));
        for particle in universe {
            particle.velocity = factor * particle.velocity;
        }
    }
}

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

    fn testing_universe() -> Universe {
        let mut universe = Universe::from_cell(UnitCell::cubic(20.0));;

        for i in 0..10 {
            for j in 0..10 {
                for k in 0..10 {
                    let mut p = Particle::new("Cl");
                    p.position = Vector3D::new(i as f64*2.0, j as f64*2.0, k as f64*2.0);
                    universe.add_particle(p);
                }
            }
        }

        let mut velocities = BoltzmanVelocities::new(300.0);
        velocities.init(&mut universe);
        return universe;
    }

    #[test]
    fn rescale_thermostat() {
        let mut universe = testing_universe();
        let T0 = universe.temperature();
        assert_approx_eq!(T0, 300.0, 1e-12);

        let mut thermostat = RescaleThermostat::with_tolerance(250.0, 100.0);
        thermostat.control(&mut universe);
        let T1 = universe.temperature();
        assert_approx_eq!(T1, 300.0, 1e-12);

        let mut thermostat = RescaleThermostat::with_tolerance(250.0, 10.0);
        thermostat.control(&mut universe);
        let T2 = universe.temperature();
        assert_approx_eq!(T2, 250.0, 1e-12);
    }

    #[test]
    fn berendsen_thermostat() {
        let mut universe = testing_universe();
        let T0 = universe.temperature();
        assert_approx_eq!(T0, 300.0, 1e-12);

        let mut thermostat = BerendsenThermostat::new(250.0, 100.0);
        for _ in 0..1000 {
            thermostat.control(&mut universe);
        }
        let T1 = universe.temperature();
        assert_approx_eq!(T1, 250.0, 1e-2);
    }

    #[test]
    #[should_panic]
    fn negative_temperature_rescale() {
        RescaleThermostat::new(-56.0);
    }

    #[test]
    #[should_panic]
    fn negative_temperature_berendsen() {
        BerendsenThermostat::new(-56.0, 1000.0);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_handler, c_coming_soon_handler, coming_soon_module, b"mod_coming_soon\0");

macro_rules! html_template {() => ("<!doctype html>

      <meta charset=\"utf-8\">
      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">
      <title>PolyDraw – Coming Soon</title>
      <meta name=\"description\" content=\"PolyDraw website is coming soon\">
      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">

      <link href=\"https://fonts.googleapis.com/css?family=Fira+Sans:300,500\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Roboto+Condensed:400\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Khand:400\" rel=\"stylesheet\" type=\"text/css\">

PolyDraw

Open source software development

COMING SOON

in

000

days

                  In the meantime, please sign the international petition against

ORGAN HARVESTING

from Falun Gong practitioners in China!

                  JOIN THE PETITION!

")}

fn coming_soon_handler(r: &mut Request) -> Status {
   if r.handler().unwrap() != "coming-soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(format!(
      html_template!(),
      STYLESHEET
   ));

   Status::OK
}

const STYLESHEET: &'static str = "
   html, body {
      height: 100%;
      width: 100%;
      margin: 0;
   }

   body {
      display: block;
      font-family: 'Roboto Condensed', sans-serif;
      background-image: url(https://www.polydraw.com/img/mountain-mist.jpg);
      background-size: cover;
      background-repeat: no-repeat;
      background-attachment: fixed;
      background-position: right bottom;
   }

   main {
      display: block;
      position: relative;
      top: 50%;
      margin: 0 auto;
      -webkit-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
      transform: translateY(-50%);
   }

   h1 {
      display: block;
      width: 60%;
      margin: 0 auto;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 500;
      font-size: 3.5em;
      color: white;
      text-align: center;
   }

   h2 {
      display: block;
      width: 70%;
      margin: -0.2em auto 0;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: 1.2em;
      color: #5b5b5b;
      text-align: center;
   }

   .coming-soon {
      display: block;
      width: 40%;
      margin: 2.5em auto .1em;
      font-size: 1.5em;
      color: white;
      text-align: center;
   }

   .in {
      display: block;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: .8em;
      font-style: italic;
      color: white;
      text-align: center;
   }

   .timer {
      display: block;
      width: 7em;
      text-align: center;
      border-style: solid none solid none;
      border-color: #e6e6e6;
      border-width: 1px;
      margin: 0 auto 1em;
   }

   .timer .number {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 4em;
      font-weight: bold;
      color: white;
      text-align: center;
   }

   .timer .days {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 1.5em;
      color: white;
      text-align: center;
      margin: -1em auto 0;
   }

   .urgent-call {
      margin: 3% auto 0;
   }

   .urgent-call .description {
      display: block;
      width: 100%;
      padding-top: 1em;
      padding-bottom: 1em;
      background: -webkit-linear-gradient(left, rgba(86,86,107,0), rgba(86,86,107,.25), rgba(86,86,107,0));
      background: linear-gradient(to right,rgba(86,86,107,0),rgba(86,86,107,.25),rgba(86,86,107,0));
   }

   .urgent-call .first, .urgent-call .second, .urgent-call .third {
      margin: 0 auto;
      width: 90%;
      color: white;
      font-size: 1em;
      text-align: center;
   }

   .urgent-call .first {
      margin-bottom: 0.5em;
   }

   .urgent-call .second {
      width: 100%;
      color: #ff3f5a;
      font-family: 'Khand', sans-serif;
      font-weight: bold;
      font-size: 1.2em;
      text-shadow: 0px 1px 9px rgba(0, 0, 0, 0.35);
      letter-spacing: 0.1em;
   }

   .urgent-call .third {
      margin-top: 0.15em;
   }

   .petition .button {
      display: block;
      width: 120px;
      margin: 1em auto 0;
      padding: 3px 6px;
      background: #829776;
      color: #ffffff;
      font-family: 'Fira Sans', sans-serif;
      font-size: .85em;
      font-weight: 300;
      text-align: center;
      text-decoration: none;
      border: solid #ffffff 1px;
      border-radius: 3px;
   }

   .petition .button:hover {
      background: #4d6b3c;
   }

   footer {
      display: table;
      position: fixed;
      width: 96%;
      bottom: 0;
      padding-left: 2%;
      padding-right: 2%;
   }

   .social {
      display: block;
      vertical-align: middle;
      float: right;
   }

   .social a {
      display: inline-block;
      width: 28px;
      height: 28px;
      background-repeat: no-repeat;
      opacity: .5;
      margin-left: .5em;
   }

   .social a:hover {
      opacity: .9;
   }

   .social a.facebook {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAG1BMVEUAAADY2NjY2NjY2NjY2NhGRkZqamqFhYWtra1jMrL/AAAACXRSTlMAPGaw//////9HdVBWAAAAp0lEQVQoz42TQRLDIAwDVyb/f3GxegAGmJC0PhkWge0RYoYQxuvGSGKkTu9wohW3vQj2yAQoR4Zwh3fWaYAODEJwQWNltqAKEJXShSV71dVWGJCJLuy6+MxFEKwN8uGSPGraml+uaG9s9RuqvVX8FLvSgqJ5PPysdPASP5SP1AS5O2IuEkHRcfCuCFSOt1Y3J5wGkW5O8IFmDg/daTPYH9Z8N/X5O3wBpdI+PxtA6DIAAAAASUVORK5CYII=);
   }

   .social a.twitter {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjV1dXY2NjY2NjY2NjY2NhHR0empqaQkJBtbW3Dw8PQfCyMAAAADHRSTlMAPPVmwKD////////J66Z0AAAA5UlEQVQoz32T0ZKFIAxDT1qc/f+/3VFo9wFQXL23D+oQGpJQxVXCCHJdmB+lFQCq17yDclsoonXYx9NZ+dPy7PQbBEBro/MFw0gwUPJSKRAUewOJiqEbZu5QAUyITQBbVgAPwHUA5OHQO6N4zOMsAFpKW89lAw8FgLW+6XB1Hz9KcuY6XuEjt12XqBKn2bGwgMcpfe7a/XFRYQ+uUzRY9wdE7/DfCdX0cZp5l2jt5FI46QC5F5M4Fl31e/AOmW9oDbB+c89S9klI7POYkIvf4aJd05do5Y6IZTQhYjqsqvE/yLff4Q+6BFspw2Tr1AAAAABJRU5ErkJggg==);
   }

   .social a.github {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjY2NjY2NjY2NjY2NhHR0ebm5u3t7dYWFh3d3dqampwrbVmAAAADHRSTlMAPGbxsP////////80TrKnAAAA4UlEQVQoz32TwW7DMAxDH+ns/z94tbhDpDRBi+lkSCBN0bR4lxAh98YcVgxAaec51NKNIj1eANjmyR+AA8CLZxmqkR8zwAQMEl9KAsExQy+RXaPqxXEBl9gidnZDowGu0olxvBvqcUTSOgmGKlhudeU6JJWLbmmWXwXs04Ga1UaqVK/z9LsuT9+2/XxxovWkFwB2pjfI7ZaB8L6Q53aFdw44UqZb8dyek0R4WMUa5iybIEvNuv83XqBnDLqqgiH59p7JmYTwCd0TE3KLaHPWO315ZiV1jyZUFLUdl2D99x3+AND/ZE+Y11fiAAAAAElFTkSuQmCC);
   }

   @media all and (max-width: 319px) {
      main {
         margin: auto 0;
      }

      h1 {
         margin: -7% auto 0;
         font-size: 1.6em;
      }

      h2 {
         margin: 0 auto;
         font-size: .8em;
      }

      .coming-soon {
         margin: .7em auto 0;
         font-size: .8em;
      }

      .in {
         font-size: .7em;
      }

      .timer {
         width: 3em;
         margin: 0 auto .2em;
      }

      .timer .number {
         font-size: 2em;
      }

      .timer .days {
         font-size: .75em;
      }

      .urgent-call {
         margin: 0 auto;
      }

      .urgent-call .description {
         font-size: 0.7em;
      }

      .petition .button {
         width: 120px;
         margin: 1em auto 0;
         padding: 3px;
         font-size: .6em;
      }
   }

   @media all and (min-width: 320px) and (max-width: 460px) {
      h1 {
         margin: 0 auto;
         font-size: 2.5em;
      }

      h2 {
         margin: 0 auto 2em;
         font-size: .9em;
      }

      .coming-soon {
         margin: 0 auto;
         font-size: 1.3em;
      }

      .timer {
         width: 5em;
         margin: 0 auto 1em;
      }

      .timer .number {
         font-size: 2.8em;
      }

      .timer .days {
         font-size: 1.1em;
      }

      .urgent-call .description {
         font-size: .85em;
      }

      .petition .button {
         width: 100px;
         margin: 1em auto 0;
         font-size: .6em;
      }
   }

   @media all and (min-width: 1600px) {
      h1 {
         font-size: 5em;
      }

      h2 {
         font-size: 1.7em;
      }

      .coming-soon {
         font-size: 2.25em;
      }

      .in {
         font-size: 1.2em;
      }

      .timer {
         width: 10em;
         margin: 0.5em auto 2em;
      }

      .timer .number {
         font-size: 5em;
      }

      .timer .days {
         font-size: 2.25em;
      }

      .urgent-call .description {
      }

      .urgent-call .first, .urgent-call .third {
         font-size: 1.5em;
      }

      .urgent-call .second {
         font-size: 1.8em;
      }

      .petition .button {
         width: 180px;
         margin: 1em auto 0;
         padding: 5px;
         font-size: 1.2em;
      }
   }
";
<commit_msg>Trying a new color adjustments on the coming soon page.<commit_after>#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_handler, c_coming_soon_handler, coming_soon_module, b"mod_coming_soon\0");

macro_rules! html_template {() => ("<!doctype html>

      <meta charset=\"utf-8\">
      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">
      <title>PolyDraw – Coming Soon</title>
      <meta name=\"description\" content=\"PolyDraw website is coming soon\">
      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">

      <link href=\"https://fonts.googleapis.com/css?family=Fira+Sans:300,500\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Roboto+Condensed:400\" rel=\"stylesheet\" type=\"text/css\">
      <link href=\"https://fonts.googleapis.com/css?family=Khand:400\" rel=\"stylesheet\" type=\"text/css\">

PolyDraw

Open source software development

COMING SOON

in

000

days

                  In the meantime, please sign the international petition against

ORGAN HARVESTING

from Falun Gong practitioners in China!

                  JOIN THE PETITION!

")}

fn coming_soon_handler(r: &mut Request) -> Status {
   if r.handler().unwrap() != "coming-soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(format!(
      html_template!(),
      STYLESHEET
   ));

   Status::OK
}

const STYLESHEET: &'static str = "
   html, body {
      height: 100%;
      width: 100%;
      margin: 0;
   }

   body {
      display: block;
      font-family: 'Roboto Condensed', sans-serif;
      background-image: url(https://www.polydraw.com/img/mountain-mist.jpg);
      background-size: cover;
      background-repeat: no-repeat;
      background-attachment: fixed;
      background-position: right bottom;
   }

   main {
      display: block;
      position: relative;
      top: 50%;
      margin: 0 auto;
      -webkit-transform: translateY(-50%);
      -ms-transform: translateY(-50%);
      transform: translateY(-50%);
   }

   h1 {
      display: block;
      width: 60%;
      margin: 0 auto;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 500;
      font-size: 3.5em;
      color: white;
      text-align: center;
   }

   h2 {
      display: block;
      width: 70%;
      margin: -0.2em auto 0;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: 1.2em;
      color: #5b5b5b;
      text-align: center;
   }

   .coming-soon {
      display: block;
      width: 40%;
      margin: 2.5em auto .1em;
      font-size: 1.5em;
      color: white;
      text-align: center;
   }

   .in {
      display: block;
      font-family: 'Fira Sans', sans-serif;
      font-weight: 300;
      font-size: .8em;
      font-style: italic;
      color: white;
      text-align: center;
   }

   .timer {
      display: block;
      width: 7em;
      text-align: center;
      border-style: solid none solid none;
      border-color: #e6e6e6;
      border-width: 1px;
      margin: 0 auto 1em;
   }

   .timer .number {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 4em;
      font-weight: bold;
      color: white;
      text-align: center;
   }

   .timer .days {
      display: block;
      font-family: 'Khand', sans-serif;
      font-size: 1.5em;
      color: white;
      text-align: center;
      margin: -1em auto 0;
   }

   .urgent-call {
      margin: 3% auto 0;
   }

   .urgent-call .description {
      display: block;
      width: 100%;
      padding-top: 1em;
      padding-bottom: 1em;
      background: -webkit-linear-gradient(left, rgba(86,86,107,0), rgba(86,86,107,.25), rgba(86,86,107,0));
      background: linear-gradient(to right,rgba(86,86,107,0),rgba(86,86,107,.25),rgba(86,86,107,0));
   }

   .urgent-call .first, .urgent-call .second, .urgent-call .third {
      margin: 0 auto;
      width: 90%;
      color: white;
      font-size: 1em;
      text-align: center;
   }

   .urgent-call .first {
      margin-bottom: 0.5em;
   }

   .urgent-call .second {
      width: 100%;
      color: #F37875;
      font-family: 'Khand', sans-serif;
      font-weight: bold;
      font-size: 1.2em;
      text-shadow: 0px 1px 9px rgba(0, 0, 0, 0.3);
      letter-spacing: 0.1em;
   }

   .urgent-call .third {
      margin-top: 0.15em;
   }

   .petition .button {
      display: block;
      width: 120px;
      margin: 1em auto 0;
      padding: 3px 6px;
      background: #829776;
      color: #ffffff;
      font-family: 'Fira Sans', sans-serif;
      font-size: .85em;
      font-weight: 300;
      text-align: center;
      text-decoration: none;
      border: solid #ffffff 1px;
      border-radius: 3px;
   }

   .petition .button:hover {
      background: #4d6b3c;
   }

   footer {
      display: table;
      position: fixed;
      width: 96%;
      bottom: 0;
      padding-left: 2%;
      padding-right: 2%;
   }

   .social {
      display: block;
      vertical-align: middle;
      float: right;
   }

   .social a {
      display: inline-block;
      width: 28px;
      height: 28px;
      background-repeat: no-repeat;
      opacity: .5;
      margin-left: .5em;
   }

   .social a:hover {
      opacity: .9;
   }

   .social a.facebook {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAG1BMVEUAAADY2NjY2NjY2NjY2NhGRkZqamqFhYWtra1jMrL/AAAACXRSTlMAPGaw//////9HdVBWAAAAp0lEQVQoz42TQRLDIAwDVyb/f3GxegAGmJC0PhkWge0RYoYQxuvGSGKkTu9wohW3vQj2yAQoR4Zwh3fWaYAODEJwQWNltqAKEJXShSV71dVWGJCJLuy6+MxFEKwN8uGSPGraml+uaG9s9RuqvVX8FLvSgqJ5PPysdPASP5SP1AS5O2IuEkHRcfCuCFSOt1Y3J5wGkW5O8IFmDg/daTPYH9Z8N/X5O3wBpdI+PxtA6DIAAAAASUVORK5CYII=);
   }

   .social a.twitter {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjV1dXY2NjY2NjY2NjY2NhHR0empqaQkJBtbW3Dw8PQfCyMAAAADHRSTlMAPPVmwKD////////J66Z0AAAA5UlEQVQoz32T0ZKFIAxDT1qc/f+/3VFo9wFQXL23D+oQGpJQxVXCCHJdmB+lFQCq17yDclsoonXYx9NZ+dPy7PQbBEBro/MFw0gwUPJSKRAUewOJiqEbZu5QAUyITQBbVgAPwHUA5OHQO6N4zOMsAFpKW89lAw8FgLW+6XB1Hz9KcuY6XuEjt12XqBKn2bGwgMcpfe7a/XFRYQ+uUzRY9wdE7/DfCdX0cZp5l2jt5FI46QC5F5M4Fl31e/AOmW9oDbB+c89S9klI7POYkIvf4aJd05do5Y6IZTQhYjqsqvE/yLff4Q+6BFspw2Tr1AAAAABJRU5ErkJggg==);
   }

   .social a.github {
      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAJFBMVEUAAADY2NjY2NjY2NjY2NjY2NhHR0ebm5u3t7dYWFh3d3dqampwrbVmAAAADHRSTlMAPGbxsP////////80TrKnAAAA4UlEQVQoz32TwW7DMAxDH+ns/z94tbhDpDRBi+lkSCBN0bR4lxAh98YcVgxAaec51NKNIj1eANjmyR+AA8CLZxmqkR8zwAQMEl9KAsExQy+RXaPqxXEBl9gidnZDowGu0olxvBvqcUTSOgmGKlhudeU6JJWLbmmWXwXs04Ga1UaqVK/z9LsuT9+2/XxxovWkFwB2pjfI7ZaB8L6Q53aFdw44UqZb8dyek0R4WMUa5iybIEvNuv83XqBnDLqqgiH59p7JmYTwCd0TE3KLaHPWO315ZiV1jyZUFLUdl2D99x3+AND/ZE+Y11fiAAAAAElFTkSuQmCC);
   }

   @media all and (max-width: 319px) {
      main {
         margin: auto 0;
      }

      h1 {
         margin: -7% auto 0;
         font-size: 1.6em;
      }

      h2 {
         margin: 0 auto;
         font-size: .8em;
      }

      .coming-soon {
         margin: .7em auto 0;
         font-size: .8em;
      }

      .in {
         font-size: .7em;
      }

      .timer {
         width: 3em;
         margin: 0 auto .2em;
      }

      .timer .number {
         font-size: 2em;
      }

      .timer .days {
         font-size: .75em;
      }

      .urgent-call {
         margin: 0 auto;
      }

      .urgent-call .description {
         font-size: 0.7em;
      }

      .petition .button {
         width: 120px;
         margin: 1em auto 0;
         padding: 3px;
         font-size: .6em;
      }
   }

   @media all and (min-width: 320px) and (max-width: 460px) {
      h1 {
         margin: 0 auto;
         font-size: 2.5em;
      }

      h2 {
         margin: 0 auto 2em;
         font-size: .9em;
      }

      .coming-soon {
         margin: 0 auto;
         font-size: 1.3em;
      }

      .timer {
         width: 5em;
         margin: 0 auto 1em;
      }

      .timer .number {
         font-size: 2.8em;
      }

      .timer .days {
         font-size: 1.1em;
      }

      .urgent-call .description {
         font-size: .85em;
      }

      .petition .button {
         width: 100px;
         margin: 1em auto 0;
         font-size: .6em;
      }
   }

   @media all and (min-width: 1600px) {
      h1 {
         font-size: 5em;
      }

      h2 {
         font-size: 1.7em;
      }

      .coming-soon {
         font-size: 2.25em;
      }

      .in {
         font-size: 1.2em;
      }

      .timer {
         width: 10em;
         margin: 0.5em auto 2em;
      }

      .timer .number {
         font-size: 5em;
      }

      .timer .days {
         font-size: 2.25em;
      }

      .urgent-call .description {
      }

      .urgent-call .first, .urgent-call .third {
         font-size: 1.5em;
      }

      .urgent-call .second {
         font-size: 1.8em;
      }

      .petition .button {
         width: 180px;
         margin: 1em auto 0;
         padding: 5px;
         font-size: 1.2em;
      }
   }
";
<|endoftext|>


<commit_before>extern crate rand;

use rand::distributions::{IndependentSample, Range};

pub fn private_key(p: u64) -> u64 {
    Range::new(2, p).ind_sample(&mut rand::thread_rng())
}

pub fn public_key(p: u64, g: u64, a: u64) -> u64 {
    g.pow(a as u32) % p
}

pub fn secret(p: u64, b_pub: u64, a: u64) -> u64 {
    b_pub.pow(a as u32) % p
}
<commit_msg>diffie-hellman: Modified example file to use modular exponentiation<commit_after>extern crate rand;

use rand::distributions::{IndependentSample, Range};

/// Right-to-left modular exponentiation implementation
/// For more information see https://en.wikipedia.org/wiki/Modular_exponentiation
fn modular_exponentiation(base: u64, exponent: u64, modulus: u64) -> u64 {
    let mut result = 1;

    let mut e = exponent;

    let mut b = base;

    while e > 0 {
        if (e & 1) == 1 {
            result = (result * b) % modulus;
        }

        e >>= 1;

        b = (b * b) % modulus;
    }

    result
}

pub fn private_key(p: u64) -> u64 {
    Range::new(2, p).ind_sample(&mut rand::thread_rng())
}

pub fn public_key(p: u64, g: u64, a: u64) -> u64 {
    modular_exponentiation(g, a, p)
}

pub fn secret(p: u64, b_pub: u64, a: u64) -> u64 {
    modular_exponentiation(b_pub, a, p)
}
<|endoftext|>


<commit_before>use events::Milliseconds;
use node::State;

const MIN_TIMEOUT: Milliseconds = 50;
const MAX_TIMEOUT: Milliseconds = 200;

/// `TimeoutAdjuster` trait can be used to dynamically change propose timeout.
///
/// # Examples
///
/// Implementing `TimeoutAdjuster`:
///
/// ```
/// use exonum::node::{State, TimeoutAdjuster};
/// use exonum::events::Milliseconds;
///
/// struct Adjuster {}
///
/// impl TimeoutAdjuster for Adjuster {
///     fn init(&mut self, _: &State) -> Milliseconds {
///         0
///     }
///
///     fn adjust_timeout(&mut self, state: &State) -> Milliseconds {
///         // Simply increase propose time after empty blocks.
///         if state.transactions().is_empty() {
///             1000
///         } else {
///             200
///         }
///     }
/// }
/// ```
pub trait TimeoutAdjuster {
    /// Called during node initialization.
    fn init(&mut self, state: &State) -> Milliseconds;

    /// Called after accepting a new height.
    fn adjust_timeout(&mut self, state: &State) -> Milliseconds;
}

/// `TimeoutAdjuster` implementation that always returns the same value.
pub struct ConstantTimeout {
    timeout: Milliseconds,
}

impl ConstantTimeout {
    /// Creates `ConstantTimeout` with given timeout value.
    pub fn new(timeout: Milliseconds) -> Self {
        ConstantTimeout { timeout: timeout }
    }
}

impl Default for ConstantTimeout {
    fn default() -> Self {
        ConstantTimeout{ timeout: MAX_TIMEOUT }
    }
}

impl TimeoutAdjuster for ConstantTimeout {
    fn init(&mut self, _: &State) -> Milliseconds {
        self.timeout
    }

    fn adjust_timeout(&mut self, _: &State) -> Milliseconds {
        self.timeout
    }
}

/// Calculates propose timeout using last block size and precious timeout.
///
/// `target_delta_t =
///     DELTA_T_MAX - (DELTA_T_MAX - DELTA_T_MIN) * min(1, block  / (ALPHA * MAX_BLOCK))`
pub struct DynamicTimeout {
    min_timeout: Milliseconds,
    max_timeout: Milliseconds,
    adjustment_speed: f64,
    target_block_portion_feel: f64,
    desired_max_block_size: u64,
}

impl DynamicTimeout {
    /// Created `DynamicTimeout` with default values.
    pub fn new() -> Self {
        Self::default()
    }
}

impl Default for DynamicTimeout {
    fn default() -> Self {
        DynamicTimeout{
            min_timeout: MIN_TIMEOUT,
            max_timeout: MAX_TIMEOUT,
            adjustment_speed: 0.7,
            target_block_portion_feel: 0.7,
            desired_max_block_size: 3000,
        }
    }
}

impl TimeoutAdjuster for DynamicTimeout {
    fn init(&mut self, _: &State) -> Milliseconds {
        MIN_TIMEOUT
    }

    fn adjust_timeout(&mut self, state: &State) -> Milliseconds {
        let last_block_size = state.transactions().len() as f64;

        // min(1, block  / (ALPHA * MAX_BLOCK))
        let filling_rate = 1f64.min(last_block_size /
            (self.target_block_portion_feel * self.desired_max_block_size as f64));

        // (DELTA_T_MAX - DELTA_T_MIN)
        let adjusted_timeout = (self.max_timeout - self.min_timeout) as f64;

        // Collects parts of the original formula.
        let target_timeout = self.max_timeout as f64 + adjusted_timeout * filling_rate;

        // delta_t = delta_t * BETA + (1 - BETA) * target_delta_t
        (target_timeout * self.adjustment_speed + state.propose_timeout() as f64
            * (1f64 - self.adjustment_speed)) as Milliseconds
    }
}<commit_msg>Add new line<commit_after>use events::Milliseconds;
use node::State;

const MIN_TIMEOUT: Milliseconds = 50;
const MAX_TIMEOUT: Milliseconds = 200;

/// `TimeoutAdjuster` trait can be used to dynamically change propose timeout.
///
/// # Examples
///
/// Implementing `TimeoutAdjuster`:
///
/// ```
/// use exonum::node::{State, TimeoutAdjuster};
/// use exonum::events::Milliseconds;
///
/// struct Adjuster {}
///
/// impl TimeoutAdjuster for Adjuster {
///     fn init(&mut self, _: &State) -> Milliseconds {
///         0
///     }
///
///     fn adjust_timeout(&mut self, state: &State) -> Milliseconds {
///         // Simply increase propose time after empty blocks.
///         if state.transactions().is_empty() {
///             1000
///         } else {
///             200
///         }
///     }
/// }
/// ```
pub trait TimeoutAdjuster {
    /// Called during node initialization.
    fn init(&mut self, state: &State) -> Milliseconds;

    /// Called after accepting a new height.
    fn adjust_timeout(&mut self, state: &State) -> Milliseconds;
}

/// `TimeoutAdjuster` implementation that always returns the same value.
pub struct ConstantTimeout {
    timeout: Milliseconds,
}

impl ConstantTimeout {
    /// Creates `ConstantTimeout` with given timeout value.
    pub fn new(timeout: Milliseconds) -> Self {
        ConstantTimeout { timeout: timeout }
    }
}

impl Default for ConstantTimeout {
    fn default() -> Self {
        ConstantTimeout{ timeout: MAX_TIMEOUT }
    }
}

impl TimeoutAdjuster for ConstantTimeout {
    fn init(&mut self, _: &State) -> Milliseconds {
        self.timeout
    }

    fn adjust_timeout(&mut self, _: &State) -> Milliseconds {
        self.timeout
    }
}

/// Calculates propose timeout using last block size and precious timeout.
///
/// `target_delta_t =
///     DELTA_T_MAX - (DELTA_T_MAX - DELTA_T_MIN) * min(1, block  / (ALPHA * MAX_BLOCK))`
pub struct DynamicTimeout {
    min_timeout: Milliseconds,
    max_timeout: Milliseconds,
    adjustment_speed: f64,
    target_block_portion_feel: f64,
    desired_max_block_size: u64,
}

impl DynamicTimeout {
    /// Created `DynamicTimeout` with default values.
    pub fn new() -> Self {
        Self::default()
    }
}

impl Default for DynamicTimeout {
    fn default() -> Self {
        DynamicTimeout{
            min_timeout: MIN_TIMEOUT,
            max_timeout: MAX_TIMEOUT,
            adjustment_speed: 0.7,
            target_block_portion_feel: 0.7,
            desired_max_block_size: 3000,
        }
    }
}

impl TimeoutAdjuster for DynamicTimeout {
    fn init(&mut self, _: &State) -> Milliseconds {
        MIN_TIMEOUT
    }

    fn adjust_timeout(&mut self, state: &State) -> Milliseconds {
        let last_block_size = state.transactions().len() as f64;

        // min(1, block  / (ALPHA * MAX_BLOCK))
        let filling_rate = 1f64.min(last_block_size /
            (self.target_block_portion_feel * self.desired_max_block_size as f64));

        // (DELTA_T_MAX - DELTA_T_MIN)
        let adjusted_timeout = (self.max_timeout - self.min_timeout) as f64;

        // Collects parts of the original formula.
        let target_timeout = self.max_timeout as f64 + adjusted_timeout * filling_rate;

        // delta_t = delta_t * BETA + (1 - BETA) * target_delta_t
        (target_timeout * self.adjustment_speed + state.propose_timeout() as f64
            * (1f64 - self.adjustment_speed)) as Milliseconds
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

mod block_info;
mod block_allocator;
mod allocator;

use self::block_allocator::BlockAllocator;
use self::allocator::Allocator;
use self::allocator::NormalAllocator;
use self::allocator::OverflowAllocator;
use self::allocator::EvacAllocator;

pub use self::block_info::BlockInfo;

use std::{mem, ptr};
use std::rc::Rc;
use std::cell::RefCell;

use constants::{BLOCK_SIZE, MEDIUM_OBJECT};
use gc_object::{GCRTTI, GCObject, GCObjectRef};

/// The `ImmixSpace` is the default space to allocate objects into.
///
/// Objects larger than `LARGE_OBJECT` are allocated using the
/// `LargeObjectSpace`.
///
/// The `ImmixSpace` partitions the heap into `BLOCK_SIZE` blocks of
/// `LINE_SIZE` lines. Objects are allocated into free lines on free or
/// partially used blocks.
///
/// Lines are marked with the number of live objects. This counter is
/// maintained by the `RCCollector` and the `ImmixCollector`. If it drops to
/// zero the line can be reclaimed. If a block has only free lines it can be
/// returned to the global block allocator.
pub struct ImmixSpace {
    /// The global `BlockAllocator` to get new blocks from.
    block_allocator: Rc<RefCell<BlockAllocator>>,

    /// The nomal allocator for objects smaller than `MEDIUM_OBJECT` bytes.
    allocator: NormalAllocator,

    /// The overflow allocator for objects larger than `MEDIUM_OBJECT` bytes.
    overflow_allocator: OverflowAllocator,

    /// The evacuation allocator used during an evacuating collection.
    evac_allocator: EvacAllocator,

    /// The current live mark for new objects. See `Spaces.current_live_mark`.
    current_live_mark: bool,
}

impl ImmixSpace {
    /// Create a new `ImmixSpace`.
    ///
    /// This also initializes the `BlockAllocator` which will allocate a
    /// memory map of `HEAP_SIZE` bytes. The allocation will fail if there is
    /// not enough memory available.
    pub fn new() -> ImmixSpace {
        let block_allocator = Rc::new(RefCell::new(BlockAllocator::new()));
        let normal_block_allocator = block_allocator.clone();
        let overflow_block_allocator = block_allocator.clone();
        return ImmixSpace {
            block_allocator: block_allocator,
            allocator: NormalAllocator::new(normal_block_allocator),
            overflow_allocator: OverflowAllocator::new(overflow_block_allocator),
            evac_allocator: EvacAllocator::new(),
            current_live_mark: false,
        };
    }

    /// Decrement the lines on which the object is allocated.
    pub fn decrement_lines(&self, object: GCObjectRef) {
        debug!("decrement_lines() on object {:p}", object);
        debug_assert!(self.is_gc_object(object),
                     "decrement_lines() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).decrement_lines(object); }
    }

    /// Increment the lines on which the object is allocated.
    pub fn increment_lines(&self, object: GCObjectRef) {
        debug!("increment_lines() on object {:p}", object);
        debug_assert!(self.is_gc_object(object),
                      "increment_lines() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).increment_lines(object); }
    }

    /// Set an address in this space as a valid object.
    pub fn set_gc_object(&self, object: GCObjectRef) {
        debug!("set_gc_object() on object {:p}", object);
        debug_assert!(self.block_allocator.borrow().is_in_space(object),
                      "set_gc_object() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).set_gc_object(object); }
    }

    /// Unset an address as a valid object within the immix space.
    pub fn unset_gc_object(&self, object: GCObjectRef) {
        debug!("unset_gc_object() on object {:p}", object);
        debug_assert!(self.block_allocator.borrow().is_in_space(object),
                      "unset_gc_object() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).unset_gc_object(object); }
    }

    /// Return if the object an the address is a valid object within the immix
    /// space.
    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        if self.block_allocator.borrow().is_in_space(object) {
            return unsafe{ (*ImmixSpace::get_block_ptr(object)).is_gc_object(object) };
        }
        return false;
    }

    /// Return a closure that behaves like `ImmixSpace::is_gc_object()`.
    pub fn is_gc_object_filter<'a>(&'a self) -> Box<Fn(GCObjectRef) -> bool + 'a> {
        let block_allocator = self.block_allocator.borrow();
        return Box::new(move |object: GCObjectRef| block_allocator.is_in_space(object)
            && unsafe{ (*ImmixSpace::get_block_ptr(object)).is_gc_object(object) });
    }

    /// Return if the object an the address is within the immix space.
    pub fn is_in_space(&self, object: GCObjectRef) -> bool {
        return self.block_allocator.borrow().is_in_space(object);
    }

    /// Return the total number of possible blocks.
    pub fn total_blocks(&self) -> usize {
        return self.block_allocator.borrow().total_blocks();
    }

    /// Return the number of unallocated blocks.
    pub fn available_blocks(&self) -> usize {
        return self.block_allocator.borrow().available_blocks();
    }

    /// Get the number of currently free blocks in the evacuation allocator.
    pub fn evac_headroom(&self) -> usize {
        return self.evac_allocator.evac_headroom();
    }

    /// Return a collection of blocks to the global block allocator.
    pub fn return_blocks(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.block_allocator.borrow_mut().return_blocks(blocks);
    }

    /// Set the current live mark to `current_live_mark`.
    pub fn set_current_live_mark(&mut self, current_live_mark: bool) {
        self.current_live_mark = current_live_mark;
    }

    /// Set the recyclable blocks for the `NormalAllocator`.
    pub fn set_recyclable_blocks(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.allocator.set_recyclable_blocks(blocks);
    }

    /// Extend the list of free blocks in the `EvacAllocator` for evacuation.
    pub fn extend_evac_headroom(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.evac_allocator.extend_evac_headroom(blocks);
    }

    /// Get all block managed by all allocators, draining any local
    /// collections.
    pub fn get_all_blocks(&mut self) -> Vec<*mut BlockInfo> {
        let mut normal_blocks = self.allocator.get_all_blocks();
        let mut overflow_blocks = self.overflow_allocator.get_all_blocks();
        let mut evac_blocks = self.evac_allocator.get_all_blocks();
        return normal_blocks.drain()
                            .chain(overflow_blocks.drain())
                            .chain(evac_blocks.drain())
                            .collect();
    }

    /// Allocate an object of `size` bytes or return `None` if the allocation
    /// failed.
    ///
    /// This object is initialized and ready to use.
    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        let size = unsafe{ (*rtti).object_size() };
        debug!("Request to allocate an object of size {}", size);
        if let Some(object) = if size < MEDIUM_OBJECT { self.allocator.allocate(size) }
                              else { self.overflow_allocator.allocate(size) } {
            unsafe { ptr::write(object, GCObject::new(rtti, self.current_live_mark)); }
            unsafe{ (*ImmixSpace::get_block_ptr(object)).set_new_object(object); }
            self.set_gc_object(object);
            return Some(object);
        }
        return None;
    }

    /// Evacuate the object to another block using the `EvacAllocator`
    /// returning the new address or `None` if no evacuation was performed.
    ///
    /// An object is evacuated if it is not pinned, it resides on an
    /// evacuation candidate block and the evacuation allocator hat enough
    /// space left.
    ///
    /// On successful evacuation the old object is marked as forewarded an an
    /// forewarding pointer is installed.
    pub fn maybe_evacuate(&mut self, object: GCObjectRef) -> Option<GCObjectRef> {
        let block_info = unsafe{ ImmixSpace::get_block_ptr(object) };
        let is_pinned = unsafe{ (*object).is_pinned() };
        let is_candidate = unsafe{ (*block_info).is_evacuation_candidate() };
        if is_pinned || !is_candidate {
            return None;
        }
        let size = unsafe{ (*object).object_size() };
        if let Some(new_object) = self.evac_allocator.allocate(size) {
            unsafe{
                ptr::copy_nonoverlapping_memory(new_object as *mut u8,
                                                object as *const u8, size);
                debug_assert!(*object == *new_object,
                              "Evacuated object was not copied correcty");
                (*object).set_forwarded(new_object);
                self.set_gc_object(object);
            }
            debug!("Evacuated object {:p} from block {:p} to {:p}", object,
                   block_info, new_object);
            valgrind_freelike!(object);
            return Some(new_object);
        }
        debug!("Can't evacuation object {:p} from block {:p}", object, block_info);
        return None;
    }
}

impl ImmixSpace {
    /// Get the block for the given object.
    unsafe fn get_block_ptr(object: GCObjectRef) -> *mut BlockInfo {
        let block_offset = object as usize % BLOCK_SIZE;
        let block = mem::transmute((object as *mut u8).offset(-(block_offset as isize)));
        debug!("Block for object {:p}: {:p} with offset: {}", object, block, block_offset);
        return block;
    }
}
<commit_msg>Fix deprecation warning (rust update)<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

mod block_info;
mod block_allocator;
mod allocator;

use self::block_allocator::BlockAllocator;
use self::allocator::Allocator;
use self::allocator::NormalAllocator;
use self::allocator::OverflowAllocator;
use self::allocator::EvacAllocator;

pub use self::block_info::BlockInfo;

use std::{mem, ptr};
use std::rc::Rc;
use std::cell::RefCell;

use constants::{BLOCK_SIZE, MEDIUM_OBJECT};
use gc_object::{GCRTTI, GCObject, GCObjectRef};

/// The `ImmixSpace` is the default space to allocate objects into.
///
/// Objects larger than `LARGE_OBJECT` are allocated using the
/// `LargeObjectSpace`.
///
/// The `ImmixSpace` partitions the heap into `BLOCK_SIZE` blocks of
/// `LINE_SIZE` lines. Objects are allocated into free lines on free or
/// partially used blocks.
///
/// Lines are marked with the number of live objects. This counter is
/// maintained by the `RCCollector` and the `ImmixCollector`. If it drops to
/// zero the line can be reclaimed. If a block has only free lines it can be
/// returned to the global block allocator.
pub struct ImmixSpace {
    /// The global `BlockAllocator` to get new blocks from.
    block_allocator: Rc<RefCell<BlockAllocator>>,

    /// The nomal allocator for objects smaller than `MEDIUM_OBJECT` bytes.
    allocator: NormalAllocator,

    /// The overflow allocator for objects larger than `MEDIUM_OBJECT` bytes.
    overflow_allocator: OverflowAllocator,

    /// The evacuation allocator used during an evacuating collection.
    evac_allocator: EvacAllocator,

    /// The current live mark for new objects. See `Spaces.current_live_mark`.
    current_live_mark: bool,
}

impl ImmixSpace {
    /// Create a new `ImmixSpace`.
    ///
    /// This also initializes the `BlockAllocator` which will allocate a
    /// memory map of `HEAP_SIZE` bytes. The allocation will fail if there is
    /// not enough memory available.
    pub fn new() -> ImmixSpace {
        let block_allocator = Rc::new(RefCell::new(BlockAllocator::new()));
        let normal_block_allocator = block_allocator.clone();
        let overflow_block_allocator = block_allocator.clone();
        return ImmixSpace {
            block_allocator: block_allocator,
            allocator: NormalAllocator::new(normal_block_allocator),
            overflow_allocator: OverflowAllocator::new(overflow_block_allocator),
            evac_allocator: EvacAllocator::new(),
            current_live_mark: false,
        };
    }

    /// Decrement the lines on which the object is allocated.
    pub fn decrement_lines(&self, object: GCObjectRef) {
        debug!("decrement_lines() on object {:p}", object);
        debug_assert!(self.is_gc_object(object),
                     "decrement_lines() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).decrement_lines(object); }
    }

    /// Increment the lines on which the object is allocated.
    pub fn increment_lines(&self, object: GCObjectRef) {
        debug!("increment_lines() on object {:p}", object);
        debug_assert!(self.is_gc_object(object),
                      "increment_lines() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).increment_lines(object); }
    }

    /// Set an address in this space as a valid object.
    pub fn set_gc_object(&self, object: GCObjectRef) {
        debug!("set_gc_object() on object {:p}", object);
        debug_assert!(self.block_allocator.borrow().is_in_space(object),
                      "set_gc_object() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).set_gc_object(object); }
    }

    /// Unset an address as a valid object within the immix space.
    pub fn unset_gc_object(&self, object: GCObjectRef) {
        debug!("unset_gc_object() on object {:p}", object);
        debug_assert!(self.block_allocator.borrow().is_in_space(object),
                      "unset_gc_object() on invalid object {:p}", object);
        unsafe{ (*ImmixSpace::get_block_ptr(object)).unset_gc_object(object); }
    }

    /// Return if the object an the address is a valid object within the immix
    /// space.
    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        if self.block_allocator.borrow().is_in_space(object) {
            return unsafe{ (*ImmixSpace::get_block_ptr(object)).is_gc_object(object) };
        }
        return false;
    }

    /// Return a closure that behaves like `ImmixSpace::is_gc_object()`.
    pub fn is_gc_object_filter<'a>(&'a self) -> Box<Fn(GCObjectRef) -> bool + 'a> {
        let block_allocator = self.block_allocator.borrow();
        return Box::new(move |object: GCObjectRef| block_allocator.is_in_space(object)
            && unsafe{ (*ImmixSpace::get_block_ptr(object)).is_gc_object(object) });
    }

    /// Return if the object an the address is within the immix space.
    pub fn is_in_space(&self, object: GCObjectRef) -> bool {
        return self.block_allocator.borrow().is_in_space(object);
    }

    /// Return the total number of possible blocks.
    pub fn total_blocks(&self) -> usize {
        return self.block_allocator.borrow().total_blocks();
    }

    /// Return the number of unallocated blocks.
    pub fn available_blocks(&self) -> usize {
        return self.block_allocator.borrow().available_blocks();
    }

    /// Get the number of currently free blocks in the evacuation allocator.
    pub fn evac_headroom(&self) -> usize {
        return self.evac_allocator.evac_headroom();
    }

    /// Return a collection of blocks to the global block allocator.
    pub fn return_blocks(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.block_allocator.borrow_mut().return_blocks(blocks);
    }

    /// Set the current live mark to `current_live_mark`.
    pub fn set_current_live_mark(&mut self, current_live_mark: bool) {
        self.current_live_mark = current_live_mark;
    }

    /// Set the recyclable blocks for the `NormalAllocator`.
    pub fn set_recyclable_blocks(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.allocator.set_recyclable_blocks(blocks);
    }

    /// Extend the list of free blocks in the `EvacAllocator` for evacuation.
    pub fn extend_evac_headroom(&mut self, blocks: Vec<*mut BlockInfo>) {
        self.evac_allocator.extend_evac_headroom(blocks);
    }

    /// Get all block managed by all allocators, draining any local
    /// collections.
    pub fn get_all_blocks(&mut self) -> Vec<*mut BlockInfo> {
        let mut normal_blocks = self.allocator.get_all_blocks();
        let mut overflow_blocks = self.overflow_allocator.get_all_blocks();
        let mut evac_blocks = self.evac_allocator.get_all_blocks();
        return normal_blocks.drain()
                            .chain(overflow_blocks.drain())
                            .chain(evac_blocks.drain())
                            .collect();
    }

    /// Allocate an object of `size` bytes or return `None` if the allocation
    /// failed.
    ///
    /// This object is initialized and ready to use.
    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        let size = unsafe{ (*rtti).object_size() };
        debug!("Request to allocate an object of size {}", size);
        if let Some(object) = if size < MEDIUM_OBJECT { self.allocator.allocate(size) }
                              else { self.overflow_allocator.allocate(size) } {
            unsafe { ptr::write(object, GCObject::new(rtti, self.current_live_mark)); }
            unsafe{ (*ImmixSpace::get_block_ptr(object)).set_new_object(object); }
            self.set_gc_object(object);
            return Some(object);
        }
        return None;
    }

    /// Evacuate the object to another block using the `EvacAllocator`
    /// returning the new address or `None` if no evacuation was performed.
    ///
    /// An object is evacuated if it is not pinned, it resides on an
    /// evacuation candidate block and the evacuation allocator hat enough
    /// space left.
    ///
    /// On successful evacuation the old object is marked as forewarded an an
    /// forewarding pointer is installed.
    pub fn maybe_evacuate(&mut self, object: GCObjectRef) -> Option<GCObjectRef> {
        let block_info = unsafe{ ImmixSpace::get_block_ptr(object) };
        let is_pinned = unsafe{ (*object).is_pinned() };
        let is_candidate = unsafe{ (*block_info).is_evacuation_candidate() };
        if is_pinned || !is_candidate {
            return None;
        }
        let size = unsafe{ (*object).object_size() };
        if let Some(new_object) = self.evac_allocator.allocate(size) {
            unsafe{
                ptr::copy_nonoverlapping(new_object as *mut u8,
                                         object as *const u8, size);
                debug_assert!(*object == *new_object,
                              "Evacuated object was not copied correcty");
                (*object).set_forwarded(new_object);
                self.set_gc_object(object);
            }
            debug!("Evacuated object {:p} from block {:p} to {:p}", object,
                   block_info, new_object);
            valgrind_freelike!(object);
            return Some(new_object);
        }
        debug!("Can't evacuation object {:p} from block {:p}", object, block_info);
        return None;
    }
}

impl ImmixSpace {
    /// Get the block for the given object.
    unsafe fn get_block_ptr(object: GCObjectRef) -> *mut BlockInfo {
        let block_offset = object as usize % BLOCK_SIZE;
        let block = mem::transmute((object as *mut u8).offset(-(block_offset as isize)));
        debug!("Block for object {:p}: {:p} with offset: {}", object, block, block_offset);
        return block;
    }
}
<|endoftext|>


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

pub mod Text {
    use std;

    pub type Reader<'a> = &'a str;

    // len does not include the required null terminator at the end
    pub fn new_reader<'a>(p : *u8, len : uint) -> Reader<'a> {
        unsafe {
            let v = std::unstable::raw::Slice { data: p, len: len };
            assert!(std::str::is_utf8(std::cast::transmute(v)));
            std::cast::transmute(v)
        }
    }

    pub struct Builder<'a> {
        priv ptr : *mut u8,
        priv len : uint,
    }

    impl <'a> Builder <'a> {

        pub fn new<'b>(p : *mut u8, len : uint) -> Builder<'b> {
            Builder { ptr : p, len : len}
        }

        pub fn as_mut_bytes(&self) -> &'a mut [u8] {
             unsafe { std::cast::transmute(std::unstable::raw::Slice { data:self.ptr as *u8, len: self.len }) }
        }

        pub fn as_ptr(&self) -> *mut u8 {
            self.ptr
        }
    }

}

pub mod Data {
    use std;

    pub type Reader<'a> = &'a [u8];

    pub fn new_reader<'a>(p : *u8, len : uint) -> Reader<'a> {
        unsafe {
            let v = std::unstable::raw::Slice { data: p, len: len };
            std::cast::transmute(v)
        }
    }

    pub type Builder<'a> = &'a mut [u8];

    pub fn new_builder<'a>(p : *mut u8, len : uint) -> Builder<'a> {
        unsafe {
            let v = std::unstable::raw::Slice { data: p as *u8, len: len };
            std::cast::transmute(v)
        }
    }

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

pub mod Text {
    use std;

    pub type Reader<'a> = &'a str;

    // len does not include the required null terminator at the end
    pub fn new_reader<'a>(p : *u8, len : uint) -> Reader<'a> {
        let v : &'a [u8] =
            unsafe { std::cast::transmute(std::unstable::raw::Slice { data: p, len: len }) };
        std::str::from_utf8(v)
    }

    pub struct Builder<'a> {
        priv ptr : *mut u8,
        priv len : uint,
    }

    impl <'a> Builder <'a> {

        pub fn new<'b>(p : *mut u8, len : uint) -> Builder<'b> {
            Builder { ptr : p, len : len}
        }

        pub fn as_mut_bytes(&self) -> &'a mut [u8] {
             unsafe { std::cast::transmute(std::unstable::raw::Slice { data:self.ptr as *u8, len: self.len }) }
        }

        pub fn as_ptr(&self) -> *mut u8 {
            self.ptr
        }
    }

}

pub mod Data {
    use std;

    pub type Reader<'a> = &'a [u8];

    pub fn new_reader<'a>(p : *u8, len : uint) -> Reader<'a> {
        unsafe {
            let v = std::unstable::raw::Slice { data: p, len: len };
            std::cast::transmute(v)
        }
    }

    pub type Builder<'a> = &'a mut [u8];

    pub fn new_builder<'a>(p : *mut u8, len : uint) -> Builder<'a> {
        unsafe {
            let v = std::unstable::raw::Slice { data: p as *u8, len: len };
            std::cast::transmute(v)
        }
    }

}
<|endoftext|>