<commit_before>/// Kafka Consumer
///

use error::Result;
use utils::TopicMessage;
use client::KafkaClient;

#[derive(Default, Debug)]
pub struct Consumer {
    client: KafkaClient,
    topic: String,
    partition: i32,
    offset: i64,
    initialized: bool,
    messages: Vec<TopicMessage>,
    index: usize
}

impl Consumer {
    pub fn new(client: KafkaClient, topic: String, partition: i32, offset: i64) -> Consumer {
        Consumer{
            client: client,
            topic: topic,
            partition: partition,
            offset: offset,
            initialized: false,
            messages: vec!(),
            index: 0
        }
    }

    fn make_request(&mut self) -> Result<()>{
        self.messages = try!(self.client.fetch_messages(self.topic.clone(), self.partition, self.offset));
        self.initialized = true;
        self.index = 0;
        Ok(())
    }
}

impl Iterator for Consumer {
    type Item = TopicMessage;

    fn next(&mut self) -> Option<TopicMessage> {
        if self.initialized {
            self.index += 1;
            if self.index <= self.messages.len() {
                if self.messages[self.index-1].error.is_none() {
                    self.offset = self.messages[self.index-1].offset+1;
                    return Some(self.messages[self.index-1].clone());
                }
                return None;
            }
            if self.messages.len() == 0 {
                return None;
            }
        }
        match self.make_request() {
            Err(_) => None,
            Ok(_) => self.next()
        }
    }
}
<commit_msg>Consumer with offset management<commit_after>/// Kafka Consumer
///

use std::collections::HashMap;
use error::Result;
use utils::{TopicMessage, TopicPartitionOffset};
use client::KafkaClient;

const COMMIT_INTERVAL: i32 = 100; // Commit after every 100 message

#[derive(Default, Debug)]
pub struct Consumer {
    client: KafkaClient,
    group: String,
    topic: String,
    partitions: Vec<i32>,
    initialized: bool,
    messages: Vec<TopicMessage>,
    index: usize,
    offsets: HashMap<i32, i64>,
    consumed: i32
}

impl Consumer {
    pub fn new(client: KafkaClient) -> Consumer {
        Consumer{
            client: client,
            initialized: false,
            index: 0,
            ..Consumer::default()
        }
    }

    /// Set the group of this consumer.
    pub fn group<'a>(&'a mut self, group: String) -> &'a mut Consumer {
        self.group = group;
        self
    }

    /// Set the topic of this consumer.
    pub fn topic<'a>(&'a mut self, topic: String) -> &'a mut Consumer {
        self.topic = topic;
        self
    }

    /// Set the partitions of this consumer.
    pub fn partition<'a>(&'a mut self, partition: i32) -> &'a mut Consumer {
        self.partitions.push(partition);
        self
    }

    fn commit_offsets(&mut self) -> Result<()> {
        let tpos = self.offsets.iter()
                        .map(|(p, o)| TopicPartitionOffset{
                                topic: self.topic.clone(),
                                partition: p.clone(),
                                offset: o.clone()
                            })
                        .collect();
        self.client.commit_offsets(self.group.clone(), tpos)
    }

    fn fetch_offsets(&mut self) -> Result<()> {
        let tpos = try!(self.client.fetch_group_topic_offset(self.group.clone(), self.topic.clone()));
        if self.partitions.len() == 0 {
            self.partitions = self.client.topic_partitions.get(&self.topic).unwrap_or(&vec!()).clone();
        }
        for tpo in tpos {
            if self.partitions.contains(&tpo.partition) {
                self.offsets.insert(tpo.partition, tpo.offset);
            }
        }
        Ok(())
    }

    fn make_request(&mut self) -> Result<()>{
        if ! self.initialized {
            try!(self.fetch_offsets());
        }
        let tpos = self.offsets.iter()
                        .map(|(p, o)| TopicPartitionOffset{
                                topic: self.topic.clone(),
                                partition: p.clone(),
                                offset: o.clone()
                            })
                        .collect();
        self.messages = try!(self.client.fetch_messages_multi(tpos));
        self.initialized = true;
        self.index = 0;
        Ok(())
    }
}

impl Iterator for Consumer {
    type Item = TopicMessage;

    fn next(&mut self) -> Option<TopicMessage> {
        if self.initialized {
            self.index += 1;
            self.consumed += 1;
            if self.consumed % COMMIT_INTERVAL == 0 {
                let _ = self.commit_offsets();
            }
            if self.index <= self.messages.len() {
                if self.messages[self.index-1].error.is_none() {
                    let curr = self.offsets.entry(self.messages[self.index-1].partition).or_insert(0);
                    *curr = *curr+1;
                    return Some(self.messages[self.index-1].clone());
                }
                return None;
            }
            let _ = self.commit_offsets();
            if self.messages.len() == 0 {
                return None;
            }
        }
        match self.make_request() {
            Err(_) => None,
            Ok(_) => self.next()
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use serde::de::Visitor;
use serde::{self, Deserialize};

use super::CellErrorType;

/// An enum to represent all different data types that can appear as
/// a value in a worksheet cell
#[derive(Debug, Clone, PartialEq)]
pub enum DataType {
    /// Unsigned integer
    Int(i64),
    /// Float
    Float(f64),
    /// String
    String(String),
    /// Boolean
    Bool(bool),
    /// Error
    Error(CellErrorType),
    /// Empty cell
    Empty,
}

impl Default for DataType {
    fn default() -> DataType {
        DataType::Empty
    }
}

impl fmt::Display for DataType {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            DataType::Int(ref e) => write!(f, "{}", e),
            DataType::Float(ref e) => write!(f, "{}", e),
            DataType::String(ref e) => write!(f, "{}", e),
            DataType::Bool(ref e) => write!(f, "{}", e),
            DataType::Error(ref e) => write!(f, "{}", e),
            DataType::Empty => Ok(()),
        }
    }
}

impl<'de> Deserialize<'de> for DataType {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<DataType, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        struct DataTypeVisitor;

        impl<'de> Visitor<'de> for DataTypeVisitor {
            type Value = DataType;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("any valid JSON value")
            }

            #[inline]
            fn visit_bool<E>(self, value: bool) -> Result<DataType, E> {
                Ok(DataType::Bool(value))
            }

            #[inline]
            fn visit_i64<E>(self, value: i64) -> Result<DataType, E> {
                Ok(DataType::Int(value))
            }

            #[inline]
            fn visit_u64<E>(self, value: u64) -> Result<DataType, E> {
                Ok(DataType::Int(value as i64))
            }

            #[inline]
            fn visit_f64<E>(self, value: f64) -> Result<DataType, E> {
                Ok(DataType::Float(value))
            }

            #[inline]
            fn visit_str<E>(self, value: &str) -> Result<DataType, E>
            where
                E: serde::de::Error,
            {
                self.visit_string(String::from(value))
            }

            #[inline]
            fn visit_string<E>(self, value: String) -> Result<DataType, E> {
                Ok(DataType::String(value))
            }

            #[inline]
            fn visit_none<E>(self) -> Result<DataType, E> {
                Ok(DataType::Empty)
            }

            #[inline]
            fn visit_some<D>(self, deserializer: D) -> Result<DataType, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                Deserialize::deserialize(deserializer)
            }

            #[inline]
            fn visit_unit<E>(self) -> Result<DataType, E> {
                Ok(DataType::Empty)
            }
        }

        deserializer.deserialize_any(DataTypeVisitor)
    }
}

macro_rules! define_from {
    ($variant:path, $ty:ty) => {
        impl From<$ty> for DataType {
            fn from(v: $ty) -> Self {
                $variant(v)
            }
        }
    };
}

define_from!(DataType::Int, i64);
define_from!(DataType::Float, f64);
define_from!(DataType::String, String);
define_from!(DataType::Bool, bool);
define_from!(DataType::Error, CellErrorType);

impl<'a> From<&'a str> for DataType {
    fn from(v: &'a str) -> Self {
        DataType::String(String::from(v))
    }
}

impl From<()> for DataType {
    fn from(_: ()) -> Self {
        DataType::Empty
    }
}

impl<T> From<Option<T>> for DataType
where
    DataType: From<T>,
{
    fn from(v: Option<T>) -> Self {
        match v {
            Some(v) => From::from(v),
            None => DataType::Empty,
        }
    }
}
<commit_msg>add PartialEq for datatypes<commit_after>use std::fmt;

use serde::de::Visitor;
use serde::{self, Deserialize};

use super::CellErrorType;

/// An enum to represent all different data types that can appear as
/// a value in a worksheet cell
#[derive(Debug, Clone, PartialEq)]
pub enum DataType {
    /// Unsigned integer
    Int(i64),
    /// Float
    Float(f64),
    /// String
    String(String),
    /// Boolean
    Bool(bool),
    /// Error
    Error(CellErrorType),
    /// Empty cell
    Empty,
}

impl Default for DataType {
    fn default() -> DataType {
        DataType::Empty
    }
}

impl DataType {
    /// Assess if `self == DataType::Empty`
    pub fn is_empty(&self) -> bool {
        *self == DataType::Empty
    }
}

