<commit_before>use rand::{thread_rng, Rng};
use std::fmt;

///
/// Abstraction for a single Entry for our log.
///
#[derive(Clone)]
pub struct Entry {
    pub index: usize,   // index of this Entry in the log
    pub term: u64,      // term for which this Entry is committed
    pub data: Vec<u8>,  // data blob containing client-defined command to
                        // apply to the client state machine.
}

impl fmt::Debug for Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Entry {{ term: {}, data: {:?} }}", self.term, self.data)
    }
}

impl PartialEq for Entry {
    fn eq(&self, other: &Entry) -> bool {
        self.term == other.term && self.data == other.data
    }
}

impl Entry {
    ///
    /// Creates a dummy Entry (for testing!) with random data.
    /// TODO (sydli): Could I have Entry implement like a random trait or something?
    ///
    pub fn random () -> Entry {
        let mut vec = vec![0; 8];
        thread_rng().fill_bytes(&mut vec);
        Entry {
            index: 0, // TODO (sydli) this should not be 0
            term: 0,  // Unneeded, for testing, for now.
            data: vec,
        }
    }
}

///
/// Abstraction for a log of "commands" to apply to the client state machine,
/// stored locally.
/// Small wrapper over a list of Entries-- eventually should also abstract away
/// automatically pushing to persistent storage / snapshotting (TODO)
///
pub trait Log: Sync + Send {
    ///
    /// Retrieves read-only reference to an Entry in the log, specified by |index|.
    /// Will panic if supplied an index exceeds the log length.
    ///
    fn get_entry(&self, index: usize) -> &Entry;

    ///
    /// Retrieves read-only reference to a slice of all Entries in the log past |start_index|.
    /// Will panic if supplied an index exceeds the log length.
    ///
    fn get_entries_from(&self, start_index: usize) -> &[Entry];

    ///
    /// Appends a copy of each entry in |entries| to log. Will correctly modify
    /// |index| field in each Entry to match its index in the log.
    /// Returns this log object.
    ///
    fn append_entries(&mut self, entries: Vec<Entry>) -> &Log;

    ///
    /// Appends a copy of |entry| to the log. Will correclty modify
    /// |index| field in |entry| to match its index in the log.
    /// Returns this log object.
    ///
    fn append_entry(&mut self, entry: Entry) -> &Log;

    ///
    /// Retrieves the index of the last entry in our log.
    ///
    fn get_last_entry_index(&self) -> usize;

    ///
    /// Retrieves the term of the last entry in our log.
    ///
    fn get_last_entry_term(&self) -> u64;

    ///
    /// Rolls back log so that the most recent entry is located at |index|.
    /// Panics if |index| is an invalid log index.
    /// Returns this log object.
    ///
    fn roll_back(&mut self, index: usize) -> &Log;

    ///
    /// Returns true if the log represented by other_log_index,other_log_term is at least as
    /// complete as this log object.
    ///
    /// Completeness is determined by whichever log has a later term. If both logs have the same
    /// last commited term, then whichever log's index is larger is considered more complete
    ///
    fn is_other_log_valid(&self, other_log_index: usize, other_log_term: u64) -> bool;
}

///
/// Simple implementation of Log that stores all logs in memory.
///
pub struct MemoryLog {
    entries: Vec<Entry>,
}

impl MemoryLog {
    pub fn new() -> MemoryLog {
        MemoryLog { entries: Vec::new() }
    }
}

impl Log for MemoryLog {
    fn get_entry(&self, index: usize) -> &Entry {
        self.entries.get(index).unwrap()
    }

    fn get_entries_from(&self, start_index: usize) -> &[Entry] {
        &self.entries[start_index .. self.entries.len()]
    }

    fn append_entries(&mut self, entries: Vec<Entry>) -> &Log {
        let mut start_index = self.entries.len();
        let indexed_entries = entries.into_iter().map(|mut entry| {
            entry.index = start_index;
            start_index += 1;
            entry
        }).collect::<Vec<Entry>>();
        self.entries.extend(indexed_entries);
        self
    }

    fn append_entry(&mut self, mut entry: Entry) -> &Log {
        entry.index = self.entries.len();
        self.entries.push(entry);
        self
    }

    fn get_last_entry_index(&self) -> usize {
        self.entries.len() - 1 as usize
    }

    fn get_last_entry_term(&self) -> u64 {
        self.get_entry(self.get_last_entry_index()).term
    }

    fn roll_back(&mut self, index: usize) -> &Log {
        let destroyed_logs: Vec<_> = self.entries.drain(index + 1..).collect();
        self
    }

    // TODO(jason): Add unit tests
    fn is_other_log_valid (&self, other_log_index: usize, other_log_term: u64) -> bool {
        let last_log_term = self.get_last_entry_term();
        other_log_term > last_log_term ||
            (other_log_term == last_log_term &&
            other_log_index >= self.get_last_entry_index())
    }
}

/// Tests for the log-- these tests should pass for any Log (to test any log, just change the
/// type returned by the |create_log()| helper.
#[cfg(test)]
mod tests {
    use super::{Entry, Log, MemoryLog};
    fn create_log() -> MemoryLog { MemoryLog::new() } // Replace with other log types as needed
    fn create_filled_log(length: usize) -> MemoryLog {
        let mut log = create_log();
        log.append_entries( vec![Entry::random(); length] );
        log
    }

    #[test]
    #[should_panic]
    /// Makes sure we panic if an incorrect index is supplied to the log.
    fn test_log_get_entry_out_of_index() {
        let mut log = create_log();
        log.append_entry(Entry::random());
        log.get_entry(1); // should panic
    }

    #[test]
    /// Tests that simple append and get works for a two-element array.
    fn test_log_append_get_simple() {
        let mut log = create_log();
        let entry1 = Entry::random();
        let entry2 = Entry::random();

        // Append operations
        log.append_entry(entry1.clone());
        log.append_entry(entry2.clone());

        // Data should be the same
        assert_eq!(entry1.data, log.get_entry(0).data);
        assert_eq!(entry2.data, log.get_entry(1).data);
    }

    #[test]
    /// Tests that indices stay valid after appending entries.
    fn test_log_append_indices_simple() {
        let length = 10;
        let mut log = create_filled_log(length);
        // Make sure the indices are correctly set
        for i in 0..length {
            assert_eq!(log.get_entry(i).index, i);
        }
    }

    #[test]
    /// Tests that indices stay valid after appending entries.
    fn test_log_roll_back_simple() {
        let length = 10;
        let mut log = create_filled_log(length);
        let new_length = 5;
        log.roll_back(new_length);
        // make sure log has been rolled back!
        assert_eq!(log.get_last_entry_index(), new_length);
    }

    #[test]
    #[ignore]
    /// TODO (sydli): Generate a bunch of random queries on the log and make
    ///               sure it stays consistent.
    fn test_fuzz() {
        unimplemented!();
    }
}
<commit_msg>chore(log): Fix most of the warnings in log<commit_after>use std::fmt;

///
/// Abstraction for a single Entry for our log.
///
#[derive(Clone)]
pub struct Entry {
    pub index: usize,   // index of this Entry in the log
    pub term: u64,      // term for which this Entry is committed
    pub data: Vec<u8>,  // data blob containing client-defined command to
                        // apply to the client state machine.
}

impl fmt::Debug for Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Entry {{ term: {}, data: {:?} }}", self.term, self.data)
    }
}

impl PartialEq for Entry {
    fn eq(&self, other: &Entry) -> bool {
        self.term == other.term && self.data == other.data
    }
}

///
/// Abstraction for a log of "commands" to apply to the client state machine,
/// stored locally.
/// Small wrapper over a list of Entries-- eventually should also abstract away
/// automatically pushing to persistent storage / snapshotting (TODO)
///
pub trait Log: Sync + Send {
    ///
    /// Retrieves read-only reference to an Entry in the log, specified by |index|.
    /// Will panic if supplied an index exceeds the log length.
    ///
    fn get_entry(&self, index: usize) -> &Entry;

    ///
    /// Retrieves read-only reference to a slice of all Entries in the log past |start_index|.
    /// Will panic if supplied an index exceeds the log length.
    ///
    fn get_entries_from(&self, start_index: usize) -> &[Entry];

    ///
    /// Appends a copy of each entry in |entries| to log. Will correctly modify
    /// |index| field in each Entry to match its index in the log.
    /// Returns this log object.
    ///
    fn append_entries(&mut self, entries: Vec<Entry>) -> &Log;

    ///
    /// Appends a copy of |entry| to the log. Will correclty modify
    /// |index| field in |entry| to match its index in the log.
    /// Returns this log object.
    ///
    fn append_entry(&mut self, entry: Entry) -> &Log;

    ///
    /// Retrieves the index of the last entry in our log.
    ///
    fn get_last_entry_index(&self) -> usize;

    ///
    /// Retrieves the term of the last entry in our log.
    ///
    fn get_last_entry_term(&self) -> u64;

    ///
    /// Rolls back log so that the most recent entry is located at |index|.
    /// Panics if |index| is an invalid log index.
    /// Returns this log object.
    ///
    fn roll_back(&mut self, index: usize) -> &Log;

    ///
    /// Returns true if the log represented by other_log_index,other_log_term is at least as
    /// complete as this log object.
    ///
    /// Completeness is determined by whichever log has a later term. If both logs have the same
    /// last commited term, then whichever log's index is larger is considered more complete
    ///
    fn is_other_log_valid(&self, other_log_index: usize, other_log_term: u64) -> bool;
}

///
/// Simple implementation of Log that stores all logs in memory.
///
pub struct MemoryLog {
    entries: Vec<Entry>,
}

impl MemoryLog {
    pub fn new() -> MemoryLog {
        MemoryLog { entries: Vec::new() }
    }
}

impl Log for MemoryLog {
    fn get_entry(&self, index: usize) -> &Entry {
        self.entries.get(index).unwrap()
    }

    fn get_entries_from(&self, start_index: usize) -> &[Entry] {
        &self.entries[start_index .. self.entries.len()]
    }

    fn append_entries(&mut self, entries: Vec<Entry>) -> &Log {
        let mut start_index = self.entries.len();
        let indexed_entries = entries.into_iter().map(|mut entry| {
            entry.index = start_index;
            start_index += 1;
            entry
        }).collect::<Vec<Entry>>();
        self.entries.extend(indexed_entries);
        self
    }

    fn append_entry(&mut self, mut entry: Entry) -> &Log {
        entry.index = self.entries.len();
        self.entries.push(entry);
        self
    }

