<commit_before>use compression;
use types::ZipFile;
use spec;
use writer_spec;
use crc32;
use std::default::Default;
use std::io;
use std::io::{IoResult, IoError};
use std::mem;
use time;
use flate2;
use flate2::FlateWriter;
use flate2::writer::DeflateEncoder;

enum GenericZipWriter<W>
{
    Closed,
    Storer(W),
    Deflater(DeflateEncoder<W>),
}

/// Generator for ZIP files.
///
/// ```
/// fn doit() -> std::io::IoResult<()>
/// {
///     // For this example we write to a buffer, but normally you should use a File
///     let mut buf = [0u8, ..65536];
///     let w = std::io::BufWriter::new(&mut buf);
///     let mut zip = zip::ZipWriter::new(w);
///
///     try!(zip.start_file("hello_world.txt", zip::compression::Stored));
///     try!(zip.write(b"Hello, World!"));
///
///     // Optionally finish the zip. (this is also done on drop)
///     try!(zip.finish());
///
///     Ok(())
/// }
///
/// println!("Result: {}", doit());
/// ```
pub struct ZipWriter<W>
{
    inner: GenericZipWriter<W>,
    files: Vec<ZipFile>,
    stats: ZipWriterStats,
}

#[deriving(Default)]
struct ZipWriterStats
{
    crc32: u32,
    start: u64,
    bytes_written: u64,
}

fn writer_closed_error<T>() -> IoResult<T>
{
    Err(IoError { kind: io::Closed, desc: "This writer has been closed", detail: None })
}

impl<W: Writer+Seek> Writer for ZipWriter<W>
{
    fn write(&mut self, buf: &[u8]) -> IoResult<()>
    {
        if self.files.len() == 0 { return Err(IoError { kind: io::OtherIoError, desc: "No file has been started", detail: None, }) }
        self.stats.update(buf);
        match self.inner
        {
            Storer(ref mut w) => w.write(buf),
            Deflater(ref mut w) => w.write(buf),
            Closed => writer_closed_error(),
        }
    }
}

impl ZipWriterStats
{
    fn update(&mut self, buf: &[u8])
    {
        self.crc32 = crc32::update(self.crc32, buf);
        self.bytes_written += buf.len() as u64;
    }
}

impl<W: Writer+Seek> ZipWriter<W>
{
    /// Initializes the ZipWriter.
    ///
    /// Before writing to this object, the start_file command should be called.
    pub fn new(inner: W) -> ZipWriter<W>
    {
        ZipWriter
        {
            inner: Storer(inner),
            files: Vec::new(),
            stats: Default::default(),
        }
    }

    /// Start a new file for with the requested compression method.
    pub fn start_file(&mut self, name: &str, compression: compression::CompressionMethod) -> IoResult<()>
    {
        try!(self.finish_file());

        {
            let writer = self.inner.get_plain();
            let header_start = try!(writer.tell());

            let mut file = ZipFile
            {
                encrypted: false,
                compression_method: compression,
                last_modified_time: time::now(),
                crc32: 0,
                compressed_size: 0,
                uncompressed_size: 0,
                file_name: String::from_str(name),
                file_comment: String::new(),
                header_start: header_start,
                data_start: 0,
            };
            try!(writer_spec::write_local_file_header(writer, &file));

            let header_end = try!(writer.tell());
            self.stats.start = header_end;
            file.data_start = header_end;

            self.stats.bytes_written = 0;
            self.stats.crc32 = 0;

            self.files.push(file);
        }

        try!(self.inner.switch_to(compression));

        Ok(())
    }

    fn finish_file(&mut self) -> IoResult<()>
    {
        try!(self.inner.switch_to(compression::Stored));
        let writer = self.inner.get_plain();

        let file = match self.files.last_mut()
        {
            None => return Ok(()),
            Some(f) => f,
        };
        file.crc32 = self.stats.crc32;
        file.uncompressed_size = self.stats.bytes_written;
        file.compressed_size = try!(writer.tell()) - self.stats.start;

        try!(writer_spec::update_local_file_header(writer, file));
        try!(writer.seek(0, io::SeekEnd));
        Ok(())
    }

    /// Finish the last file and write all other zip-structures
    ///
    /// This will return the writer, but one should normally not append any data to the end of the file.
    /// Note that the zipfile will also be finished on drop.
    pub fn finish(mut self) -> IoResult<W>
    {
        try!(self.finalize());
        let inner = mem::replace(&mut self.inner, Closed);
        Ok(inner.unwrap())
    }

    fn finalize(&mut self) -> IoResult<()>
    {
        try!(self.finish_file());

        {
            let writer = self.inner.get_plain();

            let central_start = try!(writer.tell());
            for file in self.files.iter()
            {
                try!(writer_spec::write_central_directory_header(writer, file));
            }
            let central_size = try!(writer.tell()) - central_start;

            let footer = spec::CentralDirectoryEnd
            {
                disk_number: 0,
                disk_with_central_directory: 0,
                number_of_files_on_this_disk: self.files.len() as u16,
                number_of_files: self.files.len() as u16,
                central_directory_size: central_size as u32,
                central_directory_offset: central_start as u32,
                zip_file_comment: b"zip-rs".to_vec(),
            };

            try!(footer.write(writer));
        }

        Ok(())
    }
}

#[unsafe_destructor]
impl<W: Writer+Seek> Drop for ZipWriter<W>
{
    fn drop(&mut self)
    {
        if !self.inner.is_closed()
        {
            match self.finalize()
            {
                Ok(_) => {},
                Err(e) => warn!("ZipWriter drop failed: {}", e),
            }
        }
    }
}

impl<W: Writer+Seek> GenericZipWriter<W>
{
    fn switch_to(&mut self, compression: compression::CompressionMethod) -> IoResult<()>
    {
        let bare = match mem::replace(self, Closed)
        {
            Storer(w) => w,
            Deflater(w) => try!(w.finish()),
            Closed => return writer_closed_error(),
        };

        *self = match compression
        {
            compression::Stored => Storer(bare),
            compression::Deflated => Deflater(bare.deflate_encode(flate2::Default)),
            _ => return Err(IoError { kind: io::OtherIoError, desc: "Unsupported compression requested", detail: None }),
        };

        Ok(())
    }

    fn is_closed(&self) -> bool
    {
        match *self
        {
            Closed => true,
            _ => false,
        }
    }

    fn get_plain(&mut self) -> &mut W
    {
        match *self
        {
            Storer(ref mut w) => w,
            _ => fail!("Should have switched to stored beforehand"),
        }
    }

    fn unwrap(self) -> W
    {
        match self
        {
            Storer(w) => w,
            _ => fail!("Should have switched to stored beforehand"),
        }
    }
}
<commit_msg>fail -> panic<commit_after>use compression;
use types::ZipFile;
use spec;
use writer_spec;
use crc32;
use std::default::Default;
use std::io;
use std::io::{IoResult, IoError};
use std::mem;
use time;
use flate2;
use flate2::FlateWriter;
use flate2::writer::DeflateEncoder;

enum GenericZipWriter<W>
{
    Closed,
    Storer(W),
    Deflater(DeflateEncoder<W>),
}

/// Generator for ZIP files.
///
/// ```
/// fn doit() -> std::io::IoResult<()>
/// {
///     // For this example we write to a buffer, but normally you should use a File
///     let mut buf = [0u8, ..65536];
///     let w = std::io::BufWriter::new(&mut buf);
///     let mut zip = zip::ZipWriter::new(w);
///
///     try!(zip.start_file("hello_world.txt", zip::compression::Stored));
///     try!(zip.write(b"Hello, World!"));
///
///     // Optionally finish the zip. (this is also done on drop)
///     try!(zip.finish());
///
///     Ok(())
/// }
///
/// println!("Result: {}", doit());
/// ```
pub struct ZipWriter<W>
{
    inner: GenericZipWriter<W>,
    files: Vec<ZipFile>,
    stats: ZipWriterStats,
}

#[deriving(Default)]
struct ZipWriterStats
{
    crc32: u32,
    start: u64,
    bytes_written: u64,
}

fn writer_closed_error<T>() -> IoResult<T>
{
    Err(IoError { kind: io::Closed, desc: "This writer has been closed", detail: None })
}

impl<W: Writer+Seek> Writer for ZipWriter<W>
{
    fn write(&mut self, buf: &[u8]) -> IoResult<()>
    {
        if self.files.len() == 0 { return Err(IoError { kind: io::OtherIoError, desc: "No file has been started", detail: None, }) }
        self.stats.update(buf);
        match self.inner
        {
            Storer(ref mut w) => w.write(buf),
            Deflater(ref mut w) => w.write(buf),
            Closed => writer_closed_error(),
        }
    }
}

impl ZipWriterStats
{
    fn update(&mut self, buf: &[u8])
    {
        self.crc32 = crc32::update(self.crc32, buf);
        self.bytes_written += buf.len() as u64;
    }
}

impl<W: Writer+Seek> ZipWriter<W>
{
    /// Initializes the ZipWriter.
    ///
    /// Before writing to this object, the start_file command should be called.
    pub fn new(inner: W) -> ZipWriter<W>
    {
        ZipWriter
        {
            inner: Storer(inner),
            files: Vec::new(),
            stats: Default::default(),
        }
    }

    /// Start a new file for with the requested compression method.
    pub fn start_file(&mut self, name: &str, compression: compression::CompressionMethod) -> IoResult<()>
    {
        try!(self.finish_file());

        {
            let writer = self.inner.get_plain();
            let header_start = try!(writer.tell());

            let mut file = ZipFile
            {
                encrypted: false,
                compression_method: compression,
                last_modified_time: time::now(),
                crc32: 0,
                compressed_size: 0,
                uncompressed_size: 0,
                file_name: String::from_str(name),
                file_comment: String::new(),
                header_start: header_start,
                data_start: 0,
            };
            try!(writer_spec::write_local_file_header(writer, &file));

            let header_end = try!(writer.tell());
            self.stats.start = header_end;
            file.data_start = header_end;

            self.stats.bytes_written = 0;
            self.stats.crc32 = 0;

            self.files.push(file);
        }

        try!(self.inner.switch_to(compression));

        Ok(())
    }

    fn finish_file(&mut self) -> IoResult<()>
    {
        try!(self.inner.switch_to(compression::Stored));
        let writer = self.inner.get_plain();

        let file = match self.files.last_mut()
        {
            None => return Ok(()),
            Some(f) => f,
        };
        file.crc32 = self.stats.crc32;
        file.uncompressed_size = self.stats.bytes_written;
        file.compressed_size = try!(writer.tell()) - self.stats.start;

        try!(writer_spec::update_local_file_header(writer, file));
        try!(writer.seek(0, io::SeekEnd));
        Ok(())
    }

    /// Finish the last file and write all other zip-structures
    ///
    /// This will return the writer, but one should normally not append any data to the end of the file.
    /// Note that the zipfile will also be finished on drop.
    pub fn finish(mut self) -> IoResult<W>
    {
        try!(self.finalize());
        let inner = mem::replace(&mut self.inner, Closed);
        Ok(inner.unwrap())
    }

    fn finalize(&mut self) -> IoResult<()>
    {
        try!(self.finish_file());

        {
            let writer = self.inner.get_plain();

            let central_start = try!(writer.tell());
            for file in self.files.iter()
            {
                try!(writer_spec::write_central_directory_header(writer, file));
            }
            let central_size = try!(writer.tell()) - central_start;

            let footer = spec::CentralDirectoryEnd
            {
                disk_number: 0,
                disk_with_central_directory: 0,
                number_of_files_on_this_disk: self.files.len() as u16,
                number_of_files: self.files.len() as u16,
                central_directory_size: central_size as u32,
                central_directory_offset: central_start as u32,
                zip_file_comment: b"zip-rs".to_vec(),
            };

            try!(footer.write(writer));
        }

        Ok(())
    }
}