impl PartialEq<str> for DataType {
    fn eq(&self, other: &str) -> bool {
        match *self {
            DataType::String(ref s) if s == other => true,
            _ => false,
        }
    }
}

impl PartialEq<f64> for DataType {
    fn eq(&self, other: &f64) -> bool {
        match *self {
            DataType::Float(ref s) if *s == *other => true,
            _ => false,
        }
    }
}

impl PartialEq<bool> for DataType {
    fn eq(&self, other: &bool) -> bool {
        match *self {
            DataType::Bool(ref s) if *s == *other => true,
            _ => false,
        }
    }
}

impl PartialEq<i64> for DataType {
    fn eq(&self, other: &i64) -> bool {
        match *self {
            DataType::Int(ref s) if *s == *other => true,
            _ => false,
        }
    }
}

impl fmt::Display for DataType {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            DataType::Int(ref e) => write!(f, "{}", e),
            DataType::Float(ref e) => write!(f, "{}", e),
            DataType::String(ref e) => write!(f, "{}", e),
            DataType::Bool(ref e) => write!(f, "{}", e),
            DataType::Error(ref e) => write!(f, "{}", e),
            DataType::Empty => Ok(()),
        }
    }
}

impl<'de> Deserialize<'de> for DataType {
    #[inline]
    fn deserialize<D>(deserializer: D) -> Result<DataType, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        struct DataTypeVisitor;

        impl<'de> Visitor<'de> for DataTypeVisitor {
            type Value = DataType;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("any valid JSON value")
            }

            #[inline]
            fn visit_bool<E>(self, value: bool) -> Result<DataType, E> {
                Ok(DataType::Bool(value))
            }

            #[inline]
            fn visit_i64<E>(self, value: i64) -> Result<DataType, E> {
                Ok(DataType::Int(value))
            }

            #[inline]
            fn visit_u64<E>(self, value: u64) -> Result<DataType, E> {
                Ok(DataType::Int(value as i64))
            }

            #[inline]
            fn visit_f64<E>(self, value: f64) -> Result<DataType, E> {
                Ok(DataType::Float(value))
            }

            #[inline]
            fn visit_str<E>(self, value: &str) -> Result<DataType, E>
            where
                E: serde::de::Error,
            {
                self.visit_string(String::from(value))
            }

            #[inline]
            fn visit_string<E>(self, value: String) -> Result<DataType, E> {
                Ok(DataType::String(value))
            }

            #[inline]
            fn visit_none<E>(self) -> Result<DataType, E> {
                Ok(DataType::Empty)
            }

            #[inline]
            fn visit_some<D>(self, deserializer: D) -> Result<DataType, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                Deserialize::deserialize(deserializer)
            }

            #[inline]
            fn visit_unit<E>(self) -> Result<DataType, E> {
                Ok(DataType::Empty)
            }
        }

        deserializer.deserialize_any(DataTypeVisitor)
    }
}

macro_rules! define_from {
    ($variant:path, $ty:ty) => {
        impl From<$ty> for DataType {
            fn from(v: $ty) -> Self {
                $variant(v)
            }
        }
    };
}

define_from!(DataType::Int, i64);
define_from!(DataType::Float, f64);
define_from!(DataType::String, String);
define_from!(DataType::Bool, bool);
define_from!(DataType::Error, CellErrorType);

impl<'a> From<&'a str> for DataType {
    fn from(v: &'a str) -> Self {
        DataType::String(String::from(v))
    }
}

impl From<()> for DataType {
    fn from(_: ()) -> Self {
        DataType::Empty
    }
}

impl<T> From<Option<T>> for DataType
where
    DataType: From<T>,
{
    fn from(v: Option<T>) -> Self {
        match v {
            Some(v) => From::from(v),
            None => DataType::Empty,
        }
    }
}
<|endoftext|>


<commit_before>use std::path::Path;

use error::PackageError;

/// Enum for representing the state of the package downloads.
pub enum PackageDownload<'a> {
    /// The state is switched to IsFinished when the download of the
    /// package is finished.
    IsFinished {
        /// The path where the downloaded package is located at.
        location: &'a Path,
        /// The total file size of the package.
        file_size: u32,
    },

    /// The state is switched to InProgress when the download of the
    /// package is started.
    InProgress {
        /// The path where the half-downloaded package is located at.
        location: &'a Path,
        /// The progress of the current download process.
        progress: u32,
        /// The total file size of the package.
        file_size: u32,
    },

    /// This is the initial state of PackageDownload, where the package is yet
    /// to be downloaded.
    NotStarted {
        /// The path where the package is going to be located at.
        location: &'a Path,
        /// The URL of where the package is going to be downloaded from.
        url: &'a str,
    }
}

impl<'a> PackageDownload<'a> {
    /// Create a new PackageDownload.
    fn new(url: &'a str, location: &'a Path) -> Self {
        PackageDownload::NotStarted { location, url }
    }

    /// A bool to determine whether the package is downloaded.
    fn is_downloaded(&self) -> bool {
        match self {
            &PackageDownload::IsFinished { .. } => true,
            _ => false
        }
    }

    /// Returns the path of where the package is (or is going to be) located
    /// at.
    fn store_path(&self) -> &'a Path {
        match self {
            &PackageDownload::IsFinished { location: path, .. } => path,
            &PackageDownload::InProgress { location: path, .. } => path,
            &PackageDownload::NotStarted { location: path, .. } => path,
        }
    }
}<commit_msg>Implementing the download function<commit_after>use reqwest::{ self, header };
use std::fs::File;
use std::io::{ BufWriter, Read, Write };
use std::path::Path;

use error::PackageError;

/// Enum for representing the state of the package downloads.
pub enum PackageDownload<'a> {
    /// The state is switched to IsFinished when the download of the
    /// package is finished.
    IsFinished {
        /// The path where the downloaded package is located at.
        location: &'a Path,
        /// The total file size of the package.
        file_size: u32,
    },

    /// The state is switched to InProgress when the download of the
    /// package is started.
    InProgress {
        /// The path where the half-downloaded package is located at.
        location: &'a Path,
        /// The progress of the current download process.
        progress: u32,
        /// The total file size of the package.
        file_size: u32,
    },

    /// This is the initial state of PackageDownload, where the package is yet
    /// to be downloaded.
    NotStarted {
        /// The path where the package is going to be located at.
        location: &'a Path,
        /// The URL of where the package is going to be downloaded from.
        url: &'a str,
    }
}

impl<'a> PackageDownload<'a> {
    /// Create a new PackageDownload.
    fn new(url: &'a str, location: &'a Path) -> Self {
        PackageDownload::NotStarted { location, url }
    }

    /// A bool to determine whether the package is downloaded.
    fn is_downloaded(&self) -> bool {
        match self {
            &PackageDownload::IsFinished { .. } => true,
            _ => false
        }
    }

    /// Returns the path of where the package is (or is going to be) located
    /// at.
    fn store_path(&self) -> &'a Path {
        match self {
            &PackageDownload::IsFinished { location: path, .. } => path,
            &PackageDownload::InProgress { location: path, .. } => path,
            &PackageDownload::NotStarted { location: path, .. } => path,
        }
    }
}

fn download_file<F>(url: &str, to_path: &Path, callback: F) -> Result<u64, PackageError>
    where F: Fn(u64, u64)
{
    // GET the URL, returning an error if necessary.
    let response = reqwest::get(url)?;

    // Try to retrieve the content length.
    let content_length =
        response
        .headers()
        .get::<header::ContentLength>()
        // If the Response contains no content-length, default to 0.
        .map_or(0u64, |x| {
            let header::ContentLength(len) = *x;
            len
        });

    // For every `BUFFER_SIZE` bytes, call the callback once.
    const BUFFER_SIZE: u64 = 65536;

    // Obviously, the target file to be written to by the BufWriter.
    let mut target = BufWriter::new(File::create(to_path)?);

    for (index, byte) in response.bytes().enumerate() {
        // Write to the target, returns an error if necessary.
        target.write(&[byte?]);

        // Checks whether it's time to call the callback, and call it if it is.
        // Plus one to `index` as `index` itself is zero-indexed.
        if index as u64 % BUFFER_SIZE == 0 {
            callback((index + 1) as u64, content_length);
        };
    }

    // In case the callback never got a chance to be called due to the package
    // itself being too small.
    callback(content_length, content_length);

    Ok(content_length)
}<|endoftext|>


<commit_before>//! The film module provides color types and a render target that the image
//! is written too. Functions are also provided for saving PPM images
//! while I wait to migrate over to the Piston image library due to some
//! compile issues TODO: https://github.com/PistonDevelopers/image

use std::io::{File, Open, Write, BufferedWriter};

pub use self::color::Colorf;
pub use self::render_target::RenderTarget;
pub use self::camera::Camera;

pub mod color;
pub mod render_target;
pub mod camera;