    fn get_last_entry_index(&self) -> usize {
        self.entries.len() - 1 as usize
    }

    fn get_last_entry_term(&self) -> u64 {
        self.get_entry(self.get_last_entry_index()).term
    }

    fn roll_back(&mut self, index: usize) -> &Log {
        self.entries.drain(index + 1..).collect::<Vec<_>>();
        self
    }

    // TODO(jason): Add unit tests
    fn is_other_log_valid (&self, other_log_index: usize, other_log_term: u64) -> bool {
        let last_log_term = self.get_last_entry_term();
        other_log_term > last_log_term ||
            (other_log_term == last_log_term &&
            other_log_index >= self.get_last_entry_index())
    }
}

/// Tests for the log-- these tests should pass for any Log (to test any log, just change the
/// type returned by the |create_log()| helper.
#[cfg(test)]
mod tests {
    use super::{Entry, Log, MemoryLog};
    fn create_log() -> MemoryLog { MemoryLog::new() } // Replace with other log types as needed
    fn create_filled_log(length: usize) -> MemoryLog {
        let mut log = create_log();
        log.append_entries( vec![Entry::random(); length] );
        log
    }

    fn random_entry() {
        let mut vec = vec![0; 8];
        thread_rng().fill_bytes(&mut vec);
        Entry {
            index: 0, // TODO (sydli) this should not be 0
            term: 0,  // Unneeded, for testing, for now.
            data: vec,
        }
    }

    #[test]
    #[should_panic]
    /// Makes sure we panic if an incorrect index is supplied to the log.
    fn test_log_get_entry_out_of_index() {
        let mut log = create_log();
        log.append_entry(Entry::random());
        log.get_entry(1); // should panic
    }

    #[test]
    /// Tests that simple append and get works for a two-element array.
    fn test_log_append_get_simple() {
        let mut log = create_log();
        let entry1 = Entry::random();
        let entry2 = Entry::random();

        // Append operations
        log.append_entry(entry1.clone());
        log.append_entry(entry2.clone());

        // Data should be the same
        assert_eq!(entry1.data, log.get_entry(0).data);
        assert_eq!(entry2.data, log.get_entry(1).data);
    }

    #[test]
    /// Tests that indices stay valid after appending entries.
    fn test_log_append_indices_simple() {
        let length = 10;
        let mut log = create_filled_log(length);
        // Make sure the indices are correctly set
        for i in 0..length {
            assert_eq!(log.get_entry(i).index, i);
        }
    }

    #[test]
    /// Tests that indices stay valid after appending entries.
    fn test_log_roll_back_simple() {
        let length = 10;
        let mut log = create_filled_log(length);
        let new_length = 5;
        log.roll_back(new_length);
        // make sure log has been rolled back!
        assert_eq!(log.get_last_entry_index(), new_length);
    }

    #[test]
    #[ignore]
    /// TODO (sydli): Generate a bunch of random queries on the log and make
    ///               sure it stays consistent.
    fn test_fuzz() {
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 `multipart-async` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
//! The server-side abstraction for multipart requests. Enabled with the `server` feature (on by
//! default).
//!
//! Use this when you are implementing an HTTP server and want to
//! to accept, parse, and serve HTTP `multipart/form-data` requests (file uploads).
//!
//! See the `Multipart` struct for more info.
use futures::task::{self, Context};
use futures::{Future, Poll, Stream};

use std::cell::Cell;
use std::rc::Rc;

use self::boundary::BoundaryFinder;

use crate::{BodyChunk, StreamError};

macro_rules! try_opt (
    ($expr:expr) => (
        match $expr {
            Some(val) => val,
            None => return None,
        }
    )
);

macro_rules! ret_err (
    ($($args:tt)+) => (
            return fmt_err!($($args)+);
    )
);

macro_rules! fmt_err(
    ($string:expr) => (
        crate::helpers::error($string)
    );
    ($string:expr, $($args:tt)*) => (
        crate::helpers::error(format!($string, $($args)*))
    );
);

mod boundary;
mod field;

use crate::helpers::*;

use self::field::ReadHeaders;

pub use self::field::{Field, FieldData, FieldHeaders};
// pub use self::field::{ReadTextField, TextField};

#[cfg(feature = "hyper")]
mod hyper;

#[cfg(feature = "hyper")]
pub use self::hyper::{MinusBody, MultipartService};
use std::pin::Pin;

#[cfg(any(test, feature = "fuzzing"))]
pub(crate) mod fuzzing {
    pub(crate) use super::boundary::BoundaryFinder;
    pub(crate) use super::field::ReadHeaders;
}

/// The server-side implementation of `multipart/form-data` requests.
pub struct Multipart<S: TryStream> {
    inner: PushChunk<BoundaryFinder<S>, S::Ok>,
    read_hdr: ReadHeaders,
    consumed: bool,
}

// Q: why can't we just wrap up these bounds into a trait?
// A: https://github.com/rust-lang/rust/issues/24616#issuecomment-112065997
// (The workaround mentioned in a later comment doesn't seem to be worth the added complexity)
impl<S> Multipart<S>
where
    S: TryStream,
    S::Ok: BodyChunk,
    S::Error: StreamError,
{
    unsafe_pinned!(inner: PushChunk<BoundaryFinder<S>, S::Ok>);
    unsafe_unpinned!(read_hdr: ReadHeaders);
    unsafe_unpinned!(consumed: bool);

    /// Construct a new `Multipart` with the given body reader and boundary.
    ///
    /// This will add the requisite `--` and CRLF (`\r\n`) to the boundary as per
    /// [IETF RFC 7578 section 4.1](https://tools.ietf.org/html/rfc7578#section-4.1).
    pub fn with_body<B: Into<String>>(stream: S, boundary: B) -> Self {
        let mut boundary = boundary.into();
        boundary.insert_str(0, "--");

        debug!("Boundary: {}", boundary);

        Multipart {
            inner: PushChunk::new(BoundaryFinder::new(stream, boundary)),
            read_hdr: ReadHeaders::default(),
            consumed: false,
        }
    }

    pub fn poll_next_field_headers(
        mut self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> PollOpt<FieldHeaders, S::Error> {
        if !ready!(self.as_mut().inner().stream().consume_boundary(cx)?) {
            return Poll::Ready(None);
        }

        unsafe {
            let this = self.as_mut().get_unchecked_mut();
            this.read_hdr
                .read_headers(Pin::new_unchecked(&mut this.inner), cx)
        }
    }

    pub fn poll_body_chunk(self: Pin<&mut Self>, cx: &mut Context) -> PollOpt<S::Ok, S::Error> {
        if !self.read_hdr.is_reading_headers() {
            self.inner().poll_next(cx)
        } else {
            Poll::Ready(None)
        }
    }

    pub fn poll_field(mut self: Pin<&mut Self>, cx: &mut Context) -> PollOpt<Field<S>, S::Error> {
        if let Some(headers) = ready!(self.as_mut().poll_next_field_headers(cx)?) {
            ready_ok(field::new_field(headers, self.inner()))
        } else {
            Poll::Ready(None)
        }
    }

    pub fn fold_fields<F, Fut>(self, init: Fut::Ok, folder: F) -> FoldFields<F, S, Fut>
    where
        F: for<'a> FnMut(Field<'a, S>, Fut::Ok) -> Fut,
        Fut: TryFuture<Error = S::Error>,
    {
        FoldFields {
            folder,
            multipart: self,
            state: Some(init),
            fut: None,
        }
    }
}

pub struct FoldFields<F, S: TryStream, Fut: TryFuture> {
    folder: F,
    multipart: Multipart<S>,
    state: Option<Fut::Ok>,
    fut: Option<Fut>,
}

impl<F, S: TryStream, Fut: TryFuture> FoldFields<F, S, Fut> {
    unsafe_pinned!(multipart: Multipart<S>);
    unsafe_pinned!(fut: Option<Fut>);
    unsafe_unpinned!(state: Option<Fut::Ok>);
    unsafe_unpinned!(folder: F);
}

impl<F, S, Fut> Future for FoldFields<F, S, Fut>
where
    F: for<'a> FnMut(Field<'a, S>, Fut::Ok) -> Fut,
    Fut: TryFuture<Error = S::Error>,
    S: TryStream,
    S::Ok: BodyChunk,
    S::Error: StreamError,
{
    type Output = Result<Fut::Ok, S::Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        loop {
            if let Some(fut) = self.as_mut().fut().as_pin_mut() {
                *self.as_mut().state() = Some(ready!(fut.try_poll(cx)?));
            }

            let state = self
                .as_mut()
                .state()
                .take()
                .expect(".poll() called after value returned");

            unsafe {
                let this = self.as_mut().get_unchecked_mut();
                if let Some(field) = ready!(Pin::new_unchecked(&mut this.multipart).poll_field(cx)?)
                {
                    let next_state = (this.folder)(field, state);
                    Pin::new_unchecked(&mut this.fut).set(Some(next_state));
                } else {
                    return ready_ok(state);
                }
            }
        }
    }
}

/// An extension trait for requests which may be multipart.
pub trait RequestExt: Sized {
    /// The success type, may contain `Multipart` or something else.
    type Multipart;

    /// Convert `Self` into `Self::Multipart` if applicable.
    fn into_multipart(self) -> Result<Self::Multipart, Self>;
}

/// Struct wrapping a stream which allows a chunk to be pushed back to it to be yielded next.
pub(crate) struct PushChunk<S, T> {
    stream: S,
    pushed: Option<T>,
}

impl<S, T> PushChunk<S, T> {
    unsafe_pinned!(stream: S);
    unsafe_unpinned!(pushed: Option<T>);

    pub(crate) fn new(stream: S) -> Self {
        PushChunk {
            stream,
            pushed: None,
        }
    }
}

impl<S: TryStream> PushChunk<S, S::Ok> where S::Ok: BodyChunk {
    fn push_chunk(mut self: Pin<&mut Self>, chunk: S::Ok) {
        if let Some(pushed) = self.as_mut().pushed() {
            error!(
                "pushing excess chunk: \"{}\" already pushed chunk: \"{}\"",
                show_bytes(chunk.as_slice()),
                show_bytes(pushed.as_slice())
            );
        }

        *self.as_mut().pushed() = Some(chunk);
    }
}

impl<S: TryStream> Stream for PushChunk<S, S::Ok> {
    type Item = Result<S::Ok, S::Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        if let Some(pushed) = self.as_mut().pushed().take() {
            return Poll::Ready(Some(Ok(pushed)));
        }