#[unsafe_destructor]
impl<W: Writer+Seek> Drop for ZipWriter<W>
{
    fn drop(&mut self)
    {
        if !self.inner.is_closed()
        {
            match self.finalize()
            {
                Ok(_) => {},
                Err(e) => warn!("ZipWriter drop failed: {}", e),
            }
        }
    }
}

impl<W: Writer+Seek> GenericZipWriter<W>
{
    fn switch_to(&mut self, compression: compression::CompressionMethod) -> IoResult<()>
    {
        let bare = match mem::replace(self, Closed)
        {
            Storer(w) => w,
            Deflater(w) => try!(w.finish()),
            Closed => return writer_closed_error(),
        };

        *self = match compression
        {
            compression::Stored => Storer(bare),
            compression::Deflated => Deflater(bare.deflate_encode(flate2::Default)),
            _ => return Err(IoError { kind: io::OtherIoError, desc: "Unsupported compression requested", detail: None }),
        };

        Ok(())
    }

    fn is_closed(&self) -> bool
    {
        match *self
        {
            Closed => true,
            _ => false,
        }
    }

    fn get_plain(&mut self) -> &mut W
    {
        match *self
        {
            Storer(ref mut w) => w,
            _ => panic!("Should have switched to stored beforehand"),
        }
    }

    fn unwrap(self) -> W
    {
        match self
        {
            Storer(w) => w,
            _ => panic!("Should have switched to stored beforehand"),
        }
    }
}
<|endoftext|>


<commit_before>//! Write las files.

use std::path::Path;

use Result;
use file::File;
use header::Header;
use point::Point;

/// A las writer.
///
/// This wrapper conforms to the more standard structure of requiring a filename on create, not on
/// close.
///
/// I recognize that it's pretty messy to have both this and `File`, and TODO I need to clean
/// things up.
#[derive(Debug)]
pub struct Writer<P: AsRef<Path>> {
    auto_offsets: bool,
    file: File,
    header: Header,
    path: P,
}

impl<P: AsRef<Path>> Writer<P> {
    /// Creates a new writer that will write las data to the given path.
    ///
    /// This won't actually write anything until the writer is closed.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las");
    /// ```
    pub fn from_path(path: P) -> Writer<P> {
        Writer {
            auto_offsets: false,
            file: File::new(),
            header: Header::new(),
            path: path,
        }
    }

    /// Sets the scale factors on a writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").scale_factors(0.01, 0.01, 0.01);
    /// ```
    pub fn scale_factors(mut self,
                         x_scale_factor: f64,
                         y_scale_factor: f64,
                         z_scale_factor: f64)
                         -> Writer<P> {
        self.header.x_scale_factor = x_scale_factor;
        self.header.y_scale_factor = y_scale_factor;
        self.header.z_scale_factor = z_scale_factor;
        self
    }

    /// Sets the offset values for a file.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").offsets(1000.0, 2000.0, 100.0);
    /// ```
    pub fn offsets(mut self, x_offset: f64, y_offset: f64, z_offset: f64) -> Writer<P> {
        self.header.x_offset = x_offset;
        self.header.y_offset = y_offset;
        self.header.z_offset = z_offset;
        self
    }

    /// Enables auto-offsetting.
    ///
    /// If auto-offsetting is enabled, this file will set the header offset values to sensible
    /// values before writing anything. This is usually easier than calculating the offsets
    /// yourself.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").auto_offsets(true);
    /// ```
    pub fn auto_offsets(mut self, enable: bool) -> Writer<P> {
        self.auto_offsets = enable;
        self
    }

    /// Writes a point to this writer.
    ///
    /// Note that this point won't actually be written until the writer is closed.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// use las::point::Point;
    /// let mut writer = Writer::from_path("temp.las");
    /// writer.write_point(Point::new());
    /// ```
    pub fn write_point(&mut self, point: Point) {
        self.file.add_point(point)
    }

    /// Closes this writer and actually writes data out to disc.
    ///
    /// Since we need to calculate some stats on the points for the header, we delay writing until
    /// the very last minute. If you don't want to hold all those points in memory, we'll need to
    /// come up with some other way to do that.
    ///
    /// This function consumes the writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::remove_file;
    /// use las::writer::Writer;
    /// use las::point::Point;
    /// let mut writer = Writer::from_path("temp.las");
    /// writer.write_point(Point::new());
    /// writer.close().unwrap();
    /// remove_file("temp.las").unwrap();
    /// ```
    pub fn close(&mut self) -> Result<()> {
        self.file.set_header(self.header);
        self.file.to_path(&self.path, self.auto_offsets)
    }
}
<commit_msg>Provide more builders on a writer<commit_after>//! Write las files.

use std::path::Path;

use Result;
use file::File;
use header::{Header, PointFormat};
use point::Point;

/// A las writer.
///
/// This wrapper conforms to the more standard structure of requiring a filename on create, not on
/// close.
///
/// I recognize that it's pretty messy to have both this and `File`, and TODO I need to clean
/// things up.
#[derive(Debug)]
pub struct Writer<P: AsRef<Path>> {
    auto_offsets: bool,
    file: File,
    header: Header,
    path: P,
}

impl<P: AsRef<Path>> Writer<P> {
    /// Creates a new writer that will write las data to the given path.
    ///
    /// This won't actually write anything until the writer is closed.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las");
    /// ```
    pub fn from_path(path: P) -> Writer<P> {
        Writer {
            auto_offsets: false,
            file: File::new(),
            header: Header::new(),
            path: path,
        }
    }

    /// Sets the scale factors on a writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").scale_factors(0.01, 0.01, 0.01);
    /// ```
    pub fn scale_factors(mut self,
                         x_scale_factor: f64,
                         y_scale_factor: f64,
                         z_scale_factor: f64)
                         -> Writer<P> {
        self.header.x_scale_factor = x_scale_factor;
        self.header.y_scale_factor = y_scale_factor;
        self.header.z_scale_factor = z_scale_factor;
        self
    }

    /// Sets the offset values for a file.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").offsets(1000.0, 2000.0, 100.0);
    /// ```
    pub fn offsets(mut self, x_offset: f64, y_offset: f64, z_offset: f64) -> Writer<P> {
        self.header.x_offset = x_offset;
        self.header.y_offset = y_offset;
        self.header.z_offset = z_offset;
        self
    }

    /// Enables auto-offsetting.
    ///
    /// If auto-offsetting is enabled, this file will set the header offset values to sensible
    /// values before writing anything. This is usually easier than calculating the offsets
    /// yourself.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").auto_offsets(true);
    /// ```
    pub fn auto_offsets(mut self, enable: bool) -> Writer<P> {
        self.auto_offsets = enable;
        self
    }

    /// Sets the las version for this writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").version(1, 2);
    /// ```
    pub fn version(mut self, major: u8, minor: u8) -> Writer<P> {
        self.header.version_major = major;
        self.header.version_minor = minor;
        self
    }

    /// Sets the point format for this writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::PointFormat;
    /// use las::writer::Writer;
    /// let writer = Writer::from_path("temp.las").point_format(PointFormat(1));
    /// ```
    pub fn point_format(mut self, point_format: PointFormat) -> Writer<P> {
        self.header.point_data_format = point_format;
        self
    }

    /// Writes a point to this writer.
    ///
    /// Note that this point won't actually be written until the writer is closed.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::writer::Writer;
    /// use las::point::Point;
    /// let mut writer = Writer::from_path("temp.las");
    /// writer.write_point(Point::new());
    /// ```
    pub fn write_point(&mut self, point: Point) {
        self.file.add_point(point)
    }

    /// Closes this writer and actually writes data out to disc.
    ///
    /// Since we need to calculate some stats on the points for the header, we delay writing until
    /// the very last minute. If you don't want to hold all those points in memory, we'll need to
    /// come up with some other way to do that.
    ///
    /// This function consumes the writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs::remove_file;
    /// use las::writer::Writer;
    /// use las::point::Point;
    /// let mut writer = Writer::from_path("temp.las");
    /// writer.write_point(Point::new());
    /// writer.close().unwrap();
    /// remove_file("temp.las").unwrap();
    /// ```
    pub fn close(&mut self) -> Result<()> {
        self.file.set_header(self.header);
        self.file.to_path(&self.path, self.auto_offsets)
    }
}

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

    use std::fs::remove_file;

    use {PointFormat, File};

    #[test]
    fn builder() {
        let mut writer = Writer::from_path("builder.las")
                             .scale_factors(1.0, 2.0, 3.0)
                             .offsets(4.0, 5.0, 6.0)
                             .version(1, 2)
                             .point_format(PointFormat(1));
        writer.close().unwrap();

        let file = File::from_path("builder.las").unwrap();
        let header = file.header();
        assert_eq!(1.0, header.x_scale_factor);
        assert_eq!(2.0, header.y_scale_factor);
        assert_eq!(3.0, header.z_scale_factor);
        assert_eq!(4.0, header.x_offset);
        assert_eq!(5.0, header.y_offset);
        assert_eq!(6.0, header.z_offset);
        assert_eq!(1, header.version_major);
        assert_eq!(2, header.version_minor);
        assert_eq!(PointFormat(1), header.point_data_format);

        remove_file("builder.las").unwrap();
    }
}
<|endoftext|>


<commit_before>
#![deny(missing_doc)]

//! Example for Rust-Event using expression based design.
//!
//! The idea is to use combinators of events to describe more complex events.
//! An 'Action' is a variant of an event that spans across time.
//! You program the actions like a state machine, controlling how they interact with the world.
//!
//! Assume you have a complete list of the actions.
//! Any event you can construct from these actions has a corresponding `Cursor`.
//! The cursor keeps track of the combinatorial state.
//!
//! This design is useful in environments where all actions can be broken down
//! into simple interacitons while needing complex combinations of those actions.

extern crate debug;

/// Describes an event.
pub enum Event<A> {
    /// An event where some action is performed.
    Action(A),
    /// An event
    Wait(f64),
    /// An event where sub events are happening sequentially.
    Sequence(Vec<Event<A>>),
    /// An event where sub events are repeated sequentially forever.
    Repeat(Vec<Event<A>>),
    /// An event where any sub event might happen.
    WhenAny(Vec<Event<A>>),
    /// An event where all sub events happen.
    WhenAll(Vec<Event<A>>),
}

/// Keeps track of an event.
pub enum Cursor<'a, A, S> {
    /// Keeps track of an event where you have a state of an action.
    State(&'a A, S),
    /// Keeps track of an event where you wait and do nothing.
    WaitCursor(f64, f64),
    /// Keeps track of an event where sub events happens sequentially.
    SequenceCursor(&'a Vec<Event<A>>, uint, f64, f64, Box<Cursor<'a, A, S>>),
    /// Keeps track of an event where sub events are repeated sequentially.
    RepeatCursor(&'a Vec<Event<A>>, uint, Box<Cursor<'a, A, S>>),
    /// Keeps track of an event where any sub event might happen.
    WhenAnyCursor(&'a Vec<Event<A>>, Vec<Cursor<'a, A, S>>),
    /// Keeps track of an event where all sub events must happen.
    WhenAllCursor(&'a Vec<Event<A>>, Vec<Option<Cursor<'a, A, S>>>),
}

/// Implemented by all actions.
pub trait StartState<S> {
    /// Creates a state from action, which tracks the state.
    fn start_state(&self) -> S;
}