/// Write the sequence of bytes as a PPM image file with the desired name
pub fn write_ppm(name: &str, w: usize, h: usize, img: &Vec<u8>) {
    let file = match File::open_mode(&Path::new(name), Open, Write) {
        Ok(f) => f,
        Err(e) => panic!("Failed to open {}: {}", name, e),
    };
    let mut writer = BufferedWriter::new(file);
    if let Err(e) = write!(&mut writer, "P6\n{} {}\n255\n", w, h) {
        panic!("Failed to write pixel data to {}: {}", name, e);
    }
    if let Err(e) = writer.write(&img[]) {
        panic!("Failed to write pixel data to {}: {}", name, e);
    }
}
/// Write the sequence of bytes as a 24bpp BMP image
pub fn write_bmp(name: &str, w: u32, h: u32, img: &Vec<u8>) {
    let file = match File::open_mode(&Path::new(name), Open, Write) {
        Ok(f) => f,
        Err(e) => panic!("Failed to open {}: {}", name, e),
    };
    let mut writer = BufferedWriter::new(file);
    // Write BMP header
    if let Err(e) = write!(&mut writer, "BM") {
        panic!("Failed to write image {}: {}", name, e);
    }
    let padding = (w * 3) % 4;
    let img_size = h * (3 * w + padding);
    // We're just using the BMPINFOHEADER so our total header size is 54, 14 byte
    // file header + 40 byte BMPINFOHEADER
    let file_size = 54 + img_size;
    if let Err(e) = writer.write_le_u32(file_size) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // 4 bytes we don't care about, just put some random num
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // We're just using the BMPINFOHEADER so the offset to pixel data is always 54
    if let Err(e) = writer.write_le_u32(54) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Same reason as above the BMPINFOHEADER is 40 bytes
    if let Err(e) = writer.write_le_u32(40) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_i32(w as i32) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_i32(h as i32) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Color planes is unused, just set to 1
    if let Err(e) = writer.write_le_u16(1) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Always writing 24bpp BMPs
    if let Err(e) = writer.write_le_u16(24) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Uncompressed BMPs
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_u32(img_size) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Resolution just seems to be ignored? set to 2835 like Wikipedia
    if let Err(e) = writer.write_le_i32(2835) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_i32(2835) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // No color palette or important colors
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Finally we can write the image, since BMP is upside-down we need
    // to flip the rows though. We also handle padding of rows here
    for r in (0..h) {
        let begin = 3 * w * (h - r - 1);
        let end = begin + 3 * w;
        if let Err(e) = writer.write(&img[begin as usize..end as usize]) {
            panic!("Failed to write image {}: {}", name, e);
        }
        // Write any required padding, it's just padding so just throw some junk there
        if padding > 0 {
            if let Err(e) = writer.write(&img[0..padding as usize]) {
                panic!("Failed to write image {}: {}", name, e);
            }
        }
    }
}

<commit_msg>Clearer doc on how to use the BMP output<commit_after>//! The film module provides color types and a render target that the image
//! is written too. Functions are also provided for saving PPM and BMP images

use std::io::{File, Open, Write, BufferedWriter};

pub use self::color::Colorf;
pub use self::render_target::RenderTarget;
pub use self::camera::Camera;

pub mod color;
pub mod render_target;
pub mod camera;

/// Write the sequence of bytes as a PPM image file with the desired name
pub fn write_ppm(name: &str, w: usize, h: usize, img: &Vec<u8>) {
    let file = match File::open_mode(&Path::new(name), Open, Write) {
        Ok(f) => f,
        Err(e) => panic!("Failed to open {}: {}", name, e),
    };
    let mut writer = BufferedWriter::new(file);
    if let Err(e) = write!(&mut writer, "P6\n{} {}\n255\n", w, h) {
        panic!("Failed to write pixel data to {}: {}", name, e);
    }
    if let Err(e) = writer.write(&img[]) {
        panic!("Failed to write pixel data to {}: {}", name, e);
    }
}
/// Write the sequence of bytes as a 24bpp BMP image
/// Note that the bytes should be in BGR order and have previously
/// been flipped to the correct y-order for BMP output
pub fn write_bmp(name: &str, w: u32, h: u32, img: &Vec<u8>) {
    let file = match File::open_mode(&Path::new(name), Open, Write) {
        Ok(f) => f,
        Err(e) => panic!("Failed to open {}: {}", name, e),
    };
    let mut writer = BufferedWriter::new(file);
    // Write BMP header
    if let Err(e) = write!(&mut writer, "BM") {
        panic!("Failed to write image {}: {}", name, e);
    }
    let padding = (w * 3) % 4;
    let img_size = h * (3 * w + padding);
    // We're just using the BMPINFOHEADER so our total header size is 54, 14 byte
    // file header + 40 byte BMPINFOHEADER
    let file_size = 54 + img_size;
    if let Err(e) = writer.write_le_u32(file_size) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // 4 bytes we don't care about, just put some random num
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // We're just using the BMPINFOHEADER so the offset to pixel data is always 54
    if let Err(e) = writer.write_le_u32(54) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Same reason as above the BMPINFOHEADER is 40 bytes
    if let Err(e) = writer.write_le_u32(40) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_i32(w as i32) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_i32(h as i32) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Color planes is unused, just set to 1
    if let Err(e) = writer.write_le_u16(1) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Always writing 24bpp BMPs
    if let Err(e) = writer.write_le_u16(24) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Uncompressed BMPs
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_u32(img_size) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Resolution just seems to be ignored? set to 2835 like Wikipedia
    if let Err(e) = writer.write_le_i32(2835) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_i32(2835) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // No color palette or important colors
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    if let Err(e) = writer.write_le_u32(0) {
        panic!("Failed to write image {}: {}", name, e);
    }
    // Finally we can write the image, since BMP is upside-down we need
    // to flip the rows though. We also handle padding of rows here
    for r in (0..h) {
        let begin = 3 * w * (h - r - 1);
        let end = begin + 3 * w;
        if let Err(e) = writer.write(&img[begin as usize..end as usize]) {
            panic!("Failed to write image {}: {}", name, e);
        }
        // Write any required padding, it's just padding so just throw some junk there
        if padding > 0 {
            if let Err(e) = writer.write(&img[0..padding as usize]) {
                panic!("Failed to write image {}: {}", name, e);
            }
        }
    }
}

<|endoftext|>


<commit_before>//! # generator
//!
//! Rust generator implementation
//!

use std::fmt;
use std::mem;
use std::panic;
use std::thread;
use std::any::Any;
use std::boxed::FnBox;
use std::marker::PhantomData;
use std::intrinsics::type_name;

use scope::Scope;
use yield_::yield_now;
use rt::{Error, Context, ContextStack};
use reg_context::Context as RegContext;

// default stack size, in usize
// windows has a minimal size as 0x4a8!!!!
pub const DEFAULT_STACK_SIZE: usize = 0x800;

/// Generator helper
pub struct Gn<A> {
    dummy: PhantomData<A>,
}

/// the generator type
pub type Generator<'a, A, T> = Box<GeneratorImpl<'a, A, T>>;

impl<A> Gn<A> {
    /// create a scoped generator
    pub fn new_scoped<'a, T, F>(f: F) -> Box<GeneratorImpl<'a, A, T>>
        where F: FnOnce(Scope<A, T>) -> T + 'a,
              T: 'a,
              A: 'a
    {
        let mut g = GeneratorImpl::<A, T>::new(DEFAULT_STACK_SIZE);
        let scope = g.get_scope();
        g.init(move || f(scope));
        g
    }
}

impl<A: Any> Gn<A> {
    /// create a new generator with default stack size
    pub fn new<'a, T: Any, F>(f: F) -> Box<GeneratorImpl<'a, A, T>>
        where F: FnOnce() -> T + 'a
    {
        Self::new_opt(DEFAULT_STACK_SIZE, f)
    }

    /// create a new generator with specified stack size
    pub fn new_opt<'a, T: Any, F>(size: usize, f: F) -> Box<GeneratorImpl<'a, A, T>>
        where F: FnOnce() -> T + 'a
    {
        let mut g = GeneratorImpl::<A, T>::new(size);
        g.init_context();
        g.init(f);
        g
    }
}

/// `GeneratorImpl`
pub struct GeneratorImpl<'a, A, T> {
    // run time context
    context: Context,
    // save the input
    para: Option<A>,
    // save the output
    ret: Option<T>,
    // boxed functor
    f: Option<Box<FnBox() + 'a>>,
}

impl<'a, A: Any, T: Any> GeneratorImpl<'a, A, T> {
    /// create a new generator with default stack size
    pub fn init_context(&mut self) {
        self.context.para = &mut self.para as &mut Any;
        self.context.ret = &mut self.ret as &mut Any;
    }
}

impl<'a, A, T> GeneratorImpl<'a, A, T> {
    /// create a new generator with specified stack size
    pub fn new(size: usize) -> Box<Self> {
        Box::new(GeneratorImpl {
            para: None,
            ret: None,
            f: None,
            context: Context::new(size),
        })
    }

    /// get the scope object
    pub fn get_scope(&mut self) -> Scope<A, T> {
        Scope::new(&mut self.para, &mut self.ret)
    }