        self.stream().try_poll_next(cx)
    }
}

#[cfg(test)]
mod test {
    use super::Multipart;
    use crate::test_util::mock_stream;
    use crate::server::FieldHeaders;

    const BOUNDARY: &str = "boundary";

    #[test]
    fn test_empty_body() {
        let _ = ::env_logger::try_init();
        let multipart = Multipart::with_body(
            mock_stream(&[]),
            BOUNDARY
        );
        pin_mut!(multipart);
        ready_assert_eq!(|cx| multipart.as_mut().poll_next_field_headers(cx), None);
    }

    #[test]
    fn test_no_headers() {
        let _ = ::env_logger::try_init();
        let multipart = Multipart::with_body(
            mock_stream(&[b"--boundary", b"\r\n", b"\r\n", b"--boundary--"]),
            BOUNDARY
        );
        pin_mut!(multipart);
        ready_assert_eq!(|cx| multipart.as_mut().poll_next_field_headers(cx), None);
    }

    #[test]
    fn test_single_field() {
        let _ = ::env_logger::try_init();
        let multipart = Multipart::with_body(
            mock_stream(&[
                b"--boundary\r", b"\n",
                b"Content-Disposition:",
                b" form-data; name=",
                b"\"foo\"",
                b"\r\n\r\n",
                b"field data",
                b"\r", b"\n--boundary--"
            ]),
            BOUNDARY
        );
        pin_mut!(multipart);

        ready_assert_eq!(
            |cx| multipart.as_mut().poll_next_field_headers(cx),
            Some(Ok(FieldHeaders {
                name: "foo".into(),
                filename: None,
                content_type: None,
                ext_headers: Default::default(),
                _backcompat: (),
            }))
        );

    }
}
<commit_msg>cut FoldFields<commit_after>// Copyright 2017 `multipart-async` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
//! The server-side abstraction for multipart requests. Enabled with the `server` feature (on by
//! default).
//!
//! Use this when you are implementing an HTTP server and want to
//! to accept, parse, and serve HTTP `multipart/form-data` requests (file uploads).
//!
//! See the `Multipart` struct for more info.
use futures::task::{self, Context};
use futures::{Future, Poll, Stream};

use std::cell::Cell;
use std::rc::Rc;

use self::boundary::BoundaryFinder;

use crate::{BodyChunk, StreamError};

macro_rules! try_opt (
    ($expr:expr) => (
        match $expr {
            Some(val) => val,
            None => return None,
        }
    )
);

macro_rules! ret_err (
    ($($args:tt)+) => (
            return fmt_err!($($args)+);
    )
);

macro_rules! fmt_err(
    ($string:expr) => (
        crate::helpers::error($string)
    );
    ($string:expr, $($args:tt)*) => (
        crate::helpers::error(format!($string, $($args)*))
    );
);

mod boundary;
mod field;

use crate::helpers::*;

use self::field::ReadHeaders;

pub use self::field::{Field, FieldData, FieldHeaders};
// pub use self::field::{ReadTextField, TextField};

#[cfg(feature = "hyper")]
mod hyper;

#[cfg(feature = "hyper")]
pub use self::hyper::{MinusBody, MultipartService};
use std::pin::Pin;

#[cfg(any(test, feature = "fuzzing"))]
pub(crate) mod fuzzing {
    pub(crate) use super::boundary::BoundaryFinder;
    pub(crate) use super::field::ReadHeaders;
}

/// The server-side implementation of `multipart/form-data` requests.
pub struct Multipart<S: TryStream> {
    inner: PushChunk<BoundaryFinder<S>, S::Ok>,
    read_hdr: ReadHeaders,
    consumed: bool,
}

// Q: why can't we just wrap up these bounds into a trait?
// A: https://github.com/rust-lang/rust/issues/24616#issuecomment-112065997
// (The workaround mentioned in a later comment doesn't seem to be worth the added complexity)
impl<S> Multipart<S>
where
    S: TryStream,
    S::Ok: BodyChunk,
    S::Error: StreamError,
{
    unsafe_pinned!(inner: PushChunk<BoundaryFinder<S>, S::Ok>);
    unsafe_unpinned!(read_hdr: ReadHeaders);
    unsafe_unpinned!(consumed: bool);

    /// Construct a new `Multipart` with the given body reader and boundary.
    ///
    /// This will add the requisite `--` and CRLF (`\r\n`) to the boundary as per
    /// [IETF RFC 7578 section 4.1](https://tools.ietf.org/html/rfc7578#section-4.1).
    pub fn with_body<B: Into<String>>(stream: S, boundary: B) -> Self {
        let mut boundary = boundary.into();
        boundary.insert_str(0, "--");

        debug!("Boundary: {}", boundary);

        Multipart {
            inner: PushChunk::new(BoundaryFinder::new(stream, boundary)),
            read_hdr: ReadHeaders::default(),
            consumed: false,
        }
    }

    pub fn poll_next_field_headers(
        mut self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> PollOpt<FieldHeaders, S::Error> {
        if !ready!(self.as_mut().inner().stream().consume_boundary(cx)?) {
            return Poll::Ready(None);
        }

        unsafe {
            let this = self.as_mut().get_unchecked_mut();
            this.read_hdr
                .read_headers(Pin::new_unchecked(&mut this.inner), cx)
        }
    }

    pub fn poll_body_chunk(self: Pin<&mut Self>, cx: &mut Context) -> PollOpt<S::Ok, S::Error> {
        if !self.read_hdr.is_reading_headers() {
            self.inner().poll_next(cx)
        } else {
            Poll::Ready(None)
        }
    }

    pub fn poll_field(mut self: Pin<&mut Self>, cx: &mut Context) -> PollOpt<Field<S>, S::Error> {
        if let Some(headers) = ready!(self.as_mut().poll_next_field_headers(cx)?) {
            ready_ok(field::new_field(headers, self.inner()))
        } else {
            Poll::Ready(None)
        }
    }
}

/// An extension trait for requests which may be multipart.
pub trait RequestExt: Sized {
    /// The success type, may contain `Multipart` or something else.
    type Multipart;

    /// Convert `Self` into `Self::Multipart` if applicable.
    fn into_multipart(self) -> Result<Self::Multipart, Self>;
}

/// Struct wrapping a stream which allows a chunk to be pushed back to it to be yielded next.
pub(crate) struct PushChunk<S, T> {
    stream: S,
    pushed: Option<T>,
}

impl<S, T> PushChunk<S, T> {
    unsafe_pinned!(stream: S);
    unsafe_unpinned!(pushed: Option<T>);

    pub(crate) fn new(stream: S) -> Self {
        PushChunk {
            stream,
            pushed: None,
        }
    }
}

impl<S: TryStream> PushChunk<S, S::Ok> where S::Ok: BodyChunk {
    fn push_chunk(mut self: Pin<&mut Self>, chunk: S::Ok) {
        if let Some(pushed) = self.as_mut().pushed() {
            error!(
                "pushing excess chunk: \"{}\" already pushed chunk: \"{}\"",
                show_bytes(chunk.as_slice()),
                show_bytes(pushed.as_slice())
            );
        }

        *self.as_mut().pushed() = Some(chunk);
    }
}

impl<S: TryStream> Stream for PushChunk<S, S::Ok> {
    type Item = Result<S::Ok, S::Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        if let Some(pushed) = self.as_mut().pushed().take() {
            return Poll::Ready(Some(Ok(pushed)));
        }

        self.stream().try_poll_next(cx)
    }
}

#[cfg(test)]
mod test {
    use futures::prelude::*;
    use super::Multipart;
    use crate::test_util::mock_stream;
    use crate::server::FieldHeaders;

    const BOUNDARY: &str = "boundary";

    #[test]
    fn test_empty_body() {
        let _ = ::env_logger::try_init();
        let multipart = Multipart::with_body(
            mock_stream(&[]),
            BOUNDARY
        );
        pin_mut!(multipart);
        ready_assert_eq!(|cx| multipart.as_mut().poll_next_field_headers(cx), None);
    }

    #[test]
    fn test_no_headers() {
        let _ = ::env_logger::try_init();
        let multipart = Multipart::with_body(
            mock_stream(&[b"--boundary", b"\r\n", b"\r\n", b"--boundary--"]),
            BOUNDARY
        );
        pin_mut!(multipart);
        ready_assert_eq!(|cx| multipart.as_mut().poll_next_field_headers(cx), None);
    }

    #[test]
    fn test_single_field() {
        let _ = ::env_logger::try_init();
        let multipart = Multipart::with_body(
            mock_stream(&[
                b"--boundary\r", b"\n",
                b"Content-Disposition:",
                b" form-data; name=",
                b"\"foo\"",
                b"\r\n\r\n",
                b"field data",
                b"\r", b"\n--boundary--"
            ]),
            BOUNDARY
        );
        pin_mut!(multipart);

        ready_assert_eq!(
            |cx| multipart.as_mut().poll_next_field_headers(cx),
            Some(Ok(FieldHeaders {
                name: "foo".into(),
                filename: None,
                content_type: None,
                ext_headers: Default::default(),
                _backcompat: (),
            }))
        );
    }
}
<|endoftext|>


<commit_before>extern crate memcache;

#[test]
fn test_counter() {
    let client = memcache::connect(&("localhost", 2333)).unwrap();
    client.flush(0).unwrap();

    client.set_raw("truth", &[0x0u8], 0, 0).unwrap();
    client.increment("truth", 42).unwrap();
}
<commit_msg>add counter test<commit_after>extern crate memcache;

#[test]
fn test_counter() {
    let client = memcache::connect(&("localhost", 2333)).unwrap();
    client.flush(0).unwrap();

    client.set_raw("truth", &[0x30u8], 0, 0).unwrap();
    client.increment("truth", 42).unwrap();
    let (value, flag) = client.get_raw("truth").unwrap();
    assert!(flag == 0);
    assert!(value == &[0x34, 0x32]);
}
<|endoftext|>


<commit_before>use std::env;
use std::net::SocketAddr;
use std::io::{Read, Write, BufRead};

pub fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    let mut socket = ::std::net::TcpStream::connect(addr).unwrap();

    socket.write_all(&[1]).unwrap(); // subscribe

    // TODO

}
<commit_msg>get simpler subscriber working<commit_after>use std::env;
use std::net::SocketAddr;
use std::io::{Read, Write, BufRead};