impl<A: StartState<S>, S> Event<A> {
    /// Creates a cursor structure from an event structure.
    ///
    /// The cursor structure keeps track of the state.
    /// You can define your own actions and use the combinations
    /// to create more complex states.
    pub fn to_cursor<'a>(&'a self) -> Cursor<'a, A, S> {
        match *self {
            Action(ref action)
                => State(action, action.start_state()),
            Wait(dt)
                => WaitCursor(dt, 0.0),
            Sequence(ref seq)
                => SequenceCursor(seq, 0, 0.0, 0.0, box seq.get(0).to_cursor()),
            Repeat(ref rep)
                => RepeatCursor(rep, 0, box rep.get(0).to_cursor()),
            WhenAny(ref any)
                => WhenAnyCursor(any, any.iter().map(|ev| ev.to_cursor()).collect()),
            WhenAll(ref all)
                => WhenAllCursor(all, all.iter().map(|ev| Some(ev.to_cursor())).collect()),
        }
    }
}

impl<'a, A: StartState<S>, S> Cursor<'a, A, S> {
    /// Updates the cursor that tracks an event.
    ///
    /// Returns `None` if the action did not terminate.
    /// or `Some(dt)` that tells how much time was consumed by the action.
    pub fn update(
        &mut self,
        dt: f64,
        f: |action: &'a A, state: &S| -> Option<S>
    ) -> Option<f64> {
        match *self {
            State(action, ref mut state) => {
                // Call the function that updates the state.
                match f(action, state) {
                    Some(new_state) => {*state = new_state; None},
                    None => Some(0.0),
                }
            },
            WaitCursor(dt, ref mut t) => {
                // Update the time and return 'false' if we completed.
                *t = dt.min(dt + *t);
                if *t < dt { None } else { Some(dt) }
            },
            SequenceCursor(
                seq,
                ref mut i,
                ref mut inc_dt,
                ref mut waited_dt,
                ref mut cursor
            ) => {
                // Update a sequence of events.
                let next_update = *waited_dt + dt;
                let cur = cursor;
                while *i < seq.len() && *inc_dt <= next_update {
                    // If the sub event terminates,
                    // decrement the delta time for next events.
                    match cur.update(next_update  - *inc_dt, |action, state| f(action, state)) {
                        None => { *waited_dt += dt; break },
                        Some(consumed_dt) => { *waited_dt = 0.0; *inc_dt += consumed_dt },
                    };
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    *i += 1;
                    if *i >= seq.len() { return Some(*inc_dt); }
                    **cur = seq.get(*i).to_cursor();
                }
                None
            },
            _ => unimplemented!(),
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////

/// Some test actions.
pub enum TestActions {
    /// Increment accumulator.
    Inc,
    /// Decrement accumulator.
    Dec,
}

impl StartState<()> for TestActions {
    fn start_state(&self) {}
}

fn exec(mut acc: u32, dt: f64, cursor: &mut Cursor<TestActions, ()>) -> u32 {
    cursor.update(dt, |action, _| {
        println!("{:?}", action);
        match *action {
            Inc => { acc += 1; None },
            Dec => { acc -= 1; None },
        }
    });
    acc
}

fn print_2() {
    // Prints 2.
    let a: u32 = 0;
    let seq = Sequence(vec![Action(Inc), Action(Inc)]);
    let mut cursor = seq.to_cursor();
    let a = exec(a, 0.0, &mut cursor);
    println!("{}", a);
}

fn wait_sec() {
    // Prints 2.
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
    let mut cursor = seq.to_cursor();
    let a = exec(a, 1.0, &mut cursor);
    println!("{}", a);
}

fn main() {
    print_2();
    wait_sec();
}

<commit_msg>Fixed sequence algorithm<commit_after>
#![deny(missing_doc)]

//! Example for Rust-Event using expression based design.
//!
//! The idea is to use combinators of events to describe more complex events.
//! An 'Action' is a variant of an event that spans across time.
//! You program the actions like a state machine, controlling how they interact with the world.
//!
//! Assume you have a complete list of the actions.
//! Any event you can construct from these actions has a corresponding `Cursor`.
//! The cursor keeps track of the combinatorial state.
//!
//! This design is useful in environments where all actions can be broken down
//! into simple interacitons while needing complex combinations of those actions.

extern crate debug;

/// Describes an event.
pub enum Event<A> {
    /// An event where some action is performed.
    Action(A),
    /// An event
    Wait(f64),
    /// An event where sub events are happening sequentially.
    Sequence(Vec<Event<A>>),
    /// An event where sub events are repeated sequentially forever.
    Repeat(Vec<Event<A>>),
    /// An event where any sub event might happen.
    WhenAny(Vec<Event<A>>),
    /// An event where all sub events happen.
    WhenAll(Vec<Event<A>>),
}

/// Keeps track of an event.
pub enum Cursor<'a, A, S> {
    /// Keeps track of an event where you have a state of an action.
    State(&'a A, S),
    /// Keeps track of an event where you wait and do nothing.
    WaitCursor(f64, f64),
    /// Keeps track of an event where sub events happens sequentially.
    SequenceCursor(&'a Vec<Event<A>>, uint, Box<Cursor<'a, A, S>>),
    /// Keeps track of an event where sub events are repeated sequentially.
    RepeatCursor(&'a Vec<Event<A>>, uint, Box<Cursor<'a, A, S>>),
    /// Keeps track of an event where any sub event might happen.
    WhenAnyCursor(&'a Vec<Event<A>>, Vec<Cursor<'a, A, S>>),
    /// Keeps track of an event where all sub events must happen.
    WhenAllCursor(&'a Vec<Event<A>>, Vec<Option<Cursor<'a, A, S>>>),
}

/// Implemented by all actions.
pub trait StartState<S> {
    /// Creates a state from action, which tracks the state.
    fn start_state(&self) -> S;
}

impl<A: StartState<S>, S> Event<A> {
    /// Creates a cursor structure from an event structure.
    ///
    /// The cursor structure keeps track of the state.
    /// You can define your own actions and use the combinations
    /// to create more complex states.
    pub fn to_cursor<'a>(&'a self) -> Cursor<'a, A, S> {
        match *self {
            Action(ref action)
                => State(action, action.start_state()),
            Wait(dt)
                => WaitCursor(dt, 0.0),
            Sequence(ref seq)
                => SequenceCursor(seq, 0, box seq.get(0).to_cursor()),
            Repeat(ref rep)
                => RepeatCursor(rep, 0, box rep.get(0).to_cursor()),
            WhenAny(ref any)
                => WhenAnyCursor(any, any.iter().map(|ev| ev.to_cursor()).collect()),
            WhenAll(ref all)
                => WhenAllCursor(all, all.iter().map(|ev| Some(ev.to_cursor())).collect()),
        }
    }
}

impl<'a, A: StartState<S>, S> Cursor<'a, A, S> {
    /// Updates the cursor that tracks an event.
    ///
    /// Returns `None` if the action did not terminate.
    /// or `Some(dt)` that tells how much time is left of the update time.
    pub fn update(
        &mut self,
        dt: f64,
        f: |action: &'a A, state: &S| -> Option<S>
    ) -> Option<f64> {
        match *self {
            State(action, ref mut state) => {
                // Call the function that updates the state.
                match f(action, state) {
                    Some(new_state) => {
                        *state = new_state;
                        None
                    },
                    // Actions are considered instant,
                    // so there is always a full 'dt' left.
                    None => Some(dt),
                }
            },
            WaitCursor(wait_t, ref mut t) => {
                if *t + dt >= wait_t {
                    *t = wait_t;
                    // Return the 'dt' that is left.
                    Some(*t + dt - wait_t)
                } else {
                    *t += dt;
                    None
                }
            },
            SequenceCursor(
                seq,
                ref mut i,
                ref mut cursor
            ) => {
                let cur = cursor;
                let mut dt = dt;
                while *i < seq.len() {
                    match cur.update(dt, |action, state| f(action, state)) {
                        None => { break },
                        Some(new_dt) => { dt = new_dt; }
                    };
                    *i += 1;
                    // If end of sequence,
                    // return the 'dt' that is left.
                    if *i >= seq.len() { return Some(dt); }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cur = seq.get(*i).to_cursor();
                }
                None
            },
            _ => unimplemented!(),
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////

/// Some test actions.
pub enum TestActions {
    /// Increment accumulator.
    Inc,
    /// Decrement accumulator.
    Dec,
}

impl StartState<()> for TestActions {
    fn start_state(&self) {}
}

fn exec(mut acc: u32, dt: f64, cursor: &mut Cursor<TestActions, ()>) -> u32 {
    cursor.update(dt, |action, _| {
        match *action {
            Inc => { acc += 1; None },
            Dec => { acc -= 1; None },
        }
    });
    acc
}

// Each action that terminates immediately
// consumes a time of 0.0 seconds.
// This makes it possible to execute one action
// after another without delay or waiting for next update.
fn print_2() {
    let a: u32 = 0;
    let seq = Sequence(vec![Action(Inc), Action(Inc)]);
    let mut cursor = seq.to_cursor();
    let a = exec(a, 0.0, &mut cursor);
    assert_eq!(a, 2);
}

// If you wait the exact amount before to execute an action,
// it will execute. This behavior makes it easy to predict
// when an action will run.
fn wait_sec() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
    let mut cursor = seq.to_cursor();
    let a = exec(a, 1.0, &mut cursor);
    assert_eq!(a, 1);
}

// When we execute half the time and then the other half,
// then the action should be executed.
fn wait_half_sec() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(1.0), Action(Inc)]);
    let mut cursor = seq.to_cursor();
    let a = exec(a, 0.5, &mut cursor);
    assert_eq!(a, 0);
    let a = exec(a, 0.5, &mut cursor);
    assert_eq!(a, 1);
}

// A sequence of wait events is the same as one wait event.
fn wait_two_waits() {
    let a: u32 = 0;
    let seq = Sequence(vec![Wait(0.5), Wait(0.5), Action(Inc)]);
    let mut cursor = seq.to_cursor();
    let a = exec(a, 1.0, &mut cursor);
    assert_eq!(a, 1);
}

fn main() {
    print_2();
    wait_sec();
    wait_half_sec();
    wait_two_waits();
}

<|endoftext|>


<commit_before>// Copyright © 2015-2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms.
//! ApiSet Contract for api-ms-win-core-libraryloader-l1

use ctypes::c_int;
use shared::basetsd::LONG_PTR;
use shared::minwindef::{
    BOOL, DWORD, FARPROC, HGLOBAL, HINSTANCE, HMODULE, HRSRC, LPVOID, UINT, WORD
};
use um::winnt::{HANDLE, LANGID, LPCSTR, LPCWSTR, LPSTR, LPWSTR, PCWSTR, PVOID};