    /// init a heap based generator
    // it's can be used to re-init a 'done' generator before it's get dropped
    pub fn init<F: FnOnce() -> T + 'a>(&mut self, f: F)
        where T: 'a
    {
        // make sure the last one is finished
        if self.f.is_none() && self.context._ref == 0 {
            self.cancel();
        }

        // init the ref to 0 means that it's ready to start
        self.context._ref = 0;
        let ret = &mut self.ret as *mut _;
        // windows box::new is quite slow than unix
        self.f = Some(Box::new(move || unsafe { *ret = Some(f()) }));

        let stk = &self.context.stack;
        let reg = &mut self.context.regs;
        reg.init_with(gen_init, 0, &mut self.f as *mut _ as *mut usize, stk);
    }

    /// resume the generator
    #[inline]
    fn resume_gen(&mut self) {
        let env = ContextStack::current();
        // get the current regs
        let cur = &mut env.top().regs;
        // save current generator context on stack
        env.push_context(&mut self.context);
        // switch to new context
        RegContext::swap(cur, &mut self.context.regs);

        // check the panic status
        // this would propagate the panic until root context
        let err = self.context.err;
        if err.is_some() {
            panic!(err.unwrap());
        }
    }

    #[inline]
    fn is_started(&self) -> bool {
        // when the f is consumed we think it's running
        self.f.is_none()
    }

    /// prepare the para that passed into generator before send
    #[inline]
    pub fn set_para(&mut self, para: A) {
        mem::replace(&mut self.para, Some(para));
    }

    /// set the generator local data
    #[inline]
    pub fn set_local_data(&mut self, data: *mut u8) {
        self.context.local_data = data;
    }

    /// get the generator local data
    #[inline]
    pub fn get_local_data(&self) -> *mut u8 {
        self.context.local_data
    }

    /// resume the generator without touch the para
    /// you should call `set_para` before this method
    #[inline]
    pub fn resume(&mut self) -> Option<T> {
        if self.is_done() {
            return None;
        }

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        self.ret.take()
    }

    /// `raw_send`
    #[inline]
    pub fn raw_send(&mut self, para: Option<A>) -> Option<T> {
        if self.is_done() {
            return None;
        }

        // this is the passed in value of the send primitive
        // the yield part would read out this value in the next round
        // use the replace is would drop the old value
        mem::replace(&mut self.para, para);

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        self.ret.take()
    }

    /// send interface
    pub fn send(&mut self, para: A) -> T {
        let ret = self.raw_send(Some(para));
        ret.unwrap()
    }

    /// cancel the generator
    pub fn cancel(&mut self) {
        // consume the fun if it's not started
        if !self.is_started() {
            self.f.take();
            self.context._ref = 1;
        } else {
            // tell the func to panic
            // so that we can stop the inner func
            self.context._ref = 2;
            self.resume_gen();
        }
    }

    /// is finished
    #[inline]
    pub fn is_done(&self) -> bool {
        self.is_started() && self.context._ref != 0
    }

    /// get stack total size and used size in word
    pub fn stack_usage(&self) -> (usize, usize) {
        (self.context.stack.size(), self.context.stack.get_used_size())
    }
}

impl<'a, A, T> Drop for GeneratorImpl<'a, A, T> {
    fn drop(&mut self) {
        // when the thread is already panic, do nothing
        if thread::panicking() {
            return;
        }

        let mut i = 0;
        while !self.is_done() {
            if i > 2 {
                self.cancel();
                break;
            }
            self.raw_send(None);
            i += 1;
        }

        let (total_stack, used_stack) = self.stack_usage();
        if used_stack < total_stack {
            // here we should record the stack in the class
            // next time will just use
            // set_stack_size::<F>(used_stack);
        } else {
            error!("stack overflow detected!");
            panic!(Error::StackErr);
        }
    }
}

impl<'a, A, T> Iterator for GeneratorImpl<'a, A, T> {
    type Item = T;
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<T> {
        self.resume()
    }
}

impl<'a, A, T> fmt::Debug for GeneratorImpl<'a, A, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            write!(f,
                   "Generator<{}, Output={}> {{ ... }}",
                   type_name::<A>(),
                   type_name::<T>())
        }
    }
}

/// the init function passed to reg_context
fn gen_init(_: usize, f: *mut usize) -> ! {
    let clo = move || {
        // consume self.f
        let f: &mut Option<Box<FnBox()>> = unsafe { &mut *(f as *mut _) };
        let func = f.take().unwrap();
        func();
    };

    // we can't panic inside the generator context
    // need to propagate the panic to the main thread
    // It is currently undefined behavior to unwind from Rust code into foreign code
    // TODO: pass the Err to the main thread
    if let Err(cause) = panic::catch_unwind(clo) {
        if cause.downcast_ref::<Error>().is_some() {
            match cause.downcast_ref::<Error>().unwrap() {
                &Error::Cancel => {}
                err => {
                    let ctx = ContextStack::current().top();
                    ctx.err = Some(*err);
                }
            }
        } else {
            // we hope all other panic could covert to a string
            // here we forget the panic to avoid shutdown the whole thread
            let e = cause.downcast::<&str>().unwrap_or_else(|_| Box::new("unkown panic"));
            error!("Panicked inside: {:?}", e);
        }
    }

    yield_now();

    unreachable!("Should never comeback");
}
<commit_msg>impl Send for static generator<commit_after>//! # generator
//!
//! Rust generator implementation
//!

use std::fmt;
use std::mem;
use std::panic;
use std::thread;
use std::any::Any;
use std::boxed::FnBox;
use std::marker::PhantomData;
use std::intrinsics::type_name;

use scope::Scope;
use yield_::yield_now;
use rt::{Error, Context, ContextStack};
use reg_context::Context as RegContext;

// default stack size, in usize
// windows has a minimal size as 0x4a8!!!!
pub const DEFAULT_STACK_SIZE: usize = 0x800;

/// Generator helper
pub struct Gn<A> {
    dummy: PhantomData<A>,
}

/// the generator type
pub type Generator<'a, A, T> = Box<GeneratorImpl<'a, A, T>>;
unsafe impl<A, T> Send for GeneratorImpl<'static, A, T> {}

impl<A> Gn<A> {
    /// create a scoped generator
    pub fn new_scoped<'a, T, F>(f: F) -> Box<GeneratorImpl<'a, A, T>>
        where F: FnOnce(Scope<A, T>) -> T + 'a,
              T: 'a,
              A: 'a
    {
        let mut g = GeneratorImpl::<A, T>::new(DEFAULT_STACK_SIZE);
        let scope = g.get_scope();
        g.init(move || f(scope));
        g
    }
}

impl<A: Any> Gn<A> {
    /// create a new generator with default stack size
    pub fn new<'a, T: Any, F>(f: F) -> Box<GeneratorImpl<'a, A, T>>
        where F: FnOnce() -> T + 'a
    {
        Self::new_opt(DEFAULT_STACK_SIZE, f)
    }

    /// create a new generator with specified stack size
    pub fn new_opt<'a, T: Any, F>(size: usize, f: F) -> Box<GeneratorImpl<'a, A, T>>
        where F: FnOnce() -> T + 'a
    {
        let mut g = GeneratorImpl::<A, T>::new(size);
        g.init_context();
        g.init(f);
        g
    }
}

/// `GeneratorImpl`
pub struct GeneratorImpl<'a, A, T> {
    // run time context
    context: Context,
    // save the input
    para: Option<A>,
    // save the output
    ret: Option<T>,
    // boxed functor
    f: Option<Box<FnBox() + 'a>>,
}

impl<'a, A: Any, T: Any> GeneratorImpl<'a, A, T> {
    /// create a new generator with default stack size
    pub fn init_context(&mut self) {
        self.context.para = &mut self.para as &mut Any;
        self.context.ret = &mut self.ret as &mut Any;
    }
}

impl<'a, A, T> GeneratorImpl<'a, A, T> {
    /// create a new generator with specified stack size
    pub fn new(size: usize) -> Box<Self> {
        Box::new(GeneratorImpl {
            para: None,
            ret: None,
            f: None,
            context: Context::new(size),
        })
    }

    /// get the scope object
    pub fn get_scope(&mut self) -> Scope<A, T> {
        Scope::new(&mut self.para, &mut self.ret)
    }

    /// init a heap based generator
    // it's can be used to re-init a 'done' generator before it's get dropped
    pub fn init<F: FnOnce() -> T + 'a>(&mut self, f: F)
        where T: 'a
    {
        // make sure the last one is finished
        if self.f.is_none() && self.context._ref == 0 {
            self.cancel();
        }

        // init the ref to 0 means that it's ready to start
        self.context._ref = 0;
        let ret = &mut self.ret as *mut _;
        // windows box::new is quite slow than unix
        self.f = Some(Box::new(move || unsafe { *ret = Some(f()) }));

        let stk = &self.context.stack;
        let reg = &mut self.context.regs;
        reg.init_with(gen_init, 0, &mut self.f as *mut _ as *mut usize, stk);
    }