pub fn main() {
    let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
    let addr = addr.parse::<SocketAddr>().unwrap();

    let mut socket = ::std::net::TcpStream::connect(addr).unwrap();

    socket.write_all(&[1]).unwrap(); // subscribe

    let mut message = [0u8; 256];
    let mut header = [0u8];

    loop {
        socket.read_exact(&mut header).unwrap();
        let len = header[0] as usize;
        socket.read_exact(&mut message[..len]).unwrap();
        match ::std::str::from_utf8(&message[..len]) {
            Ok(s) => {
                println!("{}", s);
            }
            Err(e) => {
                println!("[received non-utf8 data]");
            }
        }
    }
}
<|endoftext|>


<commit_before>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc;
use core::mem;
use errno::{SysError, SysResult};

pub use libc::consts::os::posix88::{
    SIGHUP,   // 1
    SIGINT,   // 2
    SIGQUIT,  // 3
    SIGILL,   // 4
    SIGABRT,  // 6
    SIGFPE,   // 8
    SIGKILL,  // 9
    SIGSEGV,  // 11
    SIGPIPE,  // 13
    SIGALRM,  // 14
    SIGTERM,  // 15
};

pub use self::signal::{
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

pub use self::signal::SockFlag;
pub use self::signal::sigset_t;

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
pub mod signal {
    use libc;

    bitflags!(
        flags SockFlag: libc::c_ulong {
            const SA_NOCLDSTOP = 0x00000001,
            const SA_NOCLDWAIT = 0x00000002,
            const SA_NODEFER   = 0x40000000,
            const SA_ONSTACK   = 0x08000000,
            const SA_RESETHAND = 0x80000000,
            const SA_RESTART   = 0x10000000,
            const SA_SIGINFO   = 0x00000004,
        }
    );

    pub const SIGTRAP:      libc::c_int = 5;
    pub const SIGIOT:       libc::c_int = 6;
    pub const SIGBUS:       libc::c_int = 7;
    pub const SIGUSR1:      libc::c_int = 10;
    pub const SIGUSR2:      libc::c_int = 12;
    pub const SIGSTKFLT:    libc::c_int = 16;
    pub const SIGCHLD:      libc::c_int = 17;
    pub const SIGCONT:      libc::c_int = 18;
    pub const SIGSTOP:      libc::c_int = 19;
    pub const SIGTSTP:      libc::c_int = 20;
    pub const SIGTTIN:      libc::c_int = 21;
    pub const SIGTTOU:      libc::c_int = 22;
    pub const SIGURG:       libc::c_int = 23;
    pub const SIGXCPU:      libc::c_int = 24;
    pub const SIGXFSZ:      libc::c_int = 25;
    pub const SIGVTALRM:    libc::c_int = 26;
    pub const SIGPROF:      libc::c_int = 27;
    pub const SIGWINCH:     libc::c_int = 28;
    pub const SIGIO:        libc::c_int = 29;
    pub const SIGPOLL:      libc::c_int = 29;
    pub const SIGPWR:       libc::c_int = 30;
    pub const SIGSYS:       libc::c_int = 31;
    pub const SIGUNUSED:    libc::c_int = 31;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    #[derive(Copy)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_errno: libc::c_int,
        si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    #[allow(missing_copy_implementations)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        pub sa_flags: SockFlag,
        sa_restorer: *mut libc::c_void,
    }

    #[repr(C)]
    #[cfg(target_word_size = "32")]
    #[derive(Copy)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }

    #[repr(C)]
    #[cfg(target_word_size = "64")]
    #[derive(Copy)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 16],
    }
}

#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub mod signal {
    use libc;

    bitflags!(
        flags SockFlag: libc::c_uint {
            const SA_NOCLDSTOP = 0x00000001,
            const SA_NOCLDWAIT = 0x00001000,
            const SA_NODEFER   = 0x40000000,
            const SA_ONSTACK   = 0x08000000,
            const SA_RESETHAND = 0x80000000,
            const SA_RESTART   = 0x10000000,
            const SA_SIGINFO   = 0x00000008,
        }
    );

    pub const SIGTRAP:      libc::c_int = 5;
    pub const SIGIOT:       libc::c_int = 6;
    pub const SIGBUS:       libc::c_int = 10;
    pub const SIGSYS:       libc::c_int = 12;
    pub const SIGUSR1:      libc::c_int = 16;
    pub const SIGUSR2:      libc::c_int = 17;
    pub const SIGCHLD:      libc::c_int = 18;
    pub const SIGCLD:       libc::c_int = 18;
    pub const SIGPWR:       libc::c_int = 19;
    pub const SIGWINCH:     libc::c_int = 20;
    pub const SIGURG:       libc::c_int = 21;
    pub const SIGIO:        libc::c_int = 22;
    pub const SIGPOLL:      libc::c_int = 22;
    pub const SIGSTOP:      libc::c_int = 23;
    pub const SIGTSTP:      libc::c_int = 24;
    pub const SIGCONT:      libc::c_int = 25;
    pub const SIGTTIN:      libc::c_int = 26;
    pub const SIGTTOU:      libc::c_int = 27;
    pub const SIGVTALRM:    libc::c_int = 28;
    pub const SIGPROF:      libc::c_int = 29;
    pub const SIGXCPU:      libc::c_int = 30;
    pub const SIGFSZ:       libc::c_int = 31;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_code: libc::c_int,
        si_errno: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_flags: SockFlag,
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        sa_restorer: *mut libc::c_void,
        sa_resv: [libc::c_int; 1],
    }

    #[repr(C)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub mod signal {
    use libc;

    bitflags!(
        flags SockFlag: libc::c_int {
            const SA_NOCLDSTOP = 0x0008,
            const SA_NOCLDWAIT = 0x0020,
            const SA_NODEFER   = 0x0010,
            const SA_ONSTACK   = 0x0001,
            const SA_RESETHAND = 0x0004,
            const SA_RESTART   = 0x0002,
            const SA_SIGINFO   = 0x0040,
        }
    );

    pub const SIGTRAP:      libc::c_int = 5;
    pub const SIGIOT:       libc::c_int = 6;
    pub const SIGBUS:       libc::c_int = 10;
    pub const SIGSYS:       libc::c_int = 12;
    pub const SIGURG:       libc::c_int = 16;
    pub const SIGSTOP:      libc::c_int = 17;
    pub const SIGTSTP:      libc::c_int = 18;
    pub const SIGCONT:      libc::c_int = 19;
    pub const SIGCHLD:      libc::c_int = 20;
    pub const SIGTTIN:      libc::c_int = 21;
    pub const SIGTTOU:      libc::c_int = 22;
    pub const SIGIO:        libc::c_int = 23;
    pub const SIGXCPU:      libc::c_int = 24;
    pub const SIGXFSZ:      libc::c_int = 25;
    pub const SIGVTALRM:    libc::c_int = 26;
    pub const SIGPROF:      libc::c_int = 27;
    pub const SIGWINCH:     libc::c_int = 28;
    pub const SIGINFO:      libc::c_int = 29;
    pub const SIGUSR1:      libc::c_int = 30;
    pub const SIGUSR2:      libc::c_int = 31;

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub type sigset_t = u32;
    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigset_t {
        bits: [u32; 4],
    }

    // This structure has more fields, but we're not all that interested in
    // them.
    #[repr(C)]
    #[derive(Copy)]
    pub struct siginfo {
        pub si_signo: libc::c_int,
        pub si_errno: libc::c_int,
        pub si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    #[repr(C)]
    #[allow(missing_copy_implementations)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        sa_tramp: *mut libc::c_void,
        pub sa_mask: sigset_t,
        pub sa_flags: SockFlag,
    }

    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_flags: SockFlag,
        pub sa_mask: sigset_t,
    }

}

mod ffi {
    use libc;
    use super::signal::{sigaction, sigset_t};

    #[allow(improper_ctypes)]
    extern {
        pub fn sigaction(signum: libc::c_int,
                         act: *const sigaction,
                         oldact: *mut sigaction) -> libc::c_int;

        pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
        pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
        pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;

        pub fn kill(pid: libc::pid_t, signum: libc::c_int) -> libc::c_int;
    }
}

#[derive(Copy)]
pub struct SigSet {
    sigset: sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn empty() -> SigSet {
        let mut sigset = unsafe { mem::uninitialized::<sigset_t>() };
        let _ = unsafe { ffi::sigemptyset(&mut sigset as *mut sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> SysResult<()> {
        let res = unsafe { ffi::sigaddset(&mut self.sigset as *mut sigset_t, signum) };

        if res < 0 {
            return Err(SysError::last());
        }

        Ok(())
    }

    pub fn remove(&mut self, signum: SigNum) -> SysResult<()> {
        let res = unsafe { ffi::sigdelset(&mut self.sigset as *mut sigset_t, signum) };

        if res < 0 {
            return Err(SysError::last());
        }

        Ok(())
    }
}

type sigaction_t = self::signal::sigaction;

pub struct SigAction {
    sigaction: sigaction_t
}

impl SigAction {
    pub fn new(handler: extern fn(libc::c_int), flags: SockFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<sigaction_t>() };
        s.sa_handler = handler;
        s.sa_flags = flags;
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub fn sigaction(signum: SigNum, sigaction: &SigAction) -> SysResult<SigAction> {
    let mut oldact = unsafe { mem::uninitialized::<sigaction_t>() };

    let res = unsafe {
        ffi::sigaction(signum, &sigaction.sigaction as *const sigaction_t, &mut oldact as *mut sigaction_t)
    };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(SigAction { sigaction: oldact })
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> SysResult<()> {
    let res = unsafe { ffi::kill(pid, signum) };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(())
}
<commit_msg>Fix a bad cfg on linux<commit_after>// Portions of this file are Copyright 2014 The Rust Project Developers.
// See http://rust-lang.org/COPYRIGHT.

use libc;
use core::mem;
use errno::{SysError, SysResult};

pub use libc::consts::os::posix88::{
    SIGHUP,   // 1
    SIGINT,   // 2
    SIGQUIT,  // 3
    SIGILL,   // 4
    SIGABRT,  // 6
    SIGFPE,   // 8
    SIGKILL,  // 9
    SIGSEGV,  // 11
    SIGPIPE,  // 13
    SIGALRM,  // 14
    SIGTERM,  // 15
};

pub use self::signal::{
    SIGTRAP,
    SIGIOT,
    SIGBUS,
    SIGSYS,
    SIGURG,
    SIGSTOP,
    SIGTSTP,
    SIGCONT,
    SIGCHLD,
    SIGTTIN,
    SIGTTOU,
    SIGIO,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGUSR1,
    SIGUSR2,
};

pub use self::signal::SockFlag;
pub use self::signal::sigset_t;

// This doesn't always exist, but when it does, it's 7
pub const SIGEMT: libc::c_int = 7;

#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm")),
          target_os = "android"))]
pub mod signal {
    use libc;

    bitflags!(
        flags SockFlag: libc::c_ulong {
            const SA_NOCLDSTOP = 0x00000001,
            const SA_NOCLDWAIT = 0x00000002,
            const SA_NODEFER   = 0x40000000,
            const SA_ONSTACK   = 0x08000000,
            const SA_RESETHAND = 0x80000000,
            const SA_RESTART   = 0x10000000,
            const SA_SIGINFO   = 0x00000004,
        }
    );

    pub const SIGTRAP:      libc::c_int = 5;
    pub const SIGIOT:       libc::c_int = 6;
    pub const SIGBUS:       libc::c_int = 7;
    pub const SIGUSR1:      libc::c_int = 10;
    pub const SIGUSR2:      libc::c_int = 12;
    pub const SIGSTKFLT:    libc::c_int = 16;
    pub const SIGCHLD:      libc::c_int = 17;
    pub const SIGCONT:      libc::c_int = 18;
    pub const SIGSTOP:      libc::c_int = 19;
    pub const SIGTSTP:      libc::c_int = 20;
    pub const SIGTTIN:      libc::c_int = 21;
    pub const SIGTTOU:      libc::c_int = 22;
    pub const SIGURG:       libc::c_int = 23;
    pub const SIGXCPU:      libc::c_int = 24;
    pub const SIGXFSZ:      libc::c_int = 25;
    pub const SIGVTALRM:    libc::c_int = 26;
    pub const SIGPROF:      libc::c_int = 27;
    pub const SIGWINCH:     libc::c_int = 28;
    pub const SIGIO:        libc::c_int = 29;
    pub const SIGPOLL:      libc::c_int = 29;
    pub const SIGPWR:       libc::c_int = 30;
    pub const SIGSYS:       libc::c_int = 31;
    pub const SIGUNUSED:    libc::c_int = 31;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    #[derive(Copy)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_errno: libc::c_int,
        si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    #[allow(missing_copy_implementations)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        pub sa_flags: SockFlag,
        sa_restorer: *mut libc::c_void,
    }

    #[repr(C)]
    #[cfg(target_pointer_width = "32")]
    #[derive(Copy)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }

    #[repr(C)]
    #[cfg(target_pointer_width = "64")]
    #[derive(Copy)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 16],
    }
}