FN!{stdcall ENUMRESLANGPROCA(
    hModule: HMODULE,
    lpType: LPCSTR,
    lpName: LPCSTR,
    wLanguage: WORD,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESLANGPROCW(
    hModule: HMODULE,
    lpType: LPCWSTR,
    lpName: LPCWSTR,
    wLanguage: WORD,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESNAMEPROCA(
    hModule: HMODULE,
    lpType: LPCSTR,
    lpName: LPSTR,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESNAMEPROCW(
    hModule: HMODULE,
    lpType: LPCWSTR,
    lpName: LPWSTR,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESTYPEPROCA(
    hModule: HMODULE,
    lpType: LPSTR,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESTYPEPROCW(
    hModule: HMODULE,
    lpType: LPWSTR,
    lParam: LONG_PTR,
) -> BOOL}
extern "system" {
    pub fn DisableThreadLibraryCalls(
        hLibModule: HMODULE,
    ) -> BOOL;
    pub fn FindResourceExW(
        hModule: HMODULE,
        lpName: LPCWSTR,
        lpType: LPCWSTR,
        wLanguage: WORD,
    ) -> HRSRC;
    pub fn FindStringOrdinal(
        dwFindStringOrdinalFlags: DWORD,
        lpStringSource: LPCWSTR,
        cchSource: c_int,
        lpStringValue: LPCWSTR,
        cchValue: c_int,
        bIgnoreCase: BOOL,
    ) -> c_int;
    pub fn FreeLibrary(
        hLibModule: HMODULE,
    ) -> BOOL;
    pub fn FreeLibraryAndExitThread(
        hLibModule: HMODULE,
        dwExitCode: DWORD,
    );
    pub fn FreeResource(
        hResData: HGLOBAL,
    ) -> BOOL;
    pub fn GetModuleFileNameA(
        hModule: HMODULE,
        lpFilename: LPSTR,
        nSize: DWORD,
    ) -> DWORD;
    pub fn GetModuleFileNameW(
        hModule: HMODULE,
        lpFilename: LPWSTR,
        nSize: DWORD,
    ) -> DWORD;
    pub fn GetModuleHandleA(
        lpModuleName: LPCSTR,
    ) -> HMODULE;
    pub fn GetModuleHandleW(
        lpModuleName: LPCWSTR,
    ) -> HMODULE;
    pub fn GetModuleHandleExA(
        dwFlags: DWORD,
        lpModuleName: LPCSTR,
        phModule: *mut HMODULE,
    ) -> BOOL;
    pub fn GetModuleHandleExW(
        dwFlags: DWORD,
        lpModuleName: LPCWSTR,
        phModule: *mut HMODULE,
    ) -> BOOL;
    pub fn GetProcAddress(
        hModule: HMODULE,
        lpProcName: LPCSTR,
    ) -> FARPROC;
    pub fn LoadLibraryExA(
        lpLibFileName: LPCSTR,
        hFile: HANDLE,
        dwFlags: DWORD,
    ) -> HMODULE;
    pub fn LoadLibraryExW(
        lpLibFileName: LPCWSTR,
        hFile: HANDLE,
        dwFlags: DWORD,
    ) -> HMODULE;
    pub fn LoadResource(
        hModule: HMODULE,
        hResInfo: HRSRC,
    ) -> HGLOBAL;
    pub fn LoadStringA(
        hInstance: HINSTANCE,
        uID: UINT,
        lpBuffer: LPSTR,
        cchBufferMax: c_int,
    ) -> c_int;
    pub fn LoadStringW(
        hInstance: HINSTANCE,
        uID: UINT,
        lpBuffer: LPWSTR,
        cchBufferMax: c_int,
    ) -> c_int;
    pub fn LockResource(
        hResData: HGLOBAL,
    ) -> LPVOID;
    pub fn SizeofResource(
        hModule: HMODULE,
        hResInfo: HRSRC,
    ) -> DWORD;
}
pub type DLL_DIRECTORY_COOKIE = PVOID;
pub type PDLL_DIRECTORY_COOKIE = *mut PVOID;
extern "system" {
    pub fn AddDllDirectory(
        NewDirectory: PCWSTR,
    ) -> DLL_DIRECTORY_COOKIE;
    pub fn RemoveDllDirectory(
        Cookie: DLL_DIRECTORY_COOKIE,
    ) -> BOOL;
    pub fn SetDefaultDllDirectories(
        DirectoryFlags: DWORD,
    ) -> BOOL;
    pub fn EnumResourceLanguagesExA(
        hModule: HMODULE,
        lpType: LPCSTR,
        lpName: LPCSTR,
        lpEnumFunc: ENUMRESLANGPROCA,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceLanguagesExW(
        hModule: HMODULE,
        lpType: LPCWSTR,
        lpName: LPCWSTR,
        lpEnumFunc: ENUMRESLANGPROCW,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceNamesExA(
        hModule: HMODULE,
        lpType: LPCSTR,
        lpEnumFunc: ENUMRESNAMEPROCA,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceNamesExW(
        hModule: HMODULE,
        lpType: LPCWSTR,
        lpEnumFunc: ENUMRESNAMEPROCW,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceTypesExA(
        hModule: HMODULE,
        lpEnumFunc: ENUMRESTYPEPROCA,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceTypesExW(
        hModule: HMODULE,
        lpEnumFunc: ENUMRESTYPEPROCW,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn FindResourceW(
        hModule: HMODULE,
        lpName: LPCWSTR,
        lpType: LPCWSTR,
    ) -> HRSRC;
    pub fn LoadLibraryA(
        lpFileName: LPCSTR,
    ) -> HMODULE;
    pub fn LoadLibraryW(
        lpFileName: LPCWSTR,
    ) -> HMODULE;
    pub fn EnumResourceNamesW(
        hModule: HMODULE,
        lpType: LPCWSTR,
        lpEnumFunc: ENUMRESNAMEPROCW,
        lParam: LONG_PTR,
    ) -> BOOL;
}
<commit_msg>Add missing constants and remove all spaces (#502)<commit_after>// Copyright © 2015-2017 winapi-rs developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// All files in the project carrying such notice may not be copied, modified, or distributed
// except according to those terms.
//! ApiSet Contract for api-ms-win-core-libraryloader-l1
use ctypes::c_int;
use shared::basetsd::LONG_PTR;
use shared::minwindef::{
    BOOL, DWORD, FARPROC, HGLOBAL, HINSTANCE, HMODULE, HRSRC, LPVOID, UINT, WORD
};
use um::winnt::{HANDLE, LANGID, LPCSTR, LPCWSTR, LPSTR, LPWSTR, PCWSTR, PVOID};
pub const GET_MODULE_HANDLE_EX_FLAG_PIN: DWORD = 0x00000001;
pub const GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT: DWORD = 0x00000002;
pub const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: DWORD = 0x00000004;
pub const DONT_RESOLVE_DLL_REFERENCES: DWORD = 0x00000001;
pub const LOAD_LIBRARY_AS_DATAFILE: DWORD = 0x00000002;
pub const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = 0x00000008;
pub const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = 0x00000010;
pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = 0x00000020;
pub const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = 0x00000040;
pub const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = 0x00000080;
pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = 0x00000100;
pub const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = 0x00000200;
pub const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = 0x00000400;
pub const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = 0x00000800;
pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = 0x00001000;
pub const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = 0x00002000;
pub const LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER: DWORD = 0x00004000;
pub const LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY: DWORD = 0x00008000;
FN!{stdcall ENUMRESLANGPROCA(
    hModule: HMODULE,
    lpType: LPCSTR,
    lpName: LPCSTR,
    wLanguage: WORD,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESLANGPROCW(
    hModule: HMODULE,
    lpType: LPCWSTR,
    lpName: LPCWSTR,
    wLanguage: WORD,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESNAMEPROCA(
    hModule: HMODULE,
    lpType: LPCSTR,
    lpName: LPSTR,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESNAMEPROCW(
    hModule: HMODULE,
    lpType: LPCWSTR,
    lpName: LPWSTR,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESTYPEPROCA(
    hModule: HMODULE,
    lpType: LPSTR,
    lParam: LONG_PTR,
) -> BOOL}
FN!{stdcall ENUMRESTYPEPROCW(
    hModule: HMODULE,
    lpType: LPWSTR,
    lParam: LONG_PTR,
) -> BOOL}
extern "system" {
    pub fn DisableThreadLibraryCalls(
        hLibModule: HMODULE,
    ) -> BOOL;
    pub fn FindResourceExW(
        hModule: HMODULE,
        lpName: LPCWSTR,
        lpType: LPCWSTR,
        wLanguage: WORD,
    ) -> HRSRC;
    pub fn FindStringOrdinal(
        dwFindStringOrdinalFlags: DWORD,
        lpStringSource: LPCWSTR,
        cchSource: c_int,
        lpStringValue: LPCWSTR,
        cchValue: c_int,
        bIgnoreCase: BOOL,
    ) -> c_int;
    pub fn FreeLibrary(
        hLibModule: HMODULE,
    ) -> BOOL;
    pub fn FreeLibraryAndExitThread(
        hLibModule: HMODULE,
        dwExitCode: DWORD,
    );
    pub fn FreeResource(
        hResData: HGLOBAL,
    ) -> BOOL;
    pub fn GetModuleFileNameA(
        hModule: HMODULE,
        lpFilename: LPSTR,
        nSize: DWORD,
    ) -> DWORD;
    pub fn GetModuleFileNameW(
        hModule: HMODULE,
        lpFilename: LPWSTR,
        nSize: DWORD,
    ) -> DWORD;
    pub fn GetModuleHandleA(
        lpModuleName: LPCSTR,
    ) -> HMODULE;
    pub fn GetModuleHandleW(
        lpModuleName: LPCWSTR,
    ) -> HMODULE;
    pub fn GetModuleHandleExA(
        dwFlags: DWORD,
        lpModuleName: LPCSTR,
        phModule: *mut HMODULE,
    ) -> BOOL;
    pub fn GetModuleHandleExW(
        dwFlags: DWORD,
        lpModuleName: LPCWSTR,
        phModule: *mut HMODULE,
    ) -> BOOL;
    pub fn GetProcAddress(
        hModule: HMODULE,
        lpProcName: LPCSTR,
    ) -> FARPROC;
    pub fn LoadLibraryExA(
        lpLibFileName: LPCSTR,
        hFile: HANDLE,
        dwFlags: DWORD,
    ) -> HMODULE;
    pub fn LoadLibraryExW(
        lpLibFileName: LPCWSTR,
        hFile: HANDLE,
        dwFlags: DWORD,
    ) -> HMODULE;
    pub fn LoadResource(
        hModule: HMODULE,
        hResInfo: HRSRC,
    ) -> HGLOBAL;
    pub fn LoadStringA(
        hInstance: HINSTANCE,
        uID: UINT,
        lpBuffer: LPSTR,
        cchBufferMax: c_int,
    ) -> c_int;
    pub fn LoadStringW(
        hInstance: HINSTANCE,
        uID: UINT,
        lpBuffer: LPWSTR,
        cchBufferMax: c_int,
    ) -> c_int;
    pub fn LockResource(
        hResData: HGLOBAL,
    ) -> LPVOID;
    pub fn SizeofResource(
        hModule: HMODULE,
        hResInfo: HRSRC,
    ) -> DWORD;
}
pub type DLL_DIRECTORY_COOKIE = PVOID;
pub type PDLL_DIRECTORY_COOKIE = *mut PVOID;
extern "system" {
    pub fn AddDllDirectory(
        NewDirectory: PCWSTR,
    ) -> DLL_DIRECTORY_COOKIE;
    pub fn RemoveDllDirectory(
        Cookie: DLL_DIRECTORY_COOKIE,
    ) -> BOOL;
    pub fn SetDefaultDllDirectories(
        DirectoryFlags: DWORD,
    ) -> BOOL;
    pub fn EnumResourceLanguagesExA(
        hModule: HMODULE,
        lpType: LPCSTR,
        lpName: LPCSTR,
        lpEnumFunc: ENUMRESLANGPROCA,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceLanguagesExW(
        hModule: HMODULE,
        lpType: LPCWSTR,
        lpName: LPCWSTR,
        lpEnumFunc: ENUMRESLANGPROCW,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceNamesExA(
        hModule: HMODULE,
        lpType: LPCSTR,
        lpEnumFunc: ENUMRESNAMEPROCA,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceNamesExW(
        hModule: HMODULE,
        lpType: LPCWSTR,
        lpEnumFunc: ENUMRESNAMEPROCW,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceTypesExA(
        hModule: HMODULE,
        lpEnumFunc: ENUMRESTYPEPROCA,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn EnumResourceTypesExW(
        hModule: HMODULE,
        lpEnumFunc: ENUMRESTYPEPROCW,
        lParam: LONG_PTR,
        dwFlags: DWORD,
        LangId: LANGID,
    ) -> BOOL;
    pub fn FindResourceW(
        hModule: HMODULE,
        lpName: LPCWSTR,
        lpType: LPCWSTR,
    ) -> HRSRC;
    pub fn LoadLibraryA(
        lpFileName: LPCSTR,
    ) -> HMODULE;
    pub fn LoadLibraryW(
        lpFileName: LPCWSTR,
    ) -> HMODULE;
    pub fn EnumResourceNamesW(
        hModule: HMODULE,
        lpType: LPCWSTR,
        lpEnumFunc: ENUMRESNAMEPROCW,
        lParam: LONG_PTR,
    ) -> BOOL;
}
<|endoftext|>


<commit_before>//! # yeild
//!
//! generator yield implmentation
//!

use std::any::Any;
use generator::Generator;
use rt::{Error, Context, ContextStack};
use reg_context::Context as RegContext;

/// switch back to parent context
#[inline]
pub fn yield_now() {
    let env = ContextStack::current();
    let mut cur = env.top();
    let sp = &cur.stack;
    // judge if this is root context
    if sp.size() > 0 {
        env.pop();
        let parent = env.top();
        RegContext::swap(&mut cur.regs, &parent.regs);
    }
}

/// raw yiled without catch passed in para
#[inline]
fn raw_yield<T: Any>(context: &mut Context, v: T) {
    // check the context
    if !context.is_generator() {
        info!("yield from none generator context");
        // do nothing, just return
        return;
        // panic!(Error::ContextErr);
    }

    context.set_ret(v);
    context._ref -= 1;
    yield_now();

    // here we just panic to exit the func
    if context._ref != 1 {
        panic!(Error::Cancel);
    }
}

/// yiled something without catch passed in para
#[inline]
pub fn yield_with<T: Any>(v: T) {
    raw_yield(ContextStack::current().top(), v);
}

/// get the passed in para
#[inline]
pub fn get_yield<A: Any>() -> Option<A> {
    let context = ContextStack::current().top();

    // check the context
    if !context.is_generator() {
        error!("get yield from none generator context");
        panic!(Error::ContextErr);
    }

    context.get_para()
}

/// yiled and get the send para
#[inline]
pub fn yield_<A: Any, T: Any>(v: T) -> Option<A> {
    let p = get_yield();
    yield_with(v);
    p
}

/// `yiled_from`
pub fn yield_from<A: Any, T: Any>(mut g: Box<Generator<A, Output = T>>) {
    let context = ContextStack::current().top();
    while !g.is_done() {
        let p = context.get_para();
        let r = g.raw_send(p).unwrap();
        raw_yield(context, r);
    }
}
<commit_msg>reduce TLS access for yield_()<commit_after>//! # yeild
//!
//! generator yield implmentation
//!

use std::any::Any;
use generator::Generator;
use rt::{Error, Context, ContextStack};
use reg_context::Context as RegContext;

/// switch back to parent context
#[inline]
pub fn yield_now() {
    let env = ContextStack::current();
    let mut cur = env.top();
    let sp = &cur.stack;
    // judge if this is root context
    if sp.size() > 0 {
        env.pop();
        let parent = env.top();
        RegContext::swap(&mut cur.regs, &parent.regs);
    }
}

/// raw yiled without catch passed in para
#[inline]
fn raw_yield<T: Any>(context: &mut Context, v: T) {
    // check the context
    if !context.is_generator() {
        info!("yield from none generator context");
        // do nothing, just return
        return;
        // panic!(Error::ContextErr);
    }

    context.set_ret(v);
    context._ref -= 1;
    yield_now();

    // here we just panic to exit the func
    if context._ref != 1 {
        panic!(Error::Cancel);
    }
}

/// yiled something without catch passed in para
#[inline]
pub fn yield_with<T: Any>(v: T) {
    raw_yield(ContextStack::current().top(), v);
}

/// get the passed in para
#[inline]
pub fn get_yield<A: Any>() -> Option<A> {
    let context = ContextStack::current().top();
    raw_get_yield(context)
}

/// get the passed in para from context
#[inline]
fn raw_get_yield<A: Any>(context: &mut Context) -> Option<A> {
    // check the context
    if !context.is_generator() {
        error!("get yield from none generator context");
        panic!(Error::ContextErr);
    }

    context.get_para()
}

/// yiled and get the send para
#[inline]
pub fn yield_<A: Any, T: Any>(v: T) -> Option<A> {
    let context = ContextStack::current().top();
    let p = raw_get_yield(context);
    raw_yield(context, v);
    p
}

/// `yiled_from`
pub fn yield_from<A: Any, T: Any>(mut g: Box<Generator<A, Output = T>>) {
    let context = ContextStack::current().top();
    while !g.is_done() {
        let p = context.get_para();
        let r = g.raw_send(p).unwrap();
        raw_yield(context, r);
    }
}
<|endoftext|>


<commit_before>extern crate pty;
extern crate libc;
extern crate errno;

use self::pty::prelude::*;

use std::ffi;

use std::io::prelude::*;
use std::process::{Command, Stdio};
use std::ptr;
use std::string::String;

#[test]
fn it_fork_with_new_pty() {
    let fork = Fork::from_ptmx().unwrap();

    if let Some(mut master) = fork.is_parent().ok() {
        let mut string = String::new();

        master.read_to_string(&mut string).unwrap_or_else(|e| panic!(e));

        let output = Command::new("tty")
            .stdin(Stdio::inherit())
            .output()
            .unwrap()
            .stdout;
        let output_str = String::from_utf8_lossy(&output);

        let parent_tty = output_str.trim();
        let child_tty = string.trim();
        println!("parent: {}, child: {}", parent_tty, child_tty);

        assert!(child_tty != "");
        assert!(child_tty != parent_tty);

        // only compare if parent is tty
        // travis runs the tests without tty
        if parent_tty != "not a tty" {
            let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
            let mut child_tty_dir: Vec<&str> = child_tty.split("/").collect();

            parent_tty_dir.pop();
            child_tty_dir.pop();

            assert_eq!(parent_tty_dir, child_tty_dir);
        }
    } else {
        let cmd = ffi::CString::new("tty").unwrap();
        let mut args: Vec<*const libc::c_char> = Vec::with_capacity(1);

        args.push(cmd.as_ptr());
        args.push(ptr::null());
        unsafe {
            if libc::execvp(cmd.as_ptr(), args.as_mut_ptr()).eq(&-1) {
                panic!("{}: {}", cmd.to_string_lossy(), self::errno::errno());
            }
        }
    }
}
<commit_msg>remove println<commit_after>extern crate pty;
extern crate libc;
extern crate errno;

use self::pty::prelude::*;

use std::ffi;

use std::io::prelude::*;
use std::process::{Command, Stdio};
use std::ptr;
use std::string::String;

#[test]
fn it_fork_with_new_pty() {
    let fork = Fork::from_ptmx().unwrap();

    if let Some(mut master) = fork.is_parent().ok() {
        let mut string = String::new();

        master.read_to_string(&mut string).unwrap_or_else(|e| panic!(e));

        let output = Command::new("tty")
            .stdin(Stdio::inherit())
            .output()
            .unwrap()
            .stdout;
        let output_str = String::from_utf8_lossy(&output);

        let parent_tty = output_str.trim();
        let child_tty = string.trim();

        assert!(child_tty != "");
        assert!(child_tty != parent_tty);

        // only compare if parent is tty
        // travis runs the tests without tty
        if parent_tty != "not a tty" {
            let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
            let mut child_tty_dir: Vec<&str> = child_tty.split("/").collect();

            parent_tty_dir.pop();
            child_tty_dir.pop();

            assert_eq!(parent_tty_dir, child_tty_dir);
        }
    } else {
        let cmd = ffi::CString::new("tty").unwrap();
        let mut args: Vec<*const libc::c_char> = Vec::with_capacity(1);

        args.push(cmd.as_ptr());
        args.push(ptr::null());
        unsafe {
            if libc::execvp(cmd.as_ptr(), args.as_mut_ptr()).eq(&-1) {
                panic!("{}: {}", cmd.to_string_lossy(), self::errno::errno());
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! An example of using simplectic noise

#![feature(macro_rules)]

extern crate noise;

use noise::{simplectic2, simplectic3, simplectic4, Seed, Point2};

mod debug {
    pub mod image;
}

fn main() {
    debug::image::render_to_png("simplectic2.png", &Seed::new(0), 1024, 1024, scaled_simplectic2);
    debug::image::render_to_png("simplectic3.png", &Seed::new(0), 1024, 1024, scaled_simplectic3);
    debug::image::render_to_png("simplectic4.png", &Seed::new(0), 1024, 1024, scaled_simplectic4);
    println!("\nGenerated simplectic2.png, simplectic3.png and simplectic4.png");
}

fn scaled_simplectic2(seed: &Seed, point: &Point2<f32>) -> f32 {
    simplectic2(seed, &[point[0] / 64.0, point[1] / 64.0])
}

fn scaled_simplectic3(seed: &Seed, point: &Point2<f32>) -> f32 {
    simplectic3(seed, &[point[0] / 64.0, point[1] / 64.0, 0.0])
}

fn scaled_simplectic4(seed: &Seed, point: &Point2<f32>) -> f32 {
    simplectic4(seed, &[point[0] / 64.0, point[1] / 64.0, 0.0, 0.0])
}
<commit_msg>Reduce the image size in the simplectic example back down to 256x256.<commit_after>// Copyright 2013 The noise-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! An example of using simplectic noise

#![feature(macro_rules)]

extern crate noise;

use noise::{simplectic2, simplectic3, simplectic4, Seed, Point2};

mod debug {
    pub mod image;
}

fn main() {
    debug::image::render_to_png("simplectic2.png", &Seed::new(0), 256, 256, scaled_simplectic2);
    debug::image::render_to_png("simplectic3.png", &Seed::new(0), 256, 256, scaled_simplectic3);
    debug::image::render_to_png("simplectic4.png", &Seed::new(0), 256, 256, scaled_simplectic4);
    println!("\nGenerated simplectic2.png, simplectic3.png and simplectic4.png");
}

fn scaled_simplectic2(seed: &Seed, point: &Point2<f32>) -> f32 {
    simplectic2(seed, &[point[0] / 64.0, point[1] / 64.0])
}

fn scaled_simplectic3(seed: &Seed, point: &Point2<f32>) -> f32 {
    simplectic3(seed, &[point[0] / 64.0, point[1] / 64.0, 0.0])
}

fn scaled_simplectic4(seed: &Seed, point: &Point2<f32>) -> f32 {
    simplectic4(seed, &[point[0] / 64.0, point[1] / 64.0, 0.0, 0.0])
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::str::from_utf8;

use mio::event::Event;
use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interests, Poll, Token};

// Setup some tokens to allow us to identify which event is for which socket.
const SERVER: Token = Token(0);

// Some data we'll send over the connection.
const DATA: &[u8] = b"Hello world!\n";

fn main() -> io::Result<()> {
    env_logger::init();

    // Create a poll instance.
    let mut poll = Poll::new()?;
    // Create storage for events.
    let mut events = Events::with_capacity(128);

    // Setup the TCP server socket.
    let addr = "127.0.0.1:13265".parse().unwrap();
    let server = TcpListener::bind(addr)?;

    // Register the server with poll we can receive events for it.
    poll.registry()
        .register(&server, SERVER, Interests::READABLE)?;

    // Map of `Token` -> `TcpStream`.
    let mut connections = HashMap::new();
    // Unique token for each incoming connection.
    let mut unique_token = Token(SERVER.0 + 1);

    println!("You can connect to the server using `nc`:");
    println!(" $ nc 127.0.0.1 13265");
    println!("You'll see our welcome message and anything you type we'll be printed here.");

    loop {
        poll.poll(&mut events, None)?;

        for event in events.iter() {
            match event.token() {
                SERVER => {
                    // Received an event for the TCP server socket.
                    // Accept an connection.
                    let (connection, address) = server.accept()?;
                    println!("Accepted connection from: {}", address);

                    let token = next(&mut unique_token);
                    poll.registry().register(
                        &connection,
                        token,
                        Interests::READABLE.add(Interests::WRITABLE),
                    )?;

                    connections.insert(token, connection);
                }
                token => {
                    // (maybe) received an event for a TCP connection.
                    let done = if let Some(connection) = connections.get_mut(&token) {
                        handle_connection_event(&mut poll, connection, event)?
                    } else {
                        // Sporadic events happen.
                        false
                    };
                    if done {
                        connections.remove(&token);
                    }
                }
            }
        }
    }
}

fn next(current: &mut Token) -> Token {
    let next = current.0;
    current.0 += 1;
    Token(next)
}

/// Returns `true` if the connection is done.
fn handle_connection_event(
    poll: &mut Poll,
    connection: &mut TcpStream,
    event: &Event,
) -> io::Result<bool> {
    if event.is_writable() {
        // We can (maybe) write to the connection.
        match connection.write(DATA) {
            // We want to write the entire `DATA` buffer in a single go. If we
            // write less we'll return a short write error (same as
            // `io::Write::write_all` does).
            Ok(n) if n < DATA.len() => return Err(io::ErrorKind::WriteZero.into()),
            Ok(_) => {
                // After we've written something we'll reregister the connection
                // to only respond to readable events.
                poll.registry()
                    .reregister(&connection, event.token(), Interests::READABLE)?
            }
            // Would block "errors" are the OS's way of saying that the
            // connection is not actually ready to perform this I/O operation.
            Err(ref err) if would_block(err) => {}
            // Got interrupted (how rude!), we'll try again.
            Err(ref err) if interrupted(err) => {
                return handle_connection_event(poll, connection, event)
            }
            // Other errors we'll consider fatal.
            Err(err) => return Err(err),
        }
    }

    if event.is_readable() {
        let mut connection_closed = false;
        let mut received_data = Vec::with_capacity(4096);
        // We can (maybe) read from the connection.
        loop {
            let mut buf = [0; 256];
            match connection.read(&mut buf) {
                Ok(0) => {
                    // Reading 0 bytes means the other side has closed the
                    // connection or is done writing, then so are we.
                    connection_closed = true;
                    break;
                }
                Ok(n) => received_data.extend_from_slice(&buf[..n]),
                // Would block "errors" are the OS's way of saying that the
                // connection is not actually ready to perform this I/O operation.
                Err(ref err) if would_block(err) => break,
                Err(ref err) if interrupted(err) => continue,
                // Other errors we'll consider fatal.
                Err(err) => return Err(err),
            }
        }

        if let Ok(str_buf) = from_utf8(&received_data) {
            println!("Received data: {}", str_buf.trim_end());
        } else {
            println!("Received (none UTF-8) data: {:?}", &received_data);
        }

        if connection_closed {
            println!("Connection closed");
            return Ok(true);
        }
    }

    Ok(false)
}

fn would_block(err: &io::Error) -> bool {
    err.kind() == io::ErrorKind::WouldBlock
}

fn interrupted(err: &io::Error) -> bool {
    err.kind() == io::ErrorKind::Interrupted
}
<commit_msg>handle_connection_event just needs access to the Registry<commit_after>use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::str::from_utf8;

use mio::event::Event;
use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interests, Poll, Registry, Token};

// Setup some tokens to allow us to identify which event is for which socket.
const SERVER: Token = Token(0);

// Some data we'll send over the connection.
const DATA: &[u8] = b"Hello world!\n";

fn main() -> io::Result<()> {
    // Create a poll instance.
    let mut poll = Poll::new()?;
    // Create storage for events.
    let mut events = Events::with_capacity(128);

    // Setup the TCP server socket.
    let addr = "127.0.0.1:13265".parse().unwrap();
    let server = TcpListener::bind(addr)?;

    // Register the server with poll we can receive events for it.
    poll.registry()
        .register(&server, SERVER, Interests::READABLE)?;

    // Map of `Token` -> `TcpStream`.
    let mut connections = HashMap::new();
    // Unique token for each incoming connection.
    let mut unique_token = Token(SERVER.0 + 1);

    println!("You can connect to the server using `nc`:");
    println!(" $ nc 127.0.0.1 13265");
    println!("You'll see our welcome message and anything you type we'll be printed here.");

    loop {
        poll.poll(&mut events, None)?;

        for event in events.iter() {
            match event.token() {
                SERVER => {
                    // Received an event for the TCP server socket.
                    // Accept an connection.
                    let (connection, address) = server.accept()?;
                    println!("Accepted connection from: {}", address);

                    let token = next(&mut unique_token);
                    poll.registry().register(
                        &connection,
                        token,
                        Interests::READABLE.add(Interests::WRITABLE),
                    )?;

                    connections.insert(token, connection);
                }
                token => {
                    // (maybe) received an event for a TCP connection.
                    let done = if let Some(connection) = connections.get_mut(&token) {
                        handle_connection_event(poll.registry(), connection, event)?
                    } else {
                        // Sporadic events happen.
                        false
                    };
                    if done {
                        connections.remove(&token);
                    }
                }
            }
        }
    }
}

fn next(current: &mut Token) -> Token {
    let next = current.0;
    current.0 += 1;
    Token(next)
}

/// Returns `true` if the connection is done.
fn handle_connection_event(
    registry: &Registry,
    connection: &mut TcpStream,
    event: &Event,
) -> io::Result<bool> {
    if event.is_writable() {
        // We can (maybe) write to the connection.
        match connection.write(DATA) {
            // We want to write the entire `DATA` buffer in a single go. If we
            // write less we'll return a short write error (same as
            // `io::Write::write_all` does).
            Ok(n) if n < DATA.len() => return Err(io::ErrorKind::WriteZero.into()),
            Ok(_) => {
                // After we've written something we'll reregister the connection
                // to only respond to readable events.
                registry
                    .reregister(&connection, event.token(), Interests::READABLE)?
            }
            // Would block "errors" are the OS's way of saying that the
            // connection is not actually ready to perform this I/O operation.
            Err(ref err) if would_block(err) => {}
            // Got interrupted (how rude!), we'll try again.
            Err(ref err) if interrupted(err) => {
                return handle_connection_event(registry, connection, event)
            }
            // Other errors we'll consider fatal.
            Err(err) => return Err(err),
        }
    }

    if event.is_readable() {
        let mut connection_closed = false;
        let mut received_data = Vec::with_capacity(4096);
        // We can (maybe) read from the connection.
        loop {
            let mut buf = [0; 256];
            match connection.read(&mut buf) {
                Ok(0) => {
                    // Reading 0 bytes means the other side has closed the
                    // connection or is done writing, then so are we.
                    connection_closed = true;
                    break;
                }
                Ok(n) => received_data.extend_from_slice(&buf[..n]),
                // Would block "errors" are the OS's way of saying that the
                // connection is not actually ready to perform this I/O operation.
                Err(ref err) if would_block(err) => break,
                Err(ref err) if interrupted(err) => continue,
                // Other errors we'll consider fatal.
                Err(err) => return Err(err),
            }
        }

        if let Ok(str_buf) = from_utf8(&received_data) {
            println!("Received data: {}", str_buf.trim_end());
        } else {
            println!("Received (none UTF-8) data: {:?}", &received_data);
        }

        if connection_closed {
            println!("Connection closed");
            return Ok(true);
        }
    }

    Ok(false)
}

fn would_block(err: &io::Error) -> bool {
    err.kind() == io::ErrorKind::WouldBlock
}

fn interrupted(err: &io::Error) -> bool {
    err.kind() == io::ErrorKind::Interrupted
}
<|endoftext|>


<commit_before>const ADD_XY: u8 = 0x8; // constant for addition

struct CPU {
    current_operation: u16,
    registers: [u8; 2],
}

impl CPU {
    fn run(&mut self) {
        let enocded_op = self.current_operation;
        let op = ((enocded_op & 0xF000) >> 12) as u8; // assign each bit field to own
        let x  = ((enocded_op & 0x0F00) >>  8) as u8; // variable
        let y  = ((enocded_op & 0x00F0) >>  4) as u8; // variable

        match op {
            ADD_XY => {
                self.add_xy(x,y);
            },
            _ => unimplemented!(),
        }
    }

    fn add_xy(&mut self, x: u8, y: u8) {
        self.registers[x as usize] += self.registers[y as usize];
    }
}

fn main() {
    let mut cpu = CPU {
        current_operation: 0x8014,
        registers: [0; 2],
    };

    cpu.registers[0] = 5;
    cpu.registers[1] = 10;

    cpu.run();

    assert_eq!(cpu.registers[0], 15);

    println!("5 + 10 = {}", cpu.registers[0]);
}

<commit_msg>updated to perform a number of commands as written in memory<commit_after>const ARITHMETIC_AND_LOGIC: u8 = 0x8;
const HALT: u8 = 0x0;
const ADD_XY: u8 = 0x4; // constant for addition

struct CPU {
    // current_operation: u16,
    registers: [u8; 16],
    position_in_memory: usize,
    memory: [u8; 4096],
}

impl CPU {
    fn run(&mut self) {
        loop {
            let op_byte1 = self.memory[self.position_in_memory] as u16;
            let op_byte2 = self.memory[self.position_in_memory + 1] as u16;
            let raw_op = op_byte1 << 8 | op_byte2;

            let op_major = ((raw_op & 0xF000) >> 12) as u8;
            let x        = ((raw_op & 0x0F00) >>  8) as u8;
            let y        = ((raw_op & 0x00F0) >>  4) as u8;
            let op_minor = ((raw_op & 0x000F))       as u8;

            self.position_in_memory += 2;

            match (op_major, op_minor) {
                (HALT, HALT) => { return; },
                (ARITHMETIC_AND_LOGIC, ADD_XY) => self.add_xy(x, y),
                _ => unimplemented!(),
            }
        }
    }

    fn add_xy(&mut self, x: u8, y: u8) {
        self.registers[x as usize] += self.registers[y as usize];
    }
}

fn main() {
    let mut cpu = CPU {
        registers: [0; 16],
        memory: [0; 4096],
        position_in_memory: 0,
    };

    cpu.registers[0] = 5;
    cpu.registers[1] = 10;
    cpu.registers[2] = 10;
    cpu.registers[3] = 10;

    cpu.memory[0] = 0x80; cpu.memory[1] = 0x14; // 0x8014 = add reg1 to reg0
    cpu.memory[2] = 0x80; cpu.memory[3] = 0x24; // 0x8024 = add reg2 to reg0
    cpu.memory[4] = 0x80; cpu.memory[5] = 0x34; // 0x8034 = add reg3 to reg0

    cpu.run();

    assert_eq!(cpu.registers[0], 35);

    println!("5 + 10 + 10 + 10 = {}", cpu.registers[0]);
}

<|endoftext|>


<commit_before>use std::fmt;
pub use self::DecodeError::*;

const BASE: u64 = 62;
const ALPHABET: [u8; BASE as usize] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9',
                                       b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J',
                                       b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T',
                                       b'U', b'V', b'W', b'X', b'Y', b'Z', b'a', b'b', b'c', b'd',
                                       b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n',
                                       b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x',
                                       b'y', b'z'];

pub fn encode(mut num: u64) -> String {
    if num == 0 {
        return "0".to_owned();
    }
    let mut bytes = Vec::new();

    while num > 0 {
        bytes.push(ALPHABET[(num % BASE) as usize]);
        num /= BASE
    }
    bytes.reverse();

    String::from_utf8(bytes).unwrap()
}

pub enum DecodeError {
    InvalidBase62Byte(char, usize),
    ArithmeticOverflow,
}

impl fmt::Debug for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase62Byte(ch, idx) => {
                write!(f, "Invalid character '{}' at position {}", ch, idx)
            }
            ArithmeticOverflow => write!(f, "Decode result is too large"),
        }
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self, f)
    }
}

pub fn decode(string: &str) -> Result<u64, DecodeError> {
    let mut result = 0;

    for (i, c) in string.as_bytes().iter().rev().enumerate() {
        let num = BASE.pow(i as u32);
        match ALPHABET.binary_search(c) {
            Ok(v) => {
                match (v as u64).checked_mul(num) {
                    Some(z) => result += z,
                    None => return Err(ArithmeticOverflow),
                }
            }
            Err(_e) => {
                return Err(InvalidBase62Byte(c.to_owned() as char, string.len() - i));
            }
        }
    }

    Ok(result)
}

#[cfg(test)]
mod tests {
    use base62;

    #[test]
    fn test_encode() {
        assert_eq!(base62::encode(852751187393), "F0ob4rZ");
    }

    #[test]
    fn test_decode() {
        assert_eq!(base62::decode("F0ob4rZ").unwrap(), 852751187393);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert!(base62::decode("ds{Z455f").is_err());
    }

    #[test]
    fn test_decode_long_string() {
        assert!(base62::decode("dsZ455fzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz\
                                zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")
                    .is_err());
    }
}
<commit_msg>dont overflow on pow<commit_after>use std::fmt;
pub use self::DecodeError::*;

const BASE: u64 = 62;
const ALPHABET: [u8; BASE as usize] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9',
                                       b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J',
                                       b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T',
                                       b'U', b'V', b'W', b'X', b'Y', b'Z', b'a', b'b', b'c', b'd',
                                       b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n',
                                       b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x',
                                       b'y', b'z'];

pub fn encode(mut num: u64) -> String {
    if num == 0 {
        return "0".to_owned();
    }
    let mut bytes = Vec::new();

    while num > 0 {
        bytes.push(ALPHABET[(num % BASE) as usize]);
        num /= BASE
    }
    bytes.reverse();

    String::from_utf8(bytes).unwrap()
}

pub enum DecodeError {
    InvalidBase62Byte(char, usize),
    ArithmeticOverflow,
}

impl fmt::Debug for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase62Byte(ch, idx) => {
                write!(f, "Invalid character '{}' at position {}", ch, idx)
            }
            ArithmeticOverflow => write!(f, "Decode result is too large"),
        }
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self, f)
    }
}

pub fn decode(string: &str) -> Result<u64, DecodeError> {
    let mut result = 0;

    for (i, c) in string.as_bytes().iter().rev().enumerate() {
        let num = BASE.checked_pow(i as u32).ok_or(ArithmeticOverflow)?;
        match ALPHABET.binary_search(c) {
            Ok(v) => {
                match (v as u64).checked_mul(num) {
                    Some(z) => result += z,
                    None => return Err(ArithmeticOverflow),
                }
            }
            Err(_e) => {
                return Err(InvalidBase62Byte(c.to_owned() as char, string.len() - i));
            }
        }
    }

    Ok(result)
}

#[cfg(test)]
mod tests {
    use base62;

    #[test]
    fn test_encode() {
        assert_eq!(base62::encode(852751187393), "F0ob4rZ");
    }

    #[test]
    fn test_decode() {
        assert_eq!(base62::decode("F0ob4rZ").unwrap(), 852751187393);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert!(base62::decode("ds{Z455f").is_err());
    }

    #[test]
    fn test_decode_long_string() {
        assert!(base62::decode("dsZ455fzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz\
                                zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")
                    .is_err());
    }
}
<|endoftext|>


<commit_before>#![feature(hashmap_hasher)]

extern crate rand;
extern crate time;
extern crate getopts;
extern crate timely;
extern crate graph_map;
extern crate differential_dataflow;

use std::collections::HashMap;
use std::collections::hash_state::DefaultState;
use std::hash::{Hash, SipHasher, Hasher};

fn hash_me<T: Hash>(x: &T) -> u64 {
    let mut h = SipHasher::new();
    x.hash(&mut h);
    h.finish()
}

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::collection_trace::hash_index::HashIndex;

fn main() {
    for i in 25..26 {
        test_index(i);
    }
}

fn test_index(log_size: usize) {

    let default_state: DefaultState<SipHasher> = Default::default();
    let mut hash = HashMap::with_capacity_and_hash_state(1 << log_size, default_state);
    let mut hash_index = HashIndex::<(u64, (u64, u64)), (u64, u64), _>::new(|x| x.0);
    let mut hash_index2 = HashIndex::<(u64, u64), (u64, u64), _>::new(|x| x.0 ^ x.1);

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let start = time::precise_time_ns();
    for i in 0u64..(1 << log_size) {
        hash.insert((i,i),(i,i));
    }

    println!("loaded hash_map 2^{}:\t{:.2e} ns; capacity: {}", log_size, (time::precise_time_ns() - start) as f64, hash.capacity());

    let start = time::precise_time_ns();
    for _ in 0u64..(1 << log_size) {
        let key = (rng.next_u64(), rng.next_u64());
        hash_index.entry_or_insert((key.0 ^ key.1, key), || key);
    }

    println!("loaded hash_index 2^{}:\t{:.2e} ns; capacity: {}", log_size, (time::precise_time_ns() - start) as f64, hash_index.capacity());

    let start = time::precise_time_ns();
    for _ in 0u64..(1 << log_size) {
        let key = (rng.next_u64(), rng.next_u64());
        hash_index2.entry_or_insert(key, || key);
    }

    println!("loaded hash_index 3^{}:\t{:.2e} ns; capacity: {}", log_size, (time::precise_time_ns() - start) as f64, hash_index.capacity());

    for query in 0..log_size {

        let mut hash1_tally = 0;
        let mut hash2_tally = 0;
        let mut hash3_tally = 0;

        for _ in 0..10 {
            let mut vec = vec![];

            for _ in 0..(1 << query) {
                let key = (rng.next_u64(), rng.next_u64());
                vec.push((hash_me(&key), key));
            }

            // vec.sort_by(|x,y| (x.0 & ((1 << (log_size + 1)) - 1)).cmp(&(y.0 & ((1 << (log_size + 1)) - 1))));
            let start = time::precise_time_ns();
            for i in vec.iter() {
                assert!(hash.get(&i.1).is_none());
            }
            hash1_tally += time::precise_time_ns() - start;

            // vec.sort_by(|x,y| ((x.1).0 ^ (x.1).1).cmp(&((y.1).0 ^ (y.1).1)));
            let start = time::precise_time_ns();
            for i in vec.iter() {
                assert!(hash_index.get_ref(&((i.1).0 ^ (i.1).1, i.1)).is_none());
            }
            hash2_tally += time::precise_time_ns() - start;

            let start = time::precise_time_ns();
            for i in vec.iter() {
                assert!(hash_index2.get_ref(&i.1).is_none());
            }
            hash3_tally += time::precise_time_ns() - start;
            vec.clear();
        }

        println!("\t2^{}:\t{}\t{}\t{}", query, (hash1_tally / 10) >> query, (hash2_tally / 10) >> query, (hash3_tally / 10) >> query);

    }
}
<commit_msg>tweaked example for stability<commit_after>// #![feature(hashmap_hasher)]

extern crate rand;
extern crate time;
extern crate getopts;
extern crate timely;
extern crate graph_map;
extern crate differential_dataflow;

// use std::collections::HashMap;
// use std::collections::hash_state::DefaultState;
use std::hash::{Hash, SipHasher, Hasher};

fn hash_me<T: Hash>(x: &T) -> u64 {
    let mut h = SipHasher::new();
    x.hash(&mut h);
    h.finish()
}

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::collection_trace::hash_index::HashIndex;

fn main() {
    for i in 25..26 {
        test_index(i);
    }
}

fn test_index(log_size: usize) {

    // let default_state: DefaultState<SipHasher> = Default::default();
    // let mut hash = HashMap::with_capacity_and_hash_state(1 << log_size, default_state);
    let mut hash_index = HashIndex::<(u64, (u64, u64)), (u64, u64), _>::new(|x| x.0);
    let mut hash_index2 = HashIndex::<(u64, u64), (u64, u64), _>::new(|x| x.0 ^ x.1);

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    // let start = time::precise_time_ns();
    // for i in 0u64..(1 << log_size) {
    //     hash.insert((i,i),(i,i));
    // }
    //
    // println!("loaded hash_map 2^{}:\t{:.2e} ns; capacity: {}", log_size, (time::precise_time_ns() - start) as f64, hash.capacity());

    let start = time::precise_time_ns();
    for _ in 0u64..(1 << log_size) {
        let key = (rng.next_u64(), rng.next_u64());
        hash_index.entry_or_insert((key.0 ^ key.1, key), || key);
    }

    println!("loaded hash_index 2^{}:\t{:.2e} ns; capacity: {}", log_size, (time::precise_time_ns() - start) as f64, hash_index.capacity());

    let start = time::precise_time_ns();
    for _ in 0u64..(1 << log_size) {
        let key = (rng.next_u64(), rng.next_u64());
        hash_index2.entry_or_insert(key, || key);
    }

    println!("loaded hash_index 3^{}:\t{:.2e} ns; capacity: {}", log_size, (time::precise_time_ns() - start) as f64, hash_index.capacity());

    for query in 0..log_size {

        // let mut hash1_tally = 0;
        let mut hash2_tally = 0;
        let mut hash3_tally = 0;

        for _ in 0..10 {
            let mut vec = vec![];

            for _ in 0..(1 << query) {
                let key = (rng.next_u64(), rng.next_u64());
                vec.push((hash_me(&key), key));
            }

            // // vec.sort_by(|x,y| (x.0 & ((1 << (log_size + 1)) - 1)).cmp(&(y.0 & ((1 << (log_size + 1)) - 1))));
            // let start = time::precise_time_ns();
            // for i in vec.iter() {
            //     assert!(hash.get(&i.1).is_none());
            // }
            // hash1_tally += time::precise_time_ns() - start;

            // vec.sort_by(|x,y| ((x.1).0 ^ (x.1).1).cmp(&((y.1).0 ^ (y.1).1)));
            let start = time::precise_time_ns();
            for i in vec.iter() {
                assert!(hash_index.get_ref(&((i.1).0 ^ (i.1).1, i.1)).is_none());
            }
            hash2_tally += time::precise_time_ns() - start;

            let start = time::precise_time_ns();
            for i in vec.iter() {
                assert!(hash_index2.get_ref(&i.1).is_none());
            }
            hash3_tally += time::precise_time_ns() - start;
            vec.clear();
        }

        println!("\t2^{}:\t{}\t{}\t{}", query, "STABILITY BOO", (hash2_tally / 10) >> query, (hash3_tally / 10) >> query);

    }
}
<|endoftext|>


<commit_before>use std::ptr::null;
use libc::{c_char, c_int, c_double};
use std::ffi::CString;
use utils::_string;
use vector::{ogr, geom};
use GdalError;

pub struct Geometry {
    c_geometry: *const (),
}

impl Geometry {
    pub fn empty(wkb_type: c_int) -> Geometry {
        let c_geom = unsafe { ogr::OGR_G_CreateGeometry(wkb_type) };
        assert!(c_geom != null());
        return Geometry{c_geometry: c_geom};
    }

    pub fn from_wkt(wkt: &str) -> Geometry {
        let c_wkt = CString::new(wkt.as_bytes()).unwrap();
        let mut c_wkt_ptr: *const c_char = c_wkt.as_ptr();
        let mut c_geom: *const () = null();
        let rv = unsafe { ogr::OGR_G_CreateFromWkt(&mut c_wkt_ptr, null(), &mut c_geom) };
        assert_eq!(rv, ogr::OGRERR_NONE);
        return Geometry{c_geometry: c_geom};
    }

    pub fn bbox(w: f64, s: f64, e: f64, n: f64) -> Geometry {
        Geometry::from_wkt(format!(
            "POLYGON (({} {}, {} {}, {} {}, {} {}, {} {}))",
            w, n,
            e, n,
            e, s,
            w, s,
            w, n,
        ).as_str())
    }

    pub fn json(&self) -> String {
        let c_json = unsafe { ogr::OGR_G_ExportToJson(self.c_geometry) };
        let rv = _string(c_json);
        unsafe { ogr::VSIFree(c_json as *mut ()) };
        return rv;
    }

    pub fn wkt(&self) -> String {
        let mut c_wkt: *const c_char = null();
        let _err = unsafe { ogr::OGR_G_ExportToWkt(self.c_geometry, &mut c_wkt) };
        assert_eq!(_err, ogr::OGRERR_NONE);
        let wkt = _string(c_wkt);
        unsafe { ogr::OGRFree(c_wkt as *mut ()) };
        return wkt;
    }

    pub unsafe fn c_geometry(&self) -> *const () {
        return self.c_geometry;
    }

    pub fn set_point_2d(&mut self, i: isize, p: (f64, f64)) {
        let (x, y) = p;
        unsafe { ogr::OGR_G_SetPoint_2D(
            self.c_geometry,
            i as c_int,
            x as c_double,
            y as c_double,
        ) };
    }

    pub fn get_point(&self, i: isize) -> (f64, f64, f64) {
        let mut x: c_double = 0.;
        let mut y: c_double = 0.;
        let mut z: c_double = 0.;
        unsafe { ogr::OGR_G_GetPoint(self.c_geometry, 0, &mut x, &mut y, &mut z) };
        return (x as f64, y as f64, z as f64);
    }

    pub fn to_geom(&self) -> Result<geom::Geom, GdalError> {
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(self.c_geometry) };
        match geometry_type {
            1 => {
                let (x, y, _) = self.get_point(0);
                Ok(geom::Geom::Point(geom::Point{x: x, y: y}))
            },
            _ => Err(GdalError{desc: "Unknown geometry type"})
        }
    }
}

impl Drop for Geometry {
    fn drop(&mut self) {
        unsafe { ogr::OGR_G_DestroyGeometry(self.c_geometry as *mut ()) };
    }
}

pub trait ToGdal {
    fn to_gdal(&self) -> Geometry;
}

impl ToGdal for geom::Point {
    fn to_gdal(&self) -> Geometry {
        let mut geom = Geometry::empty(ogr::WKB_POINT);
        geom.set_point_2d(0, (self.x, self.y));
        return geom;
    }
}

#[cfg(test)]
mod tests {
    use vector::{Geometry, ToGdal};
    use vector::geom::{Geom, Point};

    #[test]
    fn test_ogr_to_point() {
        let g = Geometry::from_wkt("POINT (10 20)");
        assert_eq!(g.to_geom(), Ok(Geom::Point(Point{x: 10., y: 20.})));
    }

    #[test]
    fn test_point_to_ogr() {
        let g = Point{x: 10., y: 20.}.to_gdal();
        assert_eq!(g.wkt(), "POINT (10 20)");
    }
}
<commit_msg>use argument of get_point<commit_after>use std::ptr::null;
use libc::{c_char, c_int, c_double};
use std::ffi::CString;
use utils::_string;
use vector::{ogr, geom};
use GdalError;

pub struct Geometry {
    c_geometry: *const (),
}

impl Geometry {
    pub fn empty(wkb_type: c_int) -> Geometry {
        let c_geom = unsafe { ogr::OGR_G_CreateGeometry(wkb_type) };
        assert!(c_geom != null());
        return Geometry{c_geometry: c_geom};
    }

    pub fn from_wkt(wkt: &str) -> Geometry {
        let c_wkt = CString::new(wkt.as_bytes()).unwrap();
        let mut c_wkt_ptr: *const c_char = c_wkt.as_ptr();
        let mut c_geom: *const () = null();
        let rv = unsafe { ogr::OGR_G_CreateFromWkt(&mut c_wkt_ptr, null(), &mut c_geom) };
        assert_eq!(rv, ogr::OGRERR_NONE);
        return Geometry{c_geometry: c_geom};
    }

    pub fn bbox(w: f64, s: f64, e: f64, n: f64) -> Geometry {
        Geometry::from_wkt(format!(
            "POLYGON (({} {}, {} {}, {} {}, {} {}, {} {}))",
            w, n,
            e, n,
            e, s,
            w, s,
            w, n,
        ).as_str())
    }

    pub fn json(&self) -> String {
        let c_json = unsafe { ogr::OGR_G_ExportToJson(self.c_geometry) };
        let rv = _string(c_json);
        unsafe { ogr::VSIFree(c_json as *mut ()) };
        return rv;
    }

    pub fn wkt(&self) -> String {
        let mut c_wkt: *const c_char = null();
        let _err = unsafe { ogr::OGR_G_ExportToWkt(self.c_geometry, &mut c_wkt) };
        assert_eq!(_err, ogr::OGRERR_NONE);
        let wkt = _string(c_wkt);
        unsafe { ogr::OGRFree(c_wkt as *mut ()) };
        return wkt;
    }

    pub unsafe fn c_geometry(&self) -> *const () {
        return self.c_geometry;
    }

    pub fn set_point_2d(&mut self, i: i32, p: (f64, f64)) {
        let (x, y) = p;
        unsafe { ogr::OGR_G_SetPoint_2D(
            self.c_geometry,
            i as c_int,
            x as c_double,
            y as c_double,
        ) };
    }

    pub fn get_point(&self, i: i32) -> (f64, f64, f64) {
        let mut x: c_double = 0.;
        let mut y: c_double = 0.;
        let mut z: c_double = 0.;
        unsafe { ogr::OGR_G_GetPoint(self.c_geometry, i, &mut x, &mut y, &mut z) };
        return (x as f64, y as f64, z as f64);
    }

    pub fn to_geom(&self) -> Result<geom::Geom, GdalError> {
        let geometry_type = unsafe { ogr::OGR_G_GetGeometryType(self.c_geometry) };
        match geometry_type {
            1 => {
                let (x, y, _) = self.get_point(0);
                Ok(geom::Geom::Point(geom::Point{x: x, y: y}))
            },
            _ => Err(GdalError{desc: "Unknown geometry type"})
        }
    }
}

impl Drop for Geometry {
    fn drop(&mut self) {
        unsafe { ogr::OGR_G_DestroyGeometry(self.c_geometry as *mut ()) };
    }
}

pub trait ToGdal {
    fn to_gdal(&self) -> Geometry;
}

impl ToGdal for geom::Point {
    fn to_gdal(&self) -> Geometry {
        let mut geom = Geometry::empty(ogr::WKB_POINT);
        geom.set_point_2d(0, (self.x, self.y));
        return geom;
    }
}

#[cfg(test)]
mod tests {
    use vector::{Geometry, ToGdal};
    use vector::geom::{Geom, Point};

    #[test]
    fn test_ogr_to_point() {
        let g = Geometry::from_wkt("POINT (10 20)");
        assert_eq!(g.to_geom(), Ok(Geom::Point(Point{x: 10., y: 20.})));
    }

    #[test]
    fn test_point_to_ogr() {
        let g = Point{x: 10., y: 20.}.to_gdal();
        assert_eq!(g.wkt(), "POINT (10 20)");
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::io::Write;
use std::net::SocketAddr;
use std::net::TcpStream;

use bufstream::BufStream;
use capnp::{serialize, MessageReader, ReaderOptions};

use messages_capnp::{client_response, proposal_response};
use messages;
use Result;

pub struct Client {
    leader_connection: Option<BufStream<TcpStream>>,
    cluster: HashSet<SocketAddr>,
}

impl Client {

    /// Creates a new client.
    pub fn new(cluster: HashSet<SocketAddr>) -> Client {
        Client {
            leader_connection: None,
            cluster: cluster,
        }
    }

    /// Proposes an entry to be appended to the replicated log. This will only
    /// return once the entry has been durably committed.
    pub fn propose(&mut self, entry: &[u8]) -> Result<()> {
        let mut message = messages::proposal_request(entry);

        let mut members = self.cluster.iter().cloned().cycle();

        loop {
            let mut connection = match self.leader_connection.take() {
                Some(cxn) => cxn,
                None => {
                    let leader = members.next().unwrap();
                    debug!("connecting to potential leader {}", leader);
                    BufStream::new(try!(TcpStream::connect(leader)))
                }
            };

            try!(serialize::write_message(&mut connection, &mut message));
            try!(connection.flush());
            let response = try!(serialize::read_message(&mut connection, ReaderOptions::new()));

            match try!(response.get_root::<client_response::Reader>()).which().unwrap() {
                client_response::Which::Proposal(Ok(response)) => {
                    match response.which().unwrap() {
                        proposal_response::Which::Success(()) => {
                            self.leader_connection = Some(connection);
                            return Ok(())
                        },
                        proposal_response::Which::UnknownLeader(()) => (),
                        proposal_response::Which::NotLeader(leader) => {
                            let connection: TcpStream = try!(TcpStream::connect(try!(leader)));
                            self.leader_connection = Some(BufStream::new(connection));
                        }
                    }
                },
                _ => panic!("Unexpected message type"), // TODO: return a proper error
            }
        }
    }
}
<commit_msg>More documentation on<commit_after>use std::collections::HashSet;
use std::io::Write;
use std::net::SocketAddr;
use std::net::TcpStream;

use bufstream::BufStream;
use capnp::{serialize, MessageReader, ReaderOptions};

use messages_capnp::{client_response, proposal_response};
use messages;
use Result;

/// The representation of a Client connection to the cluster.
pub struct Client {
    /// The current connection to the current leader.
    /// If it is none it may mean that there is no estabished leader or that there has been
    /// a disconnection.
    leader_connection: Option<BufStream<TcpStream>>,
    /// A lookup for the cluster's nodes.
    cluster: HashSet<SocketAddr>,
}

impl Client {

    /// Creates a new client.
    pub fn new(cluster: HashSet<SocketAddr>) -> Client {
        Client {
            leader_connection: None,
            cluster: cluster,
        }
    }

    /// Proposes an entry to be appended to the replicated log. This will only
    /// return once the entry has been durably committed.
    pub fn propose(&mut self, entry: &[u8]) -> Result<()> {
        let mut message = messages::proposal_request(entry);

        let mut members = self.cluster.iter().cloned().cycle();

        loop {
            let mut connection = match self.leader_connection.take() {
                Some(cxn) => cxn,
                None => {
                    let leader = members.next().unwrap();
                    debug!("connecting to potential leader {}", leader);
                    BufStream::new(try!(TcpStream::connect(leader)))
                }
            };

            try!(serialize::write_message(&mut connection, &mut message));
            try!(connection.flush());
            let response = try!(serialize::read_message(&mut connection, ReaderOptions::new()));

            match try!(response.get_root::<client_response::Reader>()).which().unwrap() {
                client_response::Which::Proposal(Ok(response)) => {
                    match response.which().unwrap() {
                        proposal_response::Which::Success(()) => {
                            self.leader_connection = Some(connection);
                            return Ok(())
                        },
                        proposal_response::Which::UnknownLeader(()) => (),
                        proposal_response::Which::NotLeader(leader) => {
                            let connection: TcpStream = try!(TcpStream::connect(try!(leader)));
                            self.leader_connection = Some(BufStream::new(connection));
                        }
                    }
                },
                _ => panic!("Unexpected message type"), // TODO: return a proper error
            }
        }
    }
}
<|endoftext|>