    /// resume the generator
    #[inline]
    fn resume_gen(&mut self) {
        let env = ContextStack::current();
        // get the current regs
        let cur = &mut env.top().regs;
        // save current generator context on stack
        env.push_context(&mut self.context);
        // switch to new context
        RegContext::swap(cur, &mut self.context.regs);

        // check the panic status
        // this would propagate the panic until root context
        let err = self.context.err;
        if err.is_some() {
            panic!(err.unwrap());
        }
    }

    #[inline]
    fn is_started(&self) -> bool {
        // when the f is consumed we think it's running
        self.f.is_none()
    }

    /// prepare the para that passed into generator before send
    #[inline]
    pub fn set_para(&mut self, para: A) {
        mem::replace(&mut self.para, Some(para));
    }

    /// set the generator local data
    #[inline]
    pub fn set_local_data(&mut self, data: *mut u8) {
        self.context.local_data = data;
    }

    /// get the generator local data
    #[inline]
    pub fn get_local_data(&self) -> *mut u8 {
        self.context.local_data
    }

    /// resume the generator without touch the para
    /// you should call `set_para` before this method
    #[inline]
    pub fn resume(&mut self) -> Option<T> {
        if self.is_done() {
            return None;
        }

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        self.ret.take()
    }

    /// `raw_send`
    #[inline]
    pub fn raw_send(&mut self, para: Option<A>) -> Option<T> {
        if self.is_done() {
            return None;
        }

        // this is the passed in value of the send primitive
        // the yield part would read out this value in the next round
        // use the replace is would drop the old value
        mem::replace(&mut self.para, para);

        // every time we call the function, increase the ref count
        // yiled will decrease it and return will not
        self.context._ref += 1;
        self.resume_gen();

        self.ret.take()
    }

    /// send interface
    pub fn send(&mut self, para: A) -> T {
        let ret = self.raw_send(Some(para));
        ret.unwrap()
    }

    /// cancel the generator
    pub fn cancel(&mut self) {
        // consume the fun if it's not started
        if !self.is_started() {
            self.f.take();
            self.context._ref = 1;
        } else {
            // tell the func to panic
            // so that we can stop the inner func
            self.context._ref = 2;
            self.resume_gen();
        }
    }

    /// is finished
    #[inline]
    pub fn is_done(&self) -> bool {
        self.is_started() && self.context._ref != 0
    }

    /// get stack total size and used size in word
    pub fn stack_usage(&self) -> (usize, usize) {
        (self.context.stack.size(), self.context.stack.get_used_size())
    }
}

impl<'a, A, T> Drop for GeneratorImpl<'a, A, T> {
    fn drop(&mut self) {
        // when the thread is already panic, do nothing
        if thread::panicking() {
            return;
        }

        let mut i = 0;
        while !self.is_done() {
            if i > 2 {
                self.cancel();
                break;
            }
            self.raw_send(None);
            i += 1;
        }

        let (total_stack, used_stack) = self.stack_usage();
        if used_stack < total_stack {
            // here we should record the stack in the class
            // next time will just use
            // set_stack_size::<F>(used_stack);
        } else {
            error!("stack overflow detected!");
            panic!(Error::StackErr);
        }
    }
}

impl<'a, A, T> Iterator for GeneratorImpl<'a, A, T> {
    type Item = T;
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<T> {
        self.resume()
    }
}

impl<'a, A, T> fmt::Debug for GeneratorImpl<'a, A, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            write!(f,
                   "Generator<{}, Output={}> {{ ... }}",
                   type_name::<A>(),
                   type_name::<T>())
        }
    }
}

/// the init function passed to reg_context
fn gen_init(_: usize, f: *mut usize) -> ! {
    let clo = move || {
        // consume self.f
        let f: &mut Option<Box<FnBox()>> = unsafe { &mut *(f as *mut _) };
        let func = f.take().unwrap();
        func();
    };

    // we can't panic inside the generator context
    // need to propagate the panic to the main thread
    // It is currently undefined behavior to unwind from Rust code into foreign code
    // TODO: pass the Err to the main thread
    if let Err(cause) = panic::catch_unwind(clo) {
        if cause.downcast_ref::<Error>().is_some() {
            match cause.downcast_ref::<Error>().unwrap() {
                &Error::Cancel => {}
                err => {
                    let ctx = ContextStack::current().top();
                    ctx.err = Some(*err);
                }
            }
        } else {
            // we hope all other panic could covert to a string
            // here we forget the panic to avoid shutdown the whole thread
            let e = cause.downcast::<&str>().unwrap_or_else(|_| Box::new("unkown panic"));
            error!("Panicked inside: {:?}", e);
        }
    }

    yield_now();

    unreachable!("Should never comeback");
}
<|endoftext|>


<commit_before>use super::*;

/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct Generics {
    pub lifetimes: Vec<LifetimeDef>,
    pub ty_params: Vec<TyParam>,
    pub where_clause: WhereClause,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Lifetime {
    pub ident: Ident,
}

/// A lifetime definition, e.g. `'a: 'b+'c+'d`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct LifetimeDef {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TyParam {
    pub ident: Ident,
    pub bounds: Vec<TyParamBound>,
    pub default: Option<Ty>,
}

/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects Copy, Send and Sync.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TyParamBound {
    Trait(PolyTraitRef, TraitBoundModifier),
    Region(Lifetime),
}

/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TraitBoundModifier {
    None,
    Maybe,
}

/// A `where` clause in a definition
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct WhereClause {
    pub predicates: Vec<WherePredicate>,
}

/// A single predicate in a `where` clause
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WherePredicate {
    /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
    BoundPredicate(WhereBoundPredicate),
    /// A lifetime predicate, e.g. `'a: 'b+'c`
    RegionPredicate(WhereRegionPredicate),
}

/// A type bound.
///
/// E.g. `for<'c> Foo: Send+Clone+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereBoundPredicate {
    /// Any lifetimes from a `for` binding
    pub bound_lifetimes: Vec<LifetimeDef>,
    /// The type being bounded
    pub bounded_ty: Ty,
    /// Trait and lifetime bounds (`Clone+Send+'static`)
    pub bounds: Vec<TyParamBound>,
}