#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub mod signal {
    use libc;

    bitflags!(
        flags SockFlag: libc::c_uint {
            const SA_NOCLDSTOP = 0x00000001,
            const SA_NOCLDWAIT = 0x00001000,
            const SA_NODEFER   = 0x40000000,
            const SA_ONSTACK   = 0x08000000,
            const SA_RESETHAND = 0x80000000,
            const SA_RESTART   = 0x10000000,
            const SA_SIGINFO   = 0x00000008,
        }
    );

    pub const SIGTRAP:      libc::c_int = 5;
    pub const SIGIOT:       libc::c_int = 6;
    pub const SIGBUS:       libc::c_int = 10;
    pub const SIGSYS:       libc::c_int = 12;
    pub const SIGUSR1:      libc::c_int = 16;
    pub const SIGUSR2:      libc::c_int = 17;
    pub const SIGCHLD:      libc::c_int = 18;
    pub const SIGCLD:       libc::c_int = 18;
    pub const SIGPWR:       libc::c_int = 19;
    pub const SIGWINCH:     libc::c_int = 20;
    pub const SIGURG:       libc::c_int = 21;
    pub const SIGIO:        libc::c_int = 22;
    pub const SIGPOLL:      libc::c_int = 22;
    pub const SIGSTOP:      libc::c_int = 23;
    pub const SIGTSTP:      libc::c_int = 24;
    pub const SIGCONT:      libc::c_int = 25;
    pub const SIGTTIN:      libc::c_int = 26;
    pub const SIGTTOU:      libc::c_int = 27;
    pub const SIGVTALRM:    libc::c_int = 28;
    pub const SIGPROF:      libc::c_int = 29;
    pub const SIGXCPU:      libc::c_int = 30;
    pub const SIGFSZ:       libc::c_int = 31;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_code: libc::c_int,
        si_errno: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_flags: SockFlag,
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        sa_restorer: *mut libc::c_void,
        sa_resv: [libc::c_int; 1],
    }

    #[repr(C)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub mod signal {
    use libc;

    bitflags!(
        flags SockFlag: libc::c_int {
            const SA_NOCLDSTOP = 0x0008,
            const SA_NOCLDWAIT = 0x0020,
            const SA_NODEFER   = 0x0010,
            const SA_ONSTACK   = 0x0001,
            const SA_RESETHAND = 0x0004,
            const SA_RESTART   = 0x0002,
            const SA_SIGINFO   = 0x0040,
        }
    );

    pub const SIGTRAP:      libc::c_int = 5;
    pub const SIGIOT:       libc::c_int = 6;
    pub const SIGBUS:       libc::c_int = 10;
    pub const SIGSYS:       libc::c_int = 12;
    pub const SIGURG:       libc::c_int = 16;
    pub const SIGSTOP:      libc::c_int = 17;
    pub const SIGTSTP:      libc::c_int = 18;
    pub const SIGCONT:      libc::c_int = 19;
    pub const SIGCHLD:      libc::c_int = 20;
    pub const SIGTTIN:      libc::c_int = 21;
    pub const SIGTTOU:      libc::c_int = 22;
    pub const SIGIO:        libc::c_int = 23;
    pub const SIGXCPU:      libc::c_int = 24;
    pub const SIGXFSZ:      libc::c_int = 25;
    pub const SIGVTALRM:    libc::c_int = 26;
    pub const SIGPROF:      libc::c_int = 27;
    pub const SIGWINCH:     libc::c_int = 28;
    pub const SIGINFO:      libc::c_int = 29;
    pub const SIGUSR1:      libc::c_int = 30;
    pub const SIGUSR2:      libc::c_int = 31;

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub type sigset_t = u32;
    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigset_t {
        bits: [u32; 4],
    }

    // This structure has more fields, but we're not all that interested in
    // them.
    #[repr(C)]
    #[derive(Copy)]
    pub struct siginfo {
        pub si_signo: libc::c_int,
        pub si_errno: libc::c_int,
        pub si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    #[repr(C)]
    #[allow(missing_copy_implementations)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        sa_tramp: *mut libc::c_void,
        pub sa_mask: sigset_t,
        pub sa_flags: SockFlag,
    }

    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_flags: SockFlag,
        pub sa_mask: sigset_t,
    }

}

mod ffi {
    use libc;
    use super::signal::{sigaction, sigset_t};

    #[allow(improper_ctypes)]
    extern {
        pub fn sigaction(signum: libc::c_int,
                         act: *const sigaction,
                         oldact: *mut sigaction) -> libc::c_int;

        pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
        pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
        pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;

        pub fn kill(pid: libc::pid_t, signum: libc::c_int) -> libc::c_int;
    }
}

#[derive(Copy)]
pub struct SigSet {
    sigset: sigset_t
}

pub type SigNum = libc::c_int;

impl SigSet {
    pub fn empty() -> SigSet {
        let mut sigset = unsafe { mem::uninitialized::<sigset_t>() };
        let _ = unsafe { ffi::sigemptyset(&mut sigset as *mut sigset_t) };

        SigSet { sigset: sigset }
    }

    pub fn add(&mut self, signum: SigNum) -> SysResult<()> {
        let res = unsafe { ffi::sigaddset(&mut self.sigset as *mut sigset_t, signum) };

        if res < 0 {
            return Err(SysError::last());
        }

        Ok(())
    }

    pub fn remove(&mut self, signum: SigNum) -> SysResult<()> {
        let res = unsafe { ffi::sigdelset(&mut self.sigset as *mut sigset_t, signum) };

        if res < 0 {
            return Err(SysError::last());
        }

        Ok(())
    }
}

type sigaction_t = self::signal::sigaction;

pub struct SigAction {
    sigaction: sigaction_t
}

impl SigAction {
    pub fn new(handler: extern fn(libc::c_int), flags: SockFlag, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<sigaction_t>() };
        s.sa_handler = handler;
        s.sa_flags = flags;
        s.sa_mask = mask.sigset;

        SigAction { sigaction: s }
    }
}

pub fn sigaction(signum: SigNum, sigaction: &SigAction) -> SysResult<SigAction> {
    let mut oldact = unsafe { mem::uninitialized::<sigaction_t>() };

    let res = unsafe {
        ffi::sigaction(signum, &sigaction.sigaction as *const sigaction_t, &mut oldact as *mut sigaction_t)
    };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(SigAction { sigaction: oldact })
}

pub fn kill(pid: libc::pid_t, signum: SigNum) -> SysResult<()> {
    let res = unsafe { ffi::kill(pid, signum) };

    if res < 0 {
        return Err(SysError::last());
    }

    Ok(())
}
<|endoftext|>


<commit_before>use cpu;
use cpu::Cpu;
use cpu::decoder_arm as arm;

#[inline(always)]
fn decode_addressing_mode(instr_data: u32, cpu: &mut Cpu) -> (u32, u32) {
    let instr_data = arm::ldm_1::InstrDesc::new(instr_data);

    let register_list = bf!(instr_data.register_list);
    let num_registers = register_list.count_ones();

    let p_bit = bf!(instr_data.p_bit) == 1;
    let u_bit = bf!(instr_data.u_bit) == 1;
    let rn_val = cpu.regs[bf!(instr_data.rn) as usize];

    if !p_bit && u_bit {
        // Increment after
        return (rn_val, rn_val + num_registers * 4)
    } else if p_bit && u_bit {
        // Increment before
        return (rn_val + 4, rn_val + num_registers * 4)
    } else if !p_bit && !u_bit {
        // Decrement after
        return (rn_val - num_registers * 4 + 4, rn_val - num_registers * 4)
    } else if p_bit && !u_bit {
        // Decrement before
        return (rn_val - num_registers * 4, rn_val - num_registers * 4)
    } else {
        unreachable!();
    };
}

#[inline(always)]
pub fn instr_ldm(cpu: &mut Cpu, data: arm::ldm_1::InstrDesc) -> cpu::InstrStatus {
    if !cpu::cond_passed(bf!(data.cond), &cpu.cpsr) {
        return cpu::InstrStatus::InBlock;
    }

    let (mut addr, writeback) = decode_addressing_mode(data.raw(), cpu);
    let register_list = bf!(data.register_list);

    for i in 0..14 {
        if bit!(register_list, i) == 1 {
            cpu.regs[i] = cpu.memory.read::<u32>(addr);
            addr += 4;
        }
    }

    if bf!(data.w_bit) == 1 {
        cpu.regs[bf!(data.rn) as usize] = writeback;
    }

    if bit!(register_list, 15) == 1 {
        let val = cpu.memory.read::<u32>(addr);
        bf!((cpu.cpsr).thumb_bit = bit!(val, 0));
        cpu.branch(val & 0xFFFFFFFE);
        return cpu::InstrStatus::Branched;
    } else {
        return cpu::InstrStatus::InBlock;
    }
}

#[inline(always)]
pub fn instr_stm(cpu: &mut Cpu, data: arm::stm_1::InstrDesc) -> cpu::InstrStatus {
    if !cpu::cond_passed(bf!(data.cond), &cpu.cpsr) {
        return cpu::InstrStatus::InBlock;
    }

    let (mut addr, writeback) = decode_addressing_mode(data.raw(), cpu);
    let register_list = bf!(data.register_list);

    for i in 0..15 {
        if bit!(register_list, i) == 1 {
            cpu.memory.write::<u32>(addr, cpu.regs[i]);
            addr += 4;
        }
    }

    if bf!(data.w_bit) == 1 {
        cpu.regs[bf!(data.rn) as usize] = writeback;
    }

    cpu::InstrStatus::InBlock
}

#[inline(always)]
pub fn ldm_1(cpu: &mut Cpu, data: arm::ldm_1::InstrDesc) -> cpu::InstrStatus {
    instr_ldm(cpu, data)
}

#[inline(always)]
pub fn ldm_2(cpu: &mut Cpu, data: arm::ldm_2::InstrDesc) -> cpu::InstrStatus {
    instr_ldm(cpu, arm::ldm_1::InstrDesc::new(data.raw()))
}

#[inline(always)]
pub fn ldm_3(cpu: &mut Cpu, data: arm::ldm_3::InstrDesc) -> cpu::InstrStatus {
    instr_ldm(cpu, arm::ldm_1::InstrDesc::new(data.raw()))
}

#[inline(always)]
pub fn stm_1(cpu: &mut Cpu, data: arm::stm_1::InstrDesc) -> cpu::InstrStatus {
    instr_stm(cpu, data)
}

#[inline(always)]
pub fn stm_2(cpu: &mut Cpu, data: arm::stm_2::InstrDesc) -> cpu::InstrStatus {
    instr_stm(cpu, arm::stm_1::InstrDesc::new(data.raw()))
}<commit_msg>Fix LDM, STM off-by-one errors<commit_after>use cpu;
use cpu::Cpu;
use cpu::decoder_arm as arm;

#[inline(always)]
fn decode_addressing_mode(instr_data: u32, cpu: &mut Cpu) -> (u32, u32) {
    let instr_data = arm::ldm_1::InstrDesc::new(instr_data);

    let register_list = bf!(instr_data.register_list);
    let num_registers = register_list.count_ones();

    let p_bit = bf!(instr_data.p_bit) == 1;
    let u_bit = bf!(instr_data.u_bit) == 1;
    let rn_val = cpu.regs[bf!(instr_data.rn) as usize];

    match (p_bit, u_bit) {
        (false, true)  => (rn_val, rn_val + num_registers * 4), // Increment after
        (true, true)   => (rn_val + 4, rn_val + num_registers * 4), // Increment before
        (false, false) => (rn_val - num_registers * 4 + 4, rn_val - num_registers * 4), // Decrement after
        (true, false)  => (rn_val - num_registers * 4, rn_val - num_registers * 4) // Decrement before
    }
}

#[inline(always)]
pub fn instr_ldm(cpu: &mut Cpu, data: arm::ldm_1::InstrDesc) -> cpu::InstrStatus {
    if !cpu::cond_passed(bf!(data.cond), &cpu.cpsr) {
        return cpu::InstrStatus::InBlock;
    }

    let (mut addr, writeback) = decode_addressing_mode(data.raw(), cpu);
    let register_list = bf!(data.register_list);

    for i in 0..15 {
        if bit!(register_list, i) == 1 {
            cpu.regs[i] = cpu.memory.read::<u32>(addr);
            addr += 4;
        }
    }

    if bf!(data.w_bit) == 1 {
        cpu.regs[bf!(data.rn) as usize] = writeback;
    }

    if bit!(register_list, 15) == 1 {
        let val = cpu.memory.read::<u32>(addr);
        bf!((cpu.cpsr).thumb_bit = bit!(val, 0));
        cpu.branch(val & 0xFFFFFFFE);
        return cpu::InstrStatus::Branched;
    } else {
        return cpu::InstrStatus::InBlock;
    }
}

#[inline(always)]
pub fn instr_stm(cpu: &mut Cpu, data: arm::stm_1::InstrDesc) -> cpu::InstrStatus {
    if !cpu::cond_passed(bf!(data.cond), &cpu.cpsr) {
        return cpu::InstrStatus::InBlock;
    }

    let (mut addr, writeback) = decode_addressing_mode(data.raw(), cpu);
    let register_list = bf!(data.register_list);

    for i in 0..16 {
        if bit!(register_list, i) == 1 {
            cpu.memory.write::<u32>(addr, cpu.regs[i]);
            addr += 4;
        }
    }

    if bf!(data.w_bit) == 1 {
        cpu.regs[bf!(data.rn) as usize] = writeback;
    }

    cpu::InstrStatus::InBlock
}

#[inline(always)]
pub fn ldm_1(cpu: &mut Cpu, data: arm::ldm_1::InstrDesc) -> cpu::InstrStatus {
    instr_ldm(cpu, data)
}

#[inline(always)]
pub fn ldm_2(cpu: &mut Cpu, data: arm::ldm_2::InstrDesc) -> cpu::InstrStatus {
    instr_ldm(cpu, arm::ldm_1::InstrDesc::new(data.raw()))
}

#[inline(always)]
pub fn ldm_3(cpu: &mut Cpu, data: arm::ldm_3::InstrDesc) -> cpu::InstrStatus {
    instr_ldm(cpu, arm::ldm_1::InstrDesc::new(data.raw()))
}

#[inline(always)]
pub fn stm_1(cpu: &mut Cpu, data: arm::stm_1::InstrDesc) -> cpu::InstrStatus {
    instr_stm(cpu, data)
}

#[inline(always)]
pub fn stm_2(cpu: &mut Cpu, data: arm::stm_2::InstrDesc) -> cpu::InstrStatus {
    instr_stm(cpu, arm::stm_1::InstrDesc::new(data.raw()))
}<|endoftext|>


<commit_before>use rand::StdRng;
use rand::Rng;
use rand::SeedableRng;
use std::iter;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::HashMap;
use super::terrain::TerrainType;
use super::location::Location;
use super::mapgen;
use super::{AreaSpec};
use super::components::{Category};
use super::spawn::Spawn;

// Note to maintainer: Due to the way serialization works, Area *must* be
// generated to have exactly the same contents every time given the same seed
// value. That means absolutely no outside sources of randomness. Only use an
// internal generator initialized with the given seed value. And watch out for
// surprise randomness. A map generator in a previous project used memory
// addresses of temporary structures as indexing keys, and ended up with a
// nondeterminism bug that depended on the numerical order of the arbitrary
// address values.

#[derive(Copy, Clone, RustcDecodable, RustcEncodable)]
pub struct AreaSeed {
    pub rng_seed: u32,
    pub spec: AreaSpec,
}

#[derive(Clone)]
/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    /// Random number generator seed. Must uniquely define the Area contents.
    pub seed: AreaSeed,
    /// Stored terrain.
    pub terrain: HashMap<Location, TerrainType>,
    /// Valid slots to spawn things in, basically open floor and connected to
    /// areas the player can reach. (Does not handle stuff like monsters that
    /// spawn in water for now.)
    _open_slots: Vec<Location>,
    /// Where the player should enter the area.
    player_entrance: Location,
    /// Non-player entities to create when first initializing the map.
    spawns: Vec<(Spawn, Location)>,
}

impl Decodable for Area {
    fn decode<D: Decoder>(d: &mut D) -> Result<Area, D::Error> {
        let seed: AreaSeed = try!(Decodable::decode(d));
        Ok(Area::new(seed.rng_seed, seed.spec))
    }
}

impl Encodable for Area {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.seed.encode(s)
    }
}

impl Area {
    pub fn new(rng_seed: u32, spec: AreaSpec) -> Area {
        let num_mobs = 32;
        let num_items = 12;

        let mut terrain = HashMap::new();
        let mut rng: StdRng = SeedableRng::from_seed(&[rng_seed as usize + spec.depth as usize][..]);
        mapgen::gen_herringbone(
            &mut rng,
            &spec,
            |p, t| {terrain.insert(Location::new(0, 0) + p, t);});

        // Generate open slots that can be used to spawn stuff.

        // No connectivity analysis yet, trusting that herringbone map has
        // total connectivity. Later on, use Dijkstra map that spreads from
        // entrance/exit as a reachability floodfill to do something cleverer
        // here.
        let mut opens: Vec<Location> = terrain.iter()
            .filter(|&(_, &t)| t.valid_spawn_spot())
            .map(|(&loc, _)| loc)
            .collect();
        rng.shuffle(opens.as_mut_slice());

        let entrance = opens.pop().unwrap();

        let mut spawns = vec![];

        // XXX: copy-pasting the space-finding code.
        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Mob], vec![spec.biome]))
            .take(num_mobs)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Item], vec![spec.biome]))
            .take(num_items)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        Area {
            seed: AreaSeed { rng_seed: rng_seed, spec: spec },
            terrain: terrain,
            _open_slots: opens,
            player_entrance: entrance,
            spawns: spawns,
        }
    }

    /// Return terrain at given location.
    pub fn terrain(&self, loc: Location) -> TerrainType {
        match self.terrain.get(&loc) {
            Some(&t) => t,
            None => self.default_terrain(loc)
        }
    }

    /// List the objects that should be hatched in the world during init. This
    /// is tied to map generation, so it goes in the area module.
    pub fn get_spawns(&self) -> Vec<(Spawn, Location)> { self.spawns.clone() }

    pub fn player_entrance(&self) -> Location {
        self.player_entrance
    }

    fn default_terrain(&self, _loc: Location) -> TerrainType {
        self.seed.spec.biome.default_terrain()
    }
}
<commit_msg>Fix nondeterminism in map generation<commit_after>use rand::StdRng;
use rand::Rng;
use rand::SeedableRng;
use std::iter;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::HashMap;
use super::terrain::TerrainType;
use super::location::Location;
use super::mapgen;
use super::{AreaSpec};
use super::components::{Category};
use super::spawn::Spawn;