/// A lifetime predicate.
///
/// E.g. `'a: 'b+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereRegionPredicate {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use ident::parsing::ident;
    use ty::parsing::{ty, poly_trait_ref};

    named!(pub generics -> Generics, do_parse!(
        bracketed: alt!(
            do_parse!(
                punct!("<") >>
                lifetimes: separated_list!(punct!(","), lifetime_def) >>
                ty_params: opt_vec!(preceded!(
                    cond!(!lifetimes.is_empty(), punct!(",")),
                    separated_nonempty_list!(punct!(","), ty_param)
                )) >>
                punct!(">") >>
                (lifetimes, ty_params)
            )
            |
            epsilon!() => { |_| (Vec::new(), Vec::new()) }
        ) >>
        where_clause: where_clause >>
        (Generics {
            lifetimes: bracketed.0,
            ty_params: bracketed.1,
            where_clause: where_clause,
        })
    ));

    named!(pub lifetime -> Lifetime, preceded!(
        punct!("'"),
        map!(ident, |id| Lifetime {
            ident: format!("'{}", id).into(),
        })
    ));

    named!(pub lifetime_def -> LifetimeDef, do_parse!(
        life: lifetime >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), lifetime)
        )) >>
        (LifetimeDef {
            lifetime: life,
            bounds: bounds,
        })
    ));

    named!(pub bound_lifetimes -> Vec<LifetimeDef>, opt_vec!(do_parse!(
        keyword!("for") >>
        punct!("<") >>
        lifetimes: separated_list!(punct!(","), lifetime_def) >>
        punct!(">") >>
        (lifetimes)
    )));

    named!(ty_param -> TyParam, do_parse!(
        id: ident >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), ty_param_bound)
        )) >>
        default: option!(preceded!(
            punct!("="),
            ty
        )) >>
        (TyParam {
            ident: id,
            bounds: bounds,
            default: default,
        })
    ));

    named!(pub ty_param_bound -> TyParamBound, alt!(
        preceded!(punct!("?"), poly_trait_ref) => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe)
        }
        |
        lifetime => { TyParamBound::Region }
        |
        poly_trait_ref => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
        }
    ));

    named!(pub where_clause -> WhereClause, alt!(
        do_parse!(
            keyword!("where") >>
            predicates: separated_nonempty_list!(punct!(","), where_predicate) >>
            option!(punct!(",")) >>
            (WhereClause { predicates: predicates })
        )
        |
        epsilon!() => { |_| Default::default() }
    ));

    named!(where_predicate -> WherePredicate, alt!(
        do_parse!(
            ident: lifetime >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), lifetime) >>
            (WherePredicate::RegionPredicate(WhereRegionPredicate {
                lifetime: ident,
                bounds: bounds,
            }))
        )
        |
        do_parse!(
            bound_lifetimes: bound_lifetimes >>
            bounded_ty: ty >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
            (WherePredicate::BoundPredicate(WhereBoundPredicate {
                bound_lifetimes: bound_lifetimes,
                bounded_ty: bounded_ty,
                bounds: bounds,
            }))
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Generics {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.lifetimes.is_empty();
            let has_ty_params = !self.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                tokens.append_separated(&self.ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
        }
    }

    impl ToTokens for LifetimeDef {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for TyParam {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
            if let Some(ref default) = self.default {
                tokens.append("=");
                default.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TyParamBound {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
                TyParamBound::Trait(ref trait_ref, modifier) => {
                    match modifier {
                        TraitBoundModifier::None => {}
                        TraitBoundModifier::Maybe => tokens.append("?"),
                    }
                    trait_ref.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereClause {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.predicates.is_empty() {
                tokens.append("where");
                tokens.append_separated(&self.predicates, ",");
            }
        }
    }

    impl ToTokens for WherePredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                WherePredicate::BoundPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::RegionPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereBoundPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.bound_lifetimes.is_empty() {
                tokens.append("for");
                tokens.append("<");
                tokens.append_separated(&self.bound_lifetimes, ",");
                tokens.append(">");
            }
            self.bounded_ty.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereRegionPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }
}
<commit_msg>Add Lifetime::new<commit_after>use super::*;

/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct Generics {
    pub lifetimes: Vec<LifetimeDef>,
    pub ty_params: Vec<TyParam>,
    pub where_clause: WhereClause,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Lifetime {
    pub ident: Ident,
}

impl Lifetime {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        Lifetime {
            ident: Ident::new(t),
        }
    }
}

/// A lifetime definition, e.g. `'a: 'b+'c+'d`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct LifetimeDef {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TyParam {
    pub ident: Ident,
    pub bounds: Vec<TyParamBound>,
    pub default: Option<Ty>,
}

/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects Copy, Send and Sync.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TyParamBound {
    Trait(PolyTraitRef, TraitBoundModifier),
    Region(Lifetime),
}

/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TraitBoundModifier {
    None,
    Maybe,
}

/// A `where` clause in a definition
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct WhereClause {
    pub predicates: Vec<WherePredicate>,
}

/// A single predicate in a `where` clause
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WherePredicate {
    /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
    BoundPredicate(WhereBoundPredicate),
    /// A lifetime predicate, e.g. `'a: 'b+'c`
    RegionPredicate(WhereRegionPredicate),
}

/// A type bound.
///
/// E.g. `for<'c> Foo: Send+Clone+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereBoundPredicate {
    /// Any lifetimes from a `for` binding
    pub bound_lifetimes: Vec<LifetimeDef>,
    /// The type being bounded
    pub bounded_ty: Ty,
    /// Trait and lifetime bounds (`Clone+Send+'static`)
    pub bounds: Vec<TyParamBound>,
}

/// A lifetime predicate.
///
/// E.g. `'a: 'b+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereRegionPredicate {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use ident::parsing::ident;
    use ty::parsing::{ty, poly_trait_ref};

    named!(pub generics -> Generics, do_parse!(
        bracketed: alt!(
            do_parse!(
                punct!("<") >>
                lifetimes: separated_list!(punct!(","), lifetime_def) >>
                ty_params: opt_vec!(preceded!(
                    cond!(!lifetimes.is_empty(), punct!(",")),
                    separated_nonempty_list!(punct!(","), ty_param)
                )) >>
                punct!(">") >>
                (lifetimes, ty_params)
            )
            |
            epsilon!() => { |_| (Vec::new(), Vec::new()) }
        ) >>
        where_clause: where_clause >>
        (Generics {
            lifetimes: bracketed.0,
            ty_params: bracketed.1,
            where_clause: where_clause,
        })
    ));

    named!(pub lifetime -> Lifetime, preceded!(
        punct!("'"),
        map!(ident, |id| Lifetime {
            ident: format!("'{}", id).into(),
        })
    ));

    named!(pub lifetime_def -> LifetimeDef, do_parse!(
        life: lifetime >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), lifetime)
        )) >>
        (LifetimeDef {
            lifetime: life,
            bounds: bounds,
        })
    ));

    named!(pub bound_lifetimes -> Vec<LifetimeDef>, opt_vec!(do_parse!(
        keyword!("for") >>
        punct!("<") >>
        lifetimes: separated_list!(punct!(","), lifetime_def) >>
        punct!(">") >>
        (lifetimes)
    )));

    named!(ty_param -> TyParam, do_parse!(
        id: ident >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), ty_param_bound)
        )) >>
        default: option!(preceded!(
            punct!("="),
            ty
        )) >>
        (TyParam {
            ident: id,
            bounds: bounds,
            default: default,
        })
    ));

    named!(pub ty_param_bound -> TyParamBound, alt!(
        preceded!(punct!("?"), poly_trait_ref) => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe)
        }
        |
        lifetime => { TyParamBound::Region }
        |
        poly_trait_ref => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
        }
    ));

    named!(pub where_clause -> WhereClause, alt!(
        do_parse!(
            keyword!("where") >>
            predicates: separated_nonempty_list!(punct!(","), where_predicate) >>
            option!(punct!(",")) >>
            (WhereClause { predicates: predicates })
        )
        |
        epsilon!() => { |_| Default::default() }
    ));

    named!(where_predicate -> WherePredicate, alt!(
        do_parse!(
            ident: lifetime >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), lifetime) >>
            (WherePredicate::RegionPredicate(WhereRegionPredicate {
                lifetime: ident,
                bounds: bounds,
            }))
        )
        |
        do_parse!(
            bound_lifetimes: bound_lifetimes >>
            bounded_ty: ty >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
            (WherePredicate::BoundPredicate(WhereBoundPredicate {
                bound_lifetimes: bound_lifetimes,
                bounded_ty: bounded_ty,
                bounds: bounds,
            }))
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Generics {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.lifetimes.is_empty();
            let has_ty_params = !self.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                tokens.append_separated(&self.ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
        }
    }

    impl ToTokens for LifetimeDef {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for TyParam {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
            if let Some(ref default) = self.default {
                tokens.append("=");
                default.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TyParamBound {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
                TyParamBound::Trait(ref trait_ref, modifier) => {
                    match modifier {
                        TraitBoundModifier::None => {}
                        TraitBoundModifier::Maybe => tokens.append("?"),
                    }
                    trait_ref.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereClause {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.predicates.is_empty() {
                tokens.append("where");
                tokens.append_separated(&self.predicates, ",");
            }
        }
    }

    impl ToTokens for WherePredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                WherePredicate::BoundPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::RegionPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereBoundPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.bound_lifetimes.is_empty() {
                tokens.append("for");
                tokens.append("<");
                tokens.append_separated(&self.bound_lifetimes, ",");
                tokens.append(">");
            }
            self.bounded_ty.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereRegionPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Defines the most basic types and constants like the pieces,
//! colors, squares, files, and ranks.
//!
//! This module also defines few simple functions.

/// `WHITE` or `BLACK`.
pub type Color = usize; // 0 or 1

/// `KING`, `QUEEN`, `ROOK`, `BISHOP`, `KINGHT`, `PAWN`, `NO_PIECE`,
/// or `UNKNOWN_PIECE`.
pub type PieceType = usize;  // from 0 to 5

/// From 0 to 7 (0 is rank 1, 7 is rank 8).
pub type Rank = usize;  // from 0 to 7

/// From 0 to 7 (0 is file A, 7 is file H).
pub type File = usize;  // from 0 to 7

/// From 0 to 63 (0 is A1, 63 is H8).
pub type Square = usize;  // from 0 to 63

/// Number of searched positions.
pub type NodeCount = u64;

/// `QUEENSIDE` or `KINGSIDE`.
pub type CastlingSide = usize;

/// A set of squares on the chessboard.
///
/// `u64` bit-sets called *bitboards* (BB) can be used to represent a
/// set of squares on the chessboard. For example, the set of squares
/// which are occupied by white rooks in the beginning of the game is:
/// `1 << A1 || 1 << H1`.
pub type Bitboard = u64;

/// Evaluation value in centipawns.
///
/// Positive values mean that the position is favorable for the side
/// to move. Negative values mean the position is favorable for the
/// other side (not to move). A value of `0` means that the chances
/// are equal. For example: a value of `100` might mean that the side
/// to move is a pawn ahead.
///
/// Values over `19999` and under `-19999` designate a certain
/// win/loss. The constant `VALUE_UNKNOWN` equals to `-32768`, and has
/// the special meaning of "unknown value".
pub type Value = i16;

// The maximum possible search depth. Should be less than 127.
pub const MAX_DEPTH: u8 = 63;

// Color
pub const WHITE: Color = 0;
pub const BLACK: Color = 1;

// Piece types
pub const KING: PieceType = 0;
pub const QUEEN: PieceType = 1;
pub const ROOK: PieceType = 2;
pub const BISHOP: PieceType = 3;
pub const KNIGHT: PieceType = 4;
pub const PAWN: PieceType = 5;
pub const NO_PIECE: PieceType = 6;
pub const UNKNOWN_PIECE: PieceType = 7;

// Ranks
pub const RANK_1: Rank = 0;
pub const RANK_2: Rank = 1;
pub const RANK_3: Rank = 2;
pub const RANK_4: Rank = 3;
pub const RANK_5: Rank = 4;
pub const RANK_6: Rank = 5;
pub const RANK_7: Rank = 6;
pub const RANK_8: Rank = 7;

// Files
pub const FILE_A: File = 0;
pub const FILE_B: File = 1;
pub const FILE_C: File = 2;
pub const FILE_D: File = 3;
pub const FILE_E: File = 4;
pub const FILE_F: File = 5;
pub const FILE_G: File = 6;
pub const FILE_H: File = 7;

// Squares
pub const A1: Square = 0 + 0 * 8;
pub const B1: Square = 1 + 0 * 8;
pub const C1: Square = 2 + 0 * 8;
pub const D1: Square = 3 + 0 * 8;
pub const E1: Square = 4 + 0 * 8;
pub const F1: Square = 5 + 0 * 8;
pub const G1: Square = 6 + 0 * 8;
pub const H1: Square = 7 + 0 * 8;
pub const A2: Square = 0 + 1 * 8;
pub const B2: Square = 1 + 1 * 8;
pub const C2: Square = 2 + 1 * 8;
pub const D2: Square = 3 + 1 * 8;
pub const E2: Square = 4 + 1 * 8;
pub const F2: Square = 5 + 1 * 8;
pub const G2: Square = 6 + 1 * 8;
pub const H2: Square = 7 + 1 * 8;
pub const A3: Square = 0 + 2 * 8;
pub const B3: Square = 1 + 2 * 8;
pub const C3: Square = 2 + 2 * 8;
pub const D3: Square = 3 + 2 * 8;
pub const E3: Square = 4 + 2 * 8;
pub const F3: Square = 5 + 2 * 8;
pub const G3: Square = 6 + 2 * 8;
pub const H3: Square = 7 + 2 * 8;
pub const A4: Square = 0 + 3 * 8;
pub const B4: Square = 1 + 3 * 8;
pub const C4: Square = 2 + 3 * 8;
pub const D4: Square = 3 + 3 * 8;
pub const E4: Square = 4 + 3 * 8;
pub const F4: Square = 5 + 3 * 8;
pub const G4: Square = 6 + 3 * 8;
pub const H4: Square = 7 + 3 * 8;
pub const A5: Square = 0 + 4 * 8;
pub const B5: Square = 1 + 4 * 8;
pub const C5: Square = 2 + 4 * 8;
pub const D5: Square = 3 + 4 * 8;
pub const E5: Square = 4 + 4 * 8;
pub const F5: Square = 5 + 4 * 8;
pub const G5: Square = 6 + 4 * 8;
pub const H5: Square = 7 + 4 * 8;
pub const A6: Square = 0 + 5 * 8;
pub const B6: Square = 1 + 5 * 8;
pub const C6: Square = 2 + 5 * 8;
pub const D6: Square = 3 + 5 * 8;
pub const E6: Square = 4 + 5 * 8;
pub const F6: Square = 5 + 5 * 8;
pub const G6: Square = 6 + 5 * 8;
pub const H6: Square = 7 + 5 * 8;
pub const A7: Square = 0 + 6 * 8;
pub const B7: Square = 1 + 6 * 8;
pub const C7: Square = 2 + 6 * 8;
pub const D7: Square = 3 + 6 * 8;
pub const E7: Square = 4 + 6 * 8;
pub const F7: Square = 5 + 6 * 8;
pub const G7: Square = 6 + 6 * 8;
pub const H7: Square = 7 + 6 * 8;
pub const A8: Square = 0 + 7 * 8;
pub const B8: Square = 1 + 7 * 8;
pub const C8: Square = 2 + 7 * 8;
pub const D8: Square = 3 + 7 * 8;
pub const E8: Square = 4 + 7 * 8;
pub const F8: Square = 5 + 7 * 8;
pub const G8: Square = 6 + 7 * 8;
pub const H8: Square = 7 + 7 * 8;

// Value
pub const VALUE_UNKNOWN: Value = ::std::i16::MIN;

// Castling side
pub const QUEENSIDE: CastlingSide = 0;
pub const KINGSIDE: CastlingSide = 1;

// Bitboards.
pub const BB_EMPTY_SET: Bitboard = 0;
pub const BB_UNIVERSAL_SET: Bitboard = 0xffffffffffffffff;

/// Returns the square on given file and rank.
#[inline]
pub fn square(file: File, rank: Rank) -> Square {
    assert!(file < 8);
    assert!(rank < 8);
    rank * 8 + file
}

/// Returns the rank of a given square.
#[inline(always)]
pub fn rank(square: Square) -> Rank {
    assert!(square <= 63);
    square >> 3
}

/// Returns the file of a given square.
#[inline(always)]
pub fn file(square: Square) -> File {
    assert!(square <= 63);
    square % 8
}

/// Returns the algebraic notation for a given square.
pub fn notation(square: Square) -> &'static str {
    lazy_static! {
        static ref NOTATION: Vec<String> = (0..64).map(|i| format!("{}{}",
            ["a", "b", "c", "d", "e", "f", "g", "h"][file(i)],
            ["1", "2", "3", "4", "5", "6", "7", "8"][rank(i)])
        ).collect();
    }
    NOTATION[square].as_str()
}
<commit_msg>fixed doc<commit_after>//! Defines the most basic types and constants like the pieces,
//! colors, squares, files, and ranks.
//!
//! This module also defines few simple functions.

/// `WHITE` or `BLACK`.
pub type Color = usize; // 0 or 1

/// `KING`, `QUEEN`, `ROOK`, `BISHOP`, `KINGHT`, `PAWN`, `NO_PIECE`,
/// or `UNKNOWN_PIECE`.
pub type PieceType = usize;  // from 0 to 5

/// From 0 to 7 (0 is rank 1, 7 is rank 8).
pub type Rank = usize;  // from 0 to 7

/// From 0 to 7 (0 is file A, 7 is file H).
pub type File = usize;  // from 0 to 7

/// From 0 to 63 (0 is A1, 63 is H8).
pub type Square = usize;  // from 0 to 63

/// Number of searched positions.
pub type NodeCount = u64;

/// `QUEENSIDE` or `KINGSIDE`.
pub type CastlingSide = usize;

/// A set of squares on the chessboard.
///
/// `u64` bit-sets called *bitboards* (BB) can be used to represent a
/// set of squares on the chessboard. For example, the set of squares
/// which are occupied by white rooks in the beginning of the game is:
/// `1 << A1 | 1 << H1`.
pub type Bitboard = u64;

/// Evaluation value in centipawns.
///
/// Positive values mean that the position is favorable for the side
/// to move. Negative values mean the position is favorable for the
/// other side (not to move). A value of `0` means that the chances
/// are equal. For example: a value of `100` might mean that the side
/// to move is a pawn ahead.
///
/// Values over `19999` and under `-19999` designate a certain
/// win/loss. The constant `VALUE_UNKNOWN` equals to `-32768`, and has
/// the special meaning of "unknown value".
pub type Value = i16;

// The maximum possible search depth. Should be less than 127.
pub const MAX_DEPTH: u8 = 63;

// Color
pub const WHITE: Color = 0;
pub const BLACK: Color = 1;

// Piece types
pub const KING: PieceType = 0;
pub const QUEEN: PieceType = 1;
pub const ROOK: PieceType = 2;
pub const BISHOP: PieceType = 3;
pub const KNIGHT: PieceType = 4;
pub const PAWN: PieceType = 5;
pub const NO_PIECE: PieceType = 6;
pub const UNKNOWN_PIECE: PieceType = 7;

// Ranks
pub const RANK_1: Rank = 0;
pub const RANK_2: Rank = 1;
pub const RANK_3: Rank = 2;
pub const RANK_4: Rank = 3;
pub const RANK_5: Rank = 4;
pub const RANK_6: Rank = 5;
pub const RANK_7: Rank = 6;
pub const RANK_8: Rank = 7;

// Files
pub const FILE_A: File = 0;
pub const FILE_B: File = 1;
pub const FILE_C: File = 2;
pub const FILE_D: File = 3;
pub const FILE_E: File = 4;
pub const FILE_F: File = 5;
pub const FILE_G: File = 6;
pub const FILE_H: File = 7;

// Squares
pub const A1: Square = 0 + 0 * 8;
pub const B1: Square = 1 + 0 * 8;
pub const C1: Square = 2 + 0 * 8;
pub const D1: Square = 3 + 0 * 8;
pub const E1: Square = 4 + 0 * 8;
pub const F1: Square = 5 + 0 * 8;
pub const G1: Square = 6 + 0 * 8;
pub const H1: Square = 7 + 0 * 8;
pub const A2: Square = 0 + 1 * 8;
pub const B2: Square = 1 + 1 * 8;
pub const C2: Square = 2 + 1 * 8;
pub const D2: Square = 3 + 1 * 8;
pub const E2: Square = 4 + 1 * 8;
pub const F2: Square = 5 + 1 * 8;
pub const G2: Square = 6 + 1 * 8;
pub const H2: Square = 7 + 1 * 8;
pub const A3: Square = 0 + 2 * 8;
pub const B3: Square = 1 + 2 * 8;
pub const C3: Square = 2 + 2 * 8;
pub const D3: Square = 3 + 2 * 8;
pub const E3: Square = 4 + 2 * 8;
pub const F3: Square = 5 + 2 * 8;
pub const G3: Square = 6 + 2 * 8;
pub const H3: Square = 7 + 2 * 8;
pub const A4: Square = 0 + 3 * 8;
pub const B4: Square = 1 + 3 * 8;
pub const C4: Square = 2 + 3 * 8;
pub const D4: Square = 3 + 3 * 8;
pub const E4: Square = 4 + 3 * 8;
pub const F4: Square = 5 + 3 * 8;
pub const G4: Square = 6 + 3 * 8;
pub const H4: Square = 7 + 3 * 8;
pub const A5: Square = 0 + 4 * 8;
pub const B5: Square = 1 + 4 * 8;
pub const C5: Square = 2 + 4 * 8;
pub const D5: Square = 3 + 4 * 8;
pub const E5: Square = 4 + 4 * 8;
pub const F5: Square = 5 + 4 * 8;
pub const G5: Square = 6 + 4 * 8;
pub const H5: Square = 7 + 4 * 8;
pub const A6: Square = 0 + 5 * 8;
pub const B6: Square = 1 + 5 * 8;
pub const C6: Square = 2 + 5 * 8;
pub const D6: Square = 3 + 5 * 8;
pub const E6: Square = 4 + 5 * 8;
pub const F6: Square = 5 + 5 * 8;
pub const G6: Square = 6 + 5 * 8;
pub const H6: Square = 7 + 5 * 8;
pub const A7: Square = 0 + 6 * 8;
pub const B7: Square = 1 + 6 * 8;
pub const C7: Square = 2 + 6 * 8;
pub const D7: Square = 3 + 6 * 8;
pub const E7: Square = 4 + 6 * 8;
pub const F7: Square = 5 + 6 * 8;
pub const G7: Square = 6 + 6 * 8;
pub const H7: Square = 7 + 6 * 8;
pub const A8: Square = 0 + 7 * 8;
pub const B8: Square = 1 + 7 * 8;
pub const C8: Square = 2 + 7 * 8;
pub const D8: Square = 3 + 7 * 8;
pub const E8: Square = 4 + 7 * 8;
pub const F8: Square = 5 + 7 * 8;
pub const G8: Square = 6 + 7 * 8;
pub const H8: Square = 7 + 7 * 8;

// Value
pub const VALUE_UNKNOWN: Value = ::std::i16::MIN;

// Castling side
pub const QUEENSIDE: CastlingSide = 0;
pub const KINGSIDE: CastlingSide = 1;

// Bitboards.
pub const BB_EMPTY_SET: Bitboard = 0;
pub const BB_UNIVERSAL_SET: Bitboard = 0xffffffffffffffff;

/// Returns the square on given file and rank.
#[inline]
pub fn square(file: File, rank: Rank) -> Square {
    assert!(file < 8);
    assert!(rank < 8);
    rank * 8 + file
}

/// Returns the rank of a given square.
#[inline(always)]
pub fn rank(square: Square) -> Rank {
    assert!(square <= 63);
    square >> 3
}

/// Returns the file of a given square.
#[inline(always)]
pub fn file(square: Square) -> File {
    assert!(square <= 63);
    square % 8
}

/// Returns the algebraic notation for a given square.
pub fn notation(square: Square) -> &'static str {
    lazy_static! {
        static ref NOTATION: Vec<String> = (0..64).map(|i| format!("{}{}",
            ["a", "b", "c", "d", "e", "f", "g", "h"][file(i)],
            ["1", "2", "3", "4", "5", "6", "7", "8"][rank(i)])
        ).collect();
    }
    NOTATION[square].as_str()
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
use coreutils::extra::OptionalExt;

use std::env::args;
use std::fs::File;
use std::hash::Hasher;
use std::io::{Write, Read, stdin, stdout};
use std::mem;

static HELP: &'static str = r#"
    NAME
        cksum - calculate the DJB2 checksum of the input.
    SYNOPSIS
        cksum [-h | --help] [-b | --binary] [FILE 1] [FILE 2]...
    DESCRIPTION
        This utility is used for calculating the checksum from one or more byte streams (files and/or standard input). The ordering of the arguments do matter.

        'cksum' differs from the Unix version in multiple ways. Most importantly: it uses DJB2, a streaming non-cryptographic hash function.

        'cksum' defaults to hexadecimal.

        NOTA BENE: This tool should **never** be used as a secure hash function, since DJB2 is non-cryptographic, and easily breakable.
    OPTIONS
        -h
        --help
            Print this manual page.
        -b
        --binary
            Print the output in base 256.
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

pub struct Djb2 {
    state: u64,
}

impl Default for Djb2 {
    fn default() -> Djb2 {
        Djb2 {
            state: 5381,
        }
    }
}

impl Hasher for Djb2 {
    fn finish(&self) -> u64 {
        self.state
    }

    fn write(&mut self, bytes: &[u8]) {
        for &b in bytes {
            self.state = (self.state << 5).wrapping_add(self.state).wrapping_add(b as u64);
        }
    }
}

/// Convert hex to ascii
#[inline]
pub fn hex_to_ascii(b: u8) -> u8 {
    match b {
        0...9 => b'0' + b,
        _ => b'a' - 10 + b,
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut buf = Vec::new();
    let mut binary_mode = false;
    let args = args();

    for i in args.skip(1) {
        match i.as_str() {
            "-h" | "--help" => {
                stdout.write(HELP.as_bytes()).try(&mut stdout);
            }
            "-b" | "--binary" => binary_mode = true,
            "-" => {
                stdin().read_to_end(&mut buf).try(&mut stdout);
            }
            file => {
                File::open(file).try(&mut stdout).read_to_end(&mut buf).try(&mut stdout);
            },
        }
    }

    let mut hasher: Djb2 = Default::default();
    hasher.write(&buf);
    let hash = unsafe { mem::transmute::<u64, [u8; 8]>(hasher.finish()) };

    if binary_mode {
        stdout.write(&hash).try(&mut stdout);
    } else {
        for i in hash.iter() {
            stdout.write(&[hex_to_ascii(i & 0b1111), hex_to_ascii(i >> 4)]).try(&mut stdout);
        }
    }

    stdout.write(b"\n")
}
<commit_msg>Handle fail case<commit_after>#![deny(warnings)]

extern crate coreutils;
use coreutils::extra::OptionalExt;

use std::env::args;
use std::fs::File;
use std::hash::Hasher;
use std::io::{Write, Read, stdin, stdout};
use std::mem;

static HELP: &'static str = r#"
    NAME
        cksum - calculate the DJB2 checksum of the input.
    SYNOPSIS
        cksum [-h | --help] [-b | --binary] [FILE 1] [FILE 2]...
    DESCRIPTION
        This utility is used for calculating the checksum from one or more byte streams (files and/or standard input). The ordering of the arguments do matter.

        'cksum' differs from the Unix version in multiple ways. Most importantly: it uses DJB2, a streaming non-cryptographic hash function.

        'cksum' defaults to hexadecimal.

        NOTA BENE: This tool should **never** be used as a secure hash function, since DJB2 is non-cryptographic, and easily breakable.
    OPTIONS
        -h
        --help
            Print this manual page.
        -b
        --binary
            Print the output in base 256.
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

pub struct Djb2 {
    state: u64,
}

impl Default for Djb2 {
    fn default() -> Djb2 {
        Djb2 {
            state: 5381,
        }
    }
}

impl Hasher for Djb2 {
    fn finish(&self) -> u64 {
        self.state
    }

    fn write(&mut self, bytes: &[u8]) {
        for &b in bytes {
            self.state = (self.state << 5).wrapping_add(self.state).wrapping_add(b as u64);
        }
    }
}

/// Convert hex to ascii
#[inline]
pub fn hex_to_ascii(b: u8) -> u8 {
    match b {
        0...9 => b'0' + b,
        _ => b'a' - 10 + b,
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut buf = Vec::new();
    let mut binary_mode = false;
    let args = args();

    for i in args.skip(1) {
        match i.as_str() {
            "-h" | "--help" => {
                stdout.write(HELP.as_bytes()).try(&mut stdout);
            }
            "-b" | "--binary" => binary_mode = true,
            "-" => {
                stdin().read_to_end(&mut buf).try(&mut stdout);
            }
            file => {
                File::open(file).try(&mut stdout).read_to_end(&mut buf).try(&mut stdout);
            },
        }
    }

    let mut hasher: Djb2 = Default::default();
    hasher.write(&buf);
    let hash = unsafe { mem::transmute::<u64, [u8; 8]>(hasher.finish()) };

    if binary_mode {
        stdout.write(&hash).try(&mut stdout);
    } else {
        for i in hash.iter() {
            stdout.write(&[hex_to_ascii(i & 0b1111), hex_to_ascii(i >> 4)]).try(&mut stdout);
        }
    }

    stdout.write(b"\n").try(&mut stdout);
}
<|endoftext|>