// Note to maintainer: Due to the way serialization works, Area *must* be
// generated to have exactly the same contents every time given the same seed
// value. That means absolutely no outside sources of randomness. Only use an
// internal generator initialized with the given seed value. And watch out for
// surprise randomness. A map generator in a previous project used memory
// addresses of temporary structures as indexing keys, and ended up with a
// nondeterminism bug that depended on the numerical order of the arbitrary
// address values.

#[derive(Copy, Clone, RustcDecodable, RustcEncodable)]
pub struct AreaSeed {
    pub rng_seed: u32,
    pub spec: AreaSpec,
}

#[derive(Clone)]
/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    /// Random number generator seed. Must uniquely define the Area contents.
    pub seed: AreaSeed,
    /// Stored terrain.
    pub terrain: HashMap<Location, TerrainType>,
    /// Valid slots to spawn things in, basically open floor and connected to
    /// areas the player can reach. (Does not handle stuff like monsters that
    /// spawn in water for now.)
    _open_slots: Vec<Location>,
    /// Where the player should enter the area.
    player_entrance: Location,
    /// Non-player entities to create when first initializing the map.
    spawns: Vec<(Spawn, Location)>,
}

impl Decodable for Area {
    fn decode<D: Decoder>(d: &mut D) -> Result<Area, D::Error> {
        let seed: AreaSeed = try!(Decodable::decode(d));
        Ok(Area::new(seed.rng_seed, seed.spec))
    }
}

impl Encodable for Area {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        self.seed.encode(s)
    }
}

impl Area {
    pub fn new(rng_seed: u32, spec: AreaSpec) -> Area {
        let num_mobs = 32;
        let num_items = 12;

        let mut terrain = HashMap::new();
        let mut rng: StdRng = SeedableRng::from_seed(&[rng_seed as usize + spec.depth as usize][..]);
        mapgen::gen_herringbone(
            &mut rng,
            &spec,
            |p, t| {terrain.insert(Location::new(0, 0) + p, t);});

        // Generate open slots that can be used to spawn stuff.

        // No connectivity analysis yet, trusting that herringbone map has
        // total connectivity. Later on, use Dijkstra map that spreads from
        // entrance/exit as a reachability floodfill to do something cleverer
        // here.
        let mut opens: Vec<Location> = terrain.iter()
            .filter(|&(_, &t)| t.valid_spawn_spot())
            .map(|(&loc, _)| loc)
            .collect();
        // Gotta sort it first to keep things deterministic.
        opens.sort();
        rng.shuffle(opens.as_mut_slice());

        let entrance = opens.pop().unwrap();

        let mut spawns = vec![];

        // XXX: copy-pasting the space-finding code.
        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Mob], vec![spec.biome]))
            .take(num_mobs)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        spawns.extend(
            iter::repeat(Spawn::new(spec.depth, vec![Category::Item], vec![spec.biome]))
            .take(num_items)
            .filter_map(|spawn|
            if let Some(loc) = opens.pop() { Some((spawn, loc)) } else { None }));

        Area {
            seed: AreaSeed { rng_seed: rng_seed, spec: spec },
            terrain: terrain,
            _open_slots: opens,
            player_entrance: entrance,
            spawns: spawns,
        }
    }

    /// Return terrain at given location.
    pub fn terrain(&self, loc: Location) -> TerrainType {
        match self.terrain.get(&loc) {
            Some(&t) => t,
            None => self.default_terrain(loc)
        }
    }

    /// List the objects that should be hatched in the world during init. This
    /// is tied to map generation, so it goes in the area module.
    pub fn get_spawns(&self) -> Vec<(Spawn, Location)> { self.spawns.clone() }

    pub fn player_entrance(&self) -> Location {
        self.player_entrance
    }

    fn default_terrain(&self, _loc: Location) -> TerrainType {
        self.seed.spec.biome.default_terrain()
    }
}
<|endoftext|>


<commit_before>#[allow(dead_code)]
use xml;
use xml::reader::events::XmlEvent;
use std::borrow::Cow;

#[derive(Debug, PartialEq)]
pub enum XmlParam {
    Integer(i32),
    Double(i32),
    XmlString(String),
    Boolean(bool),
    Array(Vec<XmlParam>)
    // Not handling dateTime.iso8601 base64 or struct types
}

enum XmlParserState {
    Idle,
    MethodName,
    ParamInt
}

pub struct XmlRequest<'a> {
    method_name: Cow<'a, str>,
    params: Vec<XmlParam>
}

impl<'a> XmlRequest<'a> {
    pub fn new() -> XmlRequest<'a> {
        XmlRequest { method_name: Cow::Borrowed(""), params: Vec::new() }
    }

    pub fn parse_xmlrpc_request(&mut self, request_str: &str) {
        let mut parser = xml::EventReader::from_str(request_str);
        let mut state = XmlParserState::Idle;

        loop {
            state = match state {
                XmlParserState::Idle => {
                    match parser.next() {
                        XmlEvent::EndDocument | XmlEvent::Error(_) => break,
                        XmlEvent::StartDocument { .. } => XmlParserState::Idle,
                        XmlEvent::StartElement { name, .. } => {
                            match name.local_name.as_ref() {
                                "methodName" => {
                                    XmlParserState::MethodName
                                }
                                "i4" | "int" => XmlParserState::ParamInt,
                                //TODO: handle all opening tags
                                _ => XmlParserState::Idle
                            }
                        },
                        // TODO: match the closing element.
                        _ => {
                            println!("Non start element");
                            XmlParserState::Idle
                        }
                    }
                }
                XmlParserState::MethodName => {
                    match parser.next() {
                        XmlEvent::Characters(text) => {
                            println!("Method name characters: {}", text);
                            self.method_name = Cow::Owned(text);
                            XmlParserState::MethodName
                        },
                        _ => {
                            XmlParserState::Idle
                        }
                    }
                }
                XmlParserState::ParamInt => {
                    match parser.next() {
                        XmlEvent::Characters(text) => {
                            println!("Param Int: {}", text);
                            self.params.push(XmlParam::Integer(text.parse::<i32>().unwrap()));
                            XmlParserState::Idle
                        }
                        _ => XmlParserState::Idle
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::XmlRequest;
    use super::XmlParam;

    #[test]
    fn test_parse_xml() {
        let request_str= "\
        <?xml version=\"1.0\"?>\n\
        <methodCall>\n\
          <methodName>life</methodName>\n\
          <params>\n\
            <param>\n\
              <value><i4>42</i4></value>\n\
            </param>\n\
          </params>\n\
        </methodCall>\n";
        let mut xml_request_parser = XmlRequest::new();
        xml_request_parser.parse_xmlrpc_request(request_str);
        assert_eq!(xml_request_parser.method_name, "life");
        assert_eq!(xml_request_parser.params, [XmlParam::Integer(42)]);
    }
}
<commit_msg>Parse boolean, float and string params<commit_after>#[allow(dead_code)]
use xml;
use xml::reader::events::XmlEvent;
use std::borrow::Cow;

#[derive(Debug, PartialEq)]
pub enum XmlParam {
    Integer(i32),
    Double(f64),
    XmlString(String),
    Boolean(bool),
    Array(Vec<XmlParam>)
    // Not handling dateTime.iso8601 base64 or struct types
}

enum XmlParserState {
    Idle,
    MethodName,
    ParamInt,
    ParamBoolean,
    ParamFloat,
    ParamString
}

pub struct XmlRequest<'a> {
    method_name: Cow<'a, str>,
    params: Vec<XmlParam>
}

impl<'a> XmlRequest<'a> {
    pub fn new() -> XmlRequest<'a> {
        XmlRequest { method_name: Cow::Borrowed(""), params: Vec::new() }
    }

    pub fn parse_xmlrpc_request(&mut self, request_str: &str) {
        let mut parser = xml::EventReader::from_str(request_str);
        let mut state = XmlParserState::Idle;

        loop {
            state = match state {
                XmlParserState::Idle => {
                    match parser.next() {
                        XmlEvent::EndDocument | XmlEvent::Error(_) => break,
                        XmlEvent::StartDocument { .. } => XmlParserState::Idle,
                        XmlEvent::StartElement { name, .. } => {
                            match name.local_name.as_ref() {
                                "methodName" => {
                                    XmlParserState::MethodName
                                }
                                "i4" | "int" => XmlParserState::ParamInt,
                                "boolean" => XmlParserState::ParamBoolean,
                                "double" => XmlParserState::ParamFloat,
                                "string" => XmlParserState::ParamString,
                                //TODO: handle all opening tags
                                _ => XmlParserState::Idle
                            }
                        },
                        // TODO: match the closing element.
                        _ => {
                            println!("Non start element");
                            XmlParserState::Idle
                        }
                    }
                }
                XmlParserState::MethodName => {
                    match parser.next() {
                        XmlEvent::Characters(text) => {
                            println!("Method name characters: {}", text);
                            self.method_name = Cow::Owned(text);
                            XmlParserState::MethodName
                        },
                        _ => {
                            XmlParserState::Idle
                        }
                    }
                }
                XmlParserState::ParamInt => {
                    match parser.next() {
                        XmlEvent::Characters(text) => {
                            println!("Param Int: {}", text);
                            self.params.push(XmlParam::Integer(text.parse::<i32>().unwrap()));
                            XmlParserState::Idle
                        }
                        _ => XmlParserState::Idle
                    }
                },
                XmlParserState::ParamString => {
                    match parser.next() {
                        XmlEvent::Characters(text) => {
                            println!("Param String: {}", text);
                            self.params.push(XmlParam::XmlString(text));
                            XmlParserState::Idle
                        }
                        _ => XmlParserState::Idle
                    }
                },
                XmlParserState::ParamBoolean => {
                    match parser.next() {
                        XmlEvent::Characters(text) => {
                            println!("Param Boolean: {}", text);
                            if text == "1" {
                                self.params.push(XmlParam::Boolean(true));
                            } else {
                                self.params.push(XmlParam::Boolean(false));
                            }
                            XmlParserState::Idle
                        }
                        _ => XmlParserState::Idle
                    }
                },
                XmlParserState::ParamFloat => {
                    match parser.next() {
                        XmlEvent::Characters(text) => {
                            println!("Param float: {}", text);
                            self.params.push(XmlParam::Double(text.parse::<f64>().unwrap()));
                            XmlParserState::Idle
                        }
                        _ => XmlParserState::Idle
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::XmlRequest;
    use super::XmlParam;

    #[test]
    fn test_parse_xml() {
        let request_str= "\
        <?xml version=\"1.0\"?>\n\
        <methodCall>\n\
          <methodName>life</methodName>\n\
          <params>\n\
            <param>\n\
              <value><i4>42</i4></value>\n\
            </param>\n\
            <param>\n\
              <value><double>3.14</double></value>\n\
            </param>\n\
            <param>\n\
              <value><boolean>1</boolean></value>\n\
            </param>\n\
            <param>\n\
              <value><string>hola</string></value>\n\
            </param>\n\
          </params>\n\
        </methodCall>\n";
        let mut xml_request_parser = XmlRequest::new();
        xml_request_parser.parse_xmlrpc_request(request_str);
        assert_eq!(xml_request_parser.method_name, "life");
        assert_eq!(xml_request_parser.params, [XmlParam::Integer(42), XmlParam::Double(3.14),
                                               XmlParam::Boolean(true), XmlParam::XmlString("hola".to_string())]);
    }
}
<|endoftext|>


<commit_before>mat!(uni_literal, r"☃", "☃", Some((0, 3)));
mat!(uni_literal_plus, r"☃+", "☃", Some((0, 3)));
mat!(uni_literal_casei_plus, r"(?i)☃+", "☃", Some((0, 3)));
mat!(uni_class_plus, r"[☃Ⅰ]+", "☃", Some((0, 3)));
mat!(uni_one, r"\pN", "Ⅰ", Some((0, 3)));
mat!(uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8)));
mat!(uni_not, r"\PN+", "abⅠ", Some((0, 2)));
mat!(uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2)));
mat!(uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5)));
mat!(uni_case, r"(?i)Δ", "δ", Some((0, 2)));
mat!(uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8)));
mat!(uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10)));
mat!(uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10)));
mat!(uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10)));

// Test the Unicode friendliness of Perl character classes.
mat!(uni_perl_w, r"\w+", "dδd", Some((0, 4)));
mat!(uni_perl_w_not, r"\w+", "⥡", None);
mat!(uni_perl_w_neg, r"\W+", "⥡", Some((0, 3)));
mat!(uni_perl_d, r"\d+", "1२३9", Some((0, 8)));
mat!(uni_perl_d_not, r"\d+", "Ⅱ", None);
mat!(uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3)));
mat!(uni_perl_s, r"\s+", " ", Some((0, 3)));
mat!(uni_perl_s_not, r"\s+", "☃", None);
mat!(uni_perl_s_neg, r"\S+", "☃", Some((0, 3)));

// And do the same for word boundaries.
mat!(uni_boundary_none, r"\d\b", "6δ", None);
mat!(uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1)));
mat!(uni_not_boundary_none, r"\d\B", "6δ", Some((0, 1)));
mat!(uni_not_boundary_ogham, r"\d\B", "6 ", None);
<commit_msg>tests: add Unicode general category tests<commit_after>mat!(uni_literal, r"☃", "☃", Some((0, 3)));
mat!(uni_literal_plus, r"☃+", "☃", Some((0, 3)));
mat!(uni_literal_casei_plus, r"(?i)☃+", "☃", Some((0, 3)));
mat!(uni_class_plus, r"[☃Ⅰ]+", "☃", Some((0, 3)));
mat!(uni_one, r"\pN", "Ⅰ", Some((0, 3)));
mat!(uni_mixed, r"\pN+", "Ⅰ1Ⅱ2", Some((0, 8)));
mat!(uni_not, r"\PN+", "abⅠ", Some((0, 2)));
mat!(uni_not_class, r"[\PN]+", "abⅠ", Some((0, 2)));
mat!(uni_not_class_neg, r"[^\PN]+", "abⅠ", Some((2, 5)));
mat!(uni_case, r"(?i)Δ", "δ", Some((0, 2)));
mat!(uni_case_upper, r"\p{Lu}+", "ΛΘΓΔα", Some((0, 8)));
mat!(uni_case_upper_nocase_flag, r"(?i)\p{Lu}+", "ΛΘΓΔα", Some((0, 10)));
mat!(uni_case_upper_nocase, r"\p{L}+", "ΛΘΓΔα", Some((0, 10)));
mat!(uni_case_lower, r"\p{Ll}+", "ΛΘΓΔα", Some((8, 10)));

// Test the Unicode friendliness of Perl character classes.
mat!(uni_perl_w, r"\w+", "dδd", Some((0, 4)));
mat!(uni_perl_w_not, r"\w+", "⥡", None);
mat!(uni_perl_w_neg, r"\W+", "⥡", Some((0, 3)));
mat!(uni_perl_d, r"\d+", "1२३9", Some((0, 8)));
mat!(uni_perl_d_not, r"\d+", "Ⅱ", None);
mat!(uni_perl_d_neg, r"\D+", "Ⅱ", Some((0, 3)));
mat!(uni_perl_s, r"\s+", " ", Some((0, 3)));
mat!(uni_perl_s_not, r"\s+", "☃", None);
mat!(uni_perl_s_neg, r"\S+", "☃", Some((0, 3)));

// And do the same for word boundaries.
mat!(uni_boundary_none, r"\d\b", "6δ", None);
mat!(uni_boundary_ogham, r"\d\b", "6 ", Some((0, 1)));
mat!(uni_not_boundary_none, r"\d\B", "6δ", Some((0, 1)));
mat!(uni_not_boundary_ogham, r"\d\B", "6 ", None);

// Test general categories.
//
// We should test more, but there's a lot. Write a script to generate more of
// these tests.
mat!(uni_class_gencat_cased_letter,
     r"\p{Cased_Letter}", "Ａ", Some((0, 3)));
mat!(uni_class_gencat_close_punctuation,
     r"\p{Close_Punctuation}", "❯", Some((0, 3)));
mat!(uni_class_gencat_connector_punctuation,
     r"\p{Connector_Punctuation}", "⁀", Some((0, 3)));
mat!(uni_class_gencat_control,
     r"\p{Control}", "\u{9f}", Some((0, 2)));
mat!(uni_class_gencat_currency_symbol,
     r"\p{Currency_Symbol}", "￡", Some((0, 3)));
mat!(uni_class_gencat_dash_punctuation,
     r"\p{Dash_Punctuation}", "〰", Some((0, 3)));
mat!(uni_class_gencat_decimal_numer,
     r"\p{Decimal_Number}", "𑓙", Some((0, 4)));
mat!(uni_class_gencat_enclosing_mark,
     r"\p{Enclosing_Mark}", "\u{A672}", Some((0, 3)));
mat!(uni_class_gencat_final_punctuation,
     r"\p{Final_Punctuation}", "⸡", Some((0, 3)));
mat!(uni_class_gencat_format,
     r"\p{Format}", "\u{E007F}", Some((0, 4)));
mat!(uni_class_gencat_initial_punctuation,
     r"\p{Initial_Punctuation}", "⸜", Some((0, 3)));
mat!(uni_class_gencat_letter,
     r"\p{Letter}", "Έ", Some((0, 2)));
mat!(uni_class_gencat_letter_number,
     r"\p{Letter_Number}", "ↂ", Some((0, 3)));
mat!(uni_class_gencat_line_separator,
     r"\p{Line_Separator}", "\u{2028}", Some((0, 3)));
mat!(uni_class_gencat_lowercase_letter,
     r"\p{Lowercase_Letter}", "ϛ", Some((0, 2)));
mat!(uni_class_gencat_mark,
     r"\p{Mark}", "\u{E01EF}", Some((0, 4)));
mat!(uni_class_gencat_math,
     r"\p{Math}", "⋿", Some((0, 3)));
mat!(uni_class_gencat_modifier_letter,
     r"\p{Modifier_Letter}", "𖭃", Some((0, 4)));
mat!(uni_class_gencat_modifier_symbol,
     r"\p{Modifier_Symbol}", "🏿", Some((0, 4)));
mat!(uni_class_gencat_nonspacing_mark,
     r"\p{Nonspacing_Mark}", "\u{1E94A}", Some((0, 4)));
mat!(uni_class_gencat_number,
     r"\p{Number}", "⓿", Some((0, 3)));
mat!(uni_class_gencat_open_punctuation,
     r"\p{Open_Punctuation}", "｟", Some((0, 3)));
mat!(uni_class_gencat_other,
     r"\p{Other}", "\u{bc9}", Some((0, 3)));
mat!(uni_class_gencat_other_letter,
     r"\p{Other_Letter}", "ꓷ", Some((0, 3)));
mat!(uni_class_gencat_other_number,
     r"\p{Other_Number}", "㉏", Some((0, 3)));
mat!(uni_class_gencat_other_punctuation,
     r"\p{Other_Punctuation}", "𞥞", Some((0, 4)));
mat!(uni_class_gencat_other_symbol,
     r"\p{Other_Symbol}", "⅌", Some((0, 3)));
mat!(uni_class_gencat_paragraph_separator,
     r"\p{Paragraph_Separator}", "\u{2029}", Some((0, 3)));
mat!(uni_class_gencat_private_use,
     r"\p{Private_Use}", "\u{10FFFD}", Some((0, 4)));
mat!(uni_class_gencat_punctuation,
     r"\p{Punctuation}", "𑁍", Some((0, 4)));
mat!(uni_class_gencat_separator,
     r"\p{Separator}", "\u{3000}", Some((0, 3)));
mat!(uni_class_gencat_space_separator,
     r"\p{Space_Separator}", "\u{205F}", Some((0, 3)));
mat!(uni_class_gencat_spacing_mark,
     r"\p{Spacing_Mark}", "\u{16F7E}", Some((0, 4)));
mat!(uni_class_gencat_symbol,
     r"\p{Symbol}", "⯈", Some((0, 3)));
mat!(uni_class_gencat_titlecase_letter,
     r"\p{Titlecase_Letter}", "ῼ", Some((0, 3)));
mat!(uni_class_gencat_unassigned,
     r"\p{Unassigned}", "\u{10FFFF}", Some((0, 4)));
mat!(uni_class_gencat_uppercase_letter,
     r"\p{Uppercase_Letter}", "Ꝋ", Some((0, 3)));
<|endoftext|>