<commit_before>#[allow(default_methods)];  // For the benefit of Server. Hopefully it'll work.

extern mod extra;

use std::option::Option;
use std::rt::io::{Listener};
use std::rt::io::net::ip::IpAddr;
use std::rt::io::{io_error, IoError};

#[cfg(newrt)]
pub use std::rt::io::net::tcp::{TcpListener, TcpStream};

#[cfg(not(newrt))]
pub use TcpListener = super::adapter::ExtraNetTcpListener;
#[cfg(not(newrt))]
pub use TcpStream = super::adapter::ExtraNetTcpStream;

use super::request::{RequestBuffer, Request};
use super::response::ResponseWriter;

// TODO: when mozilla/rust#7661 is resolved, assuming also that specifying inheritance of kinds for
// the trait works:
// - Scrap ServerUtil (including any using it into the local scope)
// - Change "trait Server" to "trait Server: Send"
// - Shift the serve_forever method into Server
pub trait Server {
	pub fn handle_request(&self, request: Request, response: ResponseWriter) -> ();

	// XXX: this could also be implemented on the serve methods
	pub fn get_config(&self) -> Config;
}

pub trait ServerUtil {
    pub fn serve_forever(self);
}

impl<T: Send + Server> ServerUtil for T {
	/**
	 * Attempt to bind to the address and port and start serving forever.
	 *
	 * This will only return if the initial connection fails or something else blows up.
	 */
    pub fn serve_forever(self) {
        let config = self.get_config();
        debug!("About to bind to %?", config.bind_address);
        let mut optlistener = TcpListener::bind(config.bind_address);
        debug!("Bind attempt completed");
        match optlistener {
            None => {
                debug!("listen failed :-(");
                return;
            }
            Some(ref mut listener) => {
                debug!("listening");
                loop {
                    // OK, we're sort of shadowing an IoError here. Perhaps this should be done in a
                    // separate task so that it can safely fail...
                    let mut error : Option<IoError> = None;
                    let mut optstream : Option<TcpStream> = None;
                    io_error::cond.trap(|e: IoError| {
                        error = Some(e);
                    }).in(|| {
                        optstream = listener.accept();
                    });
                    match optstream {
                        None => {
                            debug!("accept failed: %?", error);
                            // Question: is this the correct thing to do? We should probably be more
                            // intelligent, for there are some accept failures that are likely to be
                            // permanent, such that continuing would be a very bad idea, such as
                            // ENOBUFS/ENOMEM; and some where it should just be ignored, e.g.
                            // ECONNABORTED. TODO.
                            loop;
                        },
                        Some(stream) => {
                            debug!("accepted connection, got %?", stream);
                            let stream = ::std::cell::Cell::new(stream);
                            do spawn {
                                let mut stream = ~stream.take();
                                //RequestBuffer::new(stream);
                                let request = Request::get(~RequestBuffer::new(stream));
                                let mut response = ResponseWriter::new(*stream);
                                match request {
                                    Ok(request) => {
                                        self.handle_request(request, response);
                                        // Sorry, only single-threaded at present:
                                        // blocked on mozilla/rust#7661
                                    },
                                    Err(status) => {
                                        response.status = status;
                                        response.write_headers();
                                    },
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

pub struct Config {
	bind_address: IpAddr,
}

/*
pub struct SimpleServer {
	config: Config,
}

impl Server for SimpleServer {
	pub fn get_config(&self) -> Config {
		self.config
	}
}

impl SimpleServer {
	/// Create a `Server` bound to all IPv4 addresses on port 80
	#[inline]
	pub fn new_public(callback: &'self T) -> Server<'self, T> {
		Server {
			bind_address: ip::v4::parse_addr("0.0.0.0"),
			port: 80,
			backlog: 100,
			callback: callback,
		}
	}

	/// Create a `Server` with the specified config parameters
	#[inline]
	pub fn new(bind_address: ip::IpAddr, port: uint, callback: &'self T) -> Server<'self, T> {
		SimpleServer {
			config: Config {
				bind_address: bind_address,
				port: port,
				backlog: 100,
				callback: callback,
			}
		}
	}
}
*/
<commit_msg>"Improve server." ;-)<commit_after>#[allow(default_methods)];  // For the benefit of Server. Hopefully it'll work.

extern mod extra;

use std::rt::io::Listener;
use std::rt::io::net::ip::{IpAddr, Ipv4};
use std::rt::io::io_error;

#[cfg(newrt)]
pub use std::rt::io::net::tcp::{TcpListener, TcpStream};

#[cfg(not(newrt))]
pub use TcpListener = super::adapter::ExtraNetTcpListener;
#[cfg(not(newrt))]
pub use TcpStream = super::adapter::ExtraNetTcpStream;

use super::request::{RequestBuffer, Request};
use super::response::ResponseWriter;

// TODO: when mozilla/rust#7661 is resolved, assuming also that specifying inheritance of kinds for
// the trait works:
// - Scrap ServerUtil (including any using it into the local scope)
// - Change "trait Server" to "trait Server: Send"
// - Shift the serve_forever method into Server
pub trait Server {
	pub fn handle_request(&self, request: Request, response: ResponseWriter) -> ();

	// XXX: this could also be implemented on the serve methods
	pub fn get_config(&self) -> Config;
}

/// A temporary trait to fix current deficiencies in Rust's default methods on traits.
/// You'll need to import `ServerUtil` to be able to call `serve_forever` on a Server.
pub trait ServerUtil {
    pub fn serve_forever(self);
}

impl<T: Send + Server> ServerUtil for T {
	/**
	 * Attempt to bind to the address and port and start serving forever.
	 *
	 * This will only return if the initial connection fails or something else blows up.
	 */
    pub fn serve_forever(self) {
        let config = self.get_config();
        debug!("About to bind to %?", config.bind_address);
        let mut optlistener = TcpListener::bind(config.bind_address);
        debug!("Bind attempt completed");
        match optlistener {
            None => {
                debug!("listen failed :-(");
                return;
            }
            Some(ref mut listener) => {
                debug!("listening");
                loop {
                    // OK, we're sort of shadowing an IoError here. Perhaps this should be done in a
                    // separate task so that it can safely fail...
                    let mut error = None;
                    let optstream = io_error::cond.trap(|e| {
                        error = Some(e);
                    }).in(|| {
                        listener.accept()
                    });
                    if optstream.is_none() {
                        debug!("accept failed: %?", error);
                        // Question: is this the correct thing to do? We should probably be more
                        // intelligent, for there are some accept failures that are likely to be
                        // permanent, such that continuing would be a very bad idea, such as
                        // ENOBUFS/ENOMEM; and some where it should just be ignored, e.g.
                        // ECONNABORTED. TODO.
                        loop;
                    }
                    let stream = ::std::cell::Cell::new(optstream.unwrap());
                    do spawn {
                        let mut stream = ~stream.take();
                        debug!("accepted connection, got %?", stream);
                        //RequestBuffer::new(stream);
                        let request = Request::get(~RequestBuffer::new(stream));
                        let mut response = ResponseWriter::new(*stream);
                        match request {
                            Ok(request) => {
                                self.handle_request(request, response);
                                // Sorry, only single-threaded at present:
                                // blocked on mozilla/rust#7661
                            },
                            Err(status) => {
                                response.status = status;
                                response.write_headers();
                            },
                        }
                    }
                }
            }
        }
    }
}

/// The necessary configuration for an HTTP server.
///
/// At present, only the IP address and port to bind to are needed, but it's possible that other
/// options may turn up later.
pub struct Config {
	bind_address: IpAddr,
}

/// A simple `Server`-implementing class, allowing code to be written in an imperative style.
pub struct SimpleServer {
    config: Config,
    handler: ~fn(Request, ResponseWriter),
}

impl SimpleServer {
    /// Create a new `SimpleServer` instance with the provided members.
    pub fn new(config: Config, handler: ~fn(Request, ResponseWriter)) -> SimpleServer {
        SimpleServer {
            config: config,
            handler: handler,
        }
    }
}

impl Server for SimpleServer {
    /// Handles a request by passing it on to the structure's handler function.
    #[inline]
	pub fn handle_request(&self, request: Request, response: ResponseWriter) {
        (self.handler)(request, response);
    }

    /// Returns the structure's known config.
    #[inline]
	pub fn get_config(&self) -> Config {
        self.config
    }
}

/// Create a simple server and immediately start serving forever.
///
/// This is equivalent to
///
/// ~~~ {.rust}
/// SimpleServer::new(Config { bind_address: ip_addr }, handler).serve_forever();
/// ~~~
///
/// But it's nicer this way with `do` blocks and closures:
///
/// ~~~ {.rust}
/// do serve_forever(ip_addr) |r, mut w| {
///     // Now you can handle the request here and write the wresponse.
/// }
/// ~~~
///
/// The signature of this method is liable to change if `Config` gets more members.
// Please, pretty please, don't correct the word "wresponse".
#[inline]
pub fn serve_forever(ip_addr: IpAddr, handler: ~fn(Request, ResponseWriter)) {
    SimpleServer::new(Config { bind_address: ip_addr }, handler).serve_forever();
}

/// 0.0.0.0, port 80: publicly bound to the standard HTTP port.
/// Not recommended at present as this server is not hardened against the sort of traffic you may
/// encounter on the Internet and is vulnerable to various DoS attacks. Sit it behind a gateway.
static PUBLIC: IpAddr = Ipv4(0, 0, 0, 0, 80);
<|endoftext|>


<commit_before>use rustc_serialize::json::Json;
use chrono::{DateTime, UTC, Timelike};
use byteorder::{WriteBytesExt, BigEndian};

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct TermRef(u32);

impl TermRef {
    pub fn new(ord: u32) -> TermRef {
        TermRef(ord)
    }

    pub fn ord(&self) -> u32 {
        self.0
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum Term {
    String(String),
    Boolean(bool),
    Integer(i64),
    DateTime(DateTime<UTC>),
}

impl Term {
    pub fn from_json(json: &Json) -> Option<Term> {
        // TODO: Should be aware of mappings
        match *json {
            Json::String(ref string) => Some(Term::String(string.clone())),
            Json::Boolean(value) => Some(Term::Boolean(value)),
            Json::F64(_) => None,
            Json::I64(value) => Some(Term::Integer(value)),
            Json::U64(value) => Some(Term::Integer(value as i64)),  // FIXME
            Json::Null => None,
            Json::Array(_) => None,
            Json::Object(_) => None,
        }
    }

    pub fn as_json(&self) -> Json {
        match *self {
            Term::String(ref string) => Json::String(string.clone()),
            Term::Boolean(value) => Json::Boolean(value),
            Term::Integer(value) => Json::I64(value),
            Term::DateTime(value) => Json::String(value.to_rfc3339()),
        }
    }

    pub fn to_bytes(&self) -> Vec<u8> {
        match *self {
            Term::String(ref string) => {
                let mut bytes = Vec::with_capacity(string.len());

                for byte in string.as_bytes() {
                    bytes.push(*byte);
                }

                bytes
            },
            Term::Boolean(value) => {
                if value {
                    vec![b't']
                } else {
                    vec![b'f']
                }
            }
            Term::Integer(value) => {
                let mut bytes = Vec::with_capacity(8);
                bytes.write_i64::<BigEndian>(value).unwrap();
                bytes
            }
            Term::DateTime(value) => {
                let mut bytes = Vec::with_capacity(0);
                let timestamp = value.timestamp();
                let micros = value.nanosecond() / 1000;
                let timestamp_with_micros = timestamp * 1000000 + micros as i64;
                bytes.write_i64::<BigEndian>(timestamp_with_micros).unwrap();
                bytes
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use chrono::{DateTime, UTC, Timelike};
    use super::Term;

    #[test]
    fn test_string_to_bytes() {
        let term = Term::String("foo".to_string());

        assert_eq!(term.to_bytes(), vec![102, 111, 111])
    }

    #[test]
    fn test_hiragana_string_to_bytes() {
        let term = Term::String("こんにちは".to_string());

        assert_eq!(term.to_bytes(), vec![227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175])
    }

    #[test]
    fn test_blank_string_to_bytes() {
        let term = Term::String("".to_string());

        assert_eq!(term.to_bytes(), vec![])
    }

    #[test]
    fn test_boolean_true_to_bytes() {
        let term = Term::Boolean(true);

        // 116 = 't' in ASCII
        assert_eq!(term.to_bytes(), vec![116])
    }

    #[test]
    fn test_boolean_false_to_bytes() {
        let term = Term::Boolean(false);

        // 102 = 'f' in ASCII
        assert_eq!(term.to_bytes(), vec![102])
    }

    #[test]
    fn test_integer_to_bytes() {
        let term = Term::Integer(123);

        assert_eq!(term.to_bytes(), vec![0, 0, 0, 0, 0, 0, 0, 123])
    }

    #[test]
    fn test_negative_integer_to_bytes() {
        let term = Term::Integer(-123);

        assert_eq!(term.to_bytes(), vec![255, 255, 255, 255, 255, 255, 255, 133])
    }

    #[test]
    fn test_datetime_to_bytes() {
        let date = "2016-07-23T16:15:00+01:00".parse::<DateTime<UTC>>().unwrap();
        let term = Term::DateTime(date);

        assert_eq!(term.to_bytes(), vec![0, 5, 56, 79, 3, 191, 101, 0])
    }

    #[test]
    fn test_datetime_with_microseconds_to_bytes() {
        let mut date = "2016-07-23T16:15:00+01:00".parse::<DateTime<UTC>>().unwrap();
        date = date.with_nanosecond(123123123).unwrap();
        let term = Term::DateTime(date);

        // This is exactly 123123 higher than the result of "test_datetime_to_bytes"
        assert_eq!(term.to_bytes(), vec![0, 5, 56, 79, 3, 193, 69, 243])
    }

    #[test]
    fn test_datetime_with_different_timezone_to_bytes() {
        let date = "2016-07-23T16:15:00+02:00".parse::<DateTime<UTC>>().unwrap();
        let term = Term::DateTime(date);

        // This is exactly 3_600_000_000 lower than the result of "test_datetime_to_bytes"
        assert_eq!(term.to_bytes(), vec![0, 5, 56, 78, 45, 43, 193, 0])
    }
}
<commit_msg>Remove Term::as_json<commit_after>use rustc_serialize::json::Json;
use chrono::{DateTime, UTC, Timelike};
use byteorder::{WriteBytesExt, BigEndian};

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct TermRef(u32);

impl TermRef {
    pub fn new(ord: u32) -> TermRef {
        TermRef(ord)
    }

    pub fn ord(&self) -> u32 {
        self.0
    }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum Term {
    String(String),
    Boolean(bool),
    Integer(i64),
    DateTime(DateTime<UTC>),
}

impl Term {
    pub fn from_json(json: &Json) -> Option<Term> {
        // TODO: Should be aware of mappings
        match *json {
            Json::String(ref string) => Some(Term::String(string.clone())),
            Json::Boolean(value) => Some(Term::Boolean(value)),
            Json::F64(_) => None,
            Json::I64(value) => Some(Term::Integer(value)),
            Json::U64(value) => Some(Term::Integer(value as i64)),  // FIXME
            Json::Null => None,
            Json::Array(_) => None,
            Json::Object(_) => None,
        }
    }

    pub fn to_bytes(&self) -> Vec<u8> {
        match *self {
            Term::String(ref string) => {
                let mut bytes = Vec::with_capacity(string.len());

                for byte in string.as_bytes() {
                    bytes.push(*byte);
                }

                bytes
            },
            Term::Boolean(value) => {
                if value {
                    vec![b't']
                } else {
                    vec![b'f']
                }
            }
            Term::Integer(value) => {
                let mut bytes = Vec::with_capacity(8);
                bytes.write_i64::<BigEndian>(value).unwrap();
                bytes
            }
            Term::DateTime(value) => {
                let mut bytes = Vec::with_capacity(0);
                let timestamp = value.timestamp();
                let micros = value.nanosecond() / 1000;
                let timestamp_with_micros = timestamp * 1000000 + micros as i64;
                bytes.write_i64::<BigEndian>(timestamp_with_micros).unwrap();
                bytes
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use chrono::{DateTime, UTC, Timelike};
    use super::Term;

    #[test]
    fn test_string_to_bytes() {
        let term = Term::String("foo".to_string());

        assert_eq!(term.to_bytes(), vec![102, 111, 111])
    }

    #[test]
    fn test_hiragana_string_to_bytes() {
        let term = Term::String("こんにちは".to_string());

        assert_eq!(term.to_bytes(), vec![227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175])
    }

    #[test]
    fn test_blank_string_to_bytes() {
        let term = Term::String("".to_string());

        assert_eq!(term.to_bytes(), vec![])
    }

    #[test]
    fn test_boolean_true_to_bytes() {
        let term = Term::Boolean(true);

        // 116 = 't' in ASCII
        assert_eq!(term.to_bytes(), vec![116])
    }

    #[test]
    fn test_boolean_false_to_bytes() {
        let term = Term::Boolean(false);

        // 102 = 'f' in ASCII
        assert_eq!(term.to_bytes(), vec![102])
    }

    #[test]
    fn test_integer_to_bytes() {
        let term = Term::Integer(123);

        assert_eq!(term.to_bytes(), vec![0, 0, 0, 0, 0, 0, 0, 123])
    }

    #[test]
    fn test_negative_integer_to_bytes() {
        let term = Term::Integer(-123);

        assert_eq!(term.to_bytes(), vec![255, 255, 255, 255, 255, 255, 255, 133])
    }

    #[test]
    fn test_datetime_to_bytes() {
        let date = "2016-07-23T16:15:00+01:00".parse::<DateTime<UTC>>().unwrap();
        let term = Term::DateTime(date);

        assert_eq!(term.to_bytes(), vec![0, 5, 56, 79, 3, 191, 101, 0])
    }

    #[test]
    fn test_datetime_with_microseconds_to_bytes() {
        let mut date = "2016-07-23T16:15:00+01:00".parse::<DateTime<UTC>>().unwrap();
        date = date.with_nanosecond(123123123).unwrap();
        let term = Term::DateTime(date);

        // This is exactly 123123 higher than the result of "test_datetime_to_bytes"
        assert_eq!(term.to_bytes(), vec![0, 5, 56, 79, 3, 193, 69, 243])
    }

    #[test]
    fn test_datetime_with_different_timezone_to_bytes() {
        let date = "2016-07-23T16:15:00+02:00".parse::<DateTime<UTC>>().unwrap();
        let term = Term::DateTime(date);

        // This is exactly 3_600_000_000 lower than the result of "test_datetime_to_bytes"
        assert_eq!(term.to_bytes(), vec![0, 5, 56, 78, 45, 43, 193, 0])
    }
}
<|endoftext|>


<commit_before>//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../../std/primitive.array.html).*

#![stable(feature = "core_array", since = "1.36.0")]

use crate::borrow::{Borrow, BorrowMut};
use crate::cmp::Ordering;
use crate::convert::TryFrom;
use crate::fmt;
use crate::hash::{Hash, self};
use crate::marker::Unsize;
use crate::slice::{Iter, IterMut};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
#[unstable(feature = "fixed_size_array", issue = "27778")]
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    #[unstable(feature = "fixed_size_array", issue = "27778")]
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    #[unstable(feature = "fixed_size_array", issue = "27778")]
    fn as_mut_slice(&mut self) -> &mut [T];
}

#[unstable(feature = "fixed_size_array", issue = "27778")]
unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

/// The error type returned when a conversion from a slice to an array fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Debug, Copy, Clone)]
pub struct TryFromSliceError(());

#[stable(feature = "core_array", since = "1.36.0")]
impl fmt::Display for TryFromSliceError {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(self.__description(), f)
    }
}

impl TryFromSliceError {
    #[unstable(feature = "array_error_internals",
           reason = "available through Error trait and this method should not \
                     be exposed publicly",
           issue = "0")]
    #[inline]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        "could not convert slice to array"
    }
}

macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

// macro for implementing n-element array functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "try_from", since = "1.34.0")]
            impl<T> TryFrom<&[T]> for [T; $N] where T: Copy {
                type Error = TryFromSliceError;

                fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> {
                    <&Self>::try_from(slice).map(|r| *r)
                }
            }

            #[stable(feature = "try_from", since = "1.34.0")]
            impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_ptr() as *const [T; $N];
                        unsafe { Ok(&*ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[stable(feature = "try_from", since = "1.34.0")]
            impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_mut_ptr() as *mut [T; $N];
                        unsafe { Ok(&mut *ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<commit_msg>Auto merge of #60318 - jethrogb:jb/try-from-slice-to-infallible, r=sfackler<commit_after>//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../../std/primitive.array.html).*

#![stable(feature = "core_array", since = "1.36.0")]

use crate::borrow::{Borrow, BorrowMut};
use crate::cmp::Ordering;
use crate::convert::{Infallible, TryFrom};
use crate::fmt;
use crate::hash::{Hash, self};
use crate::marker::Unsize;
use crate::slice::{Iter, IterMut};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
#[unstable(feature = "fixed_size_array", issue = "27778")]
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    #[unstable(feature = "fixed_size_array", issue = "27778")]
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    #[unstable(feature = "fixed_size_array", issue = "27778")]
    fn as_mut_slice(&mut self) -> &mut [T];
}

#[unstable(feature = "fixed_size_array", issue = "27778")]
unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

/// The error type returned when a conversion from a slice to an array fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Debug, Copy, Clone)]
pub struct TryFromSliceError(());

#[stable(feature = "core_array", since = "1.36.0")]
impl fmt::Display for TryFromSliceError {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(self.__description(), f)
    }
}

impl TryFromSliceError {
    #[unstable(feature = "array_error_internals",
           reason = "available through Error trait and this method should not \
                     be exposed publicly",
           issue = "0")]
    #[inline]
    #[doc(hidden)]
    pub fn __description(&self) -> &str {
        "could not convert slice to array"
    }
}

#[stable(feature = "try_from_slice_error", since = "1.36.0")]
impl From<Infallible> for TryFromSliceError {
    fn from(x: Infallible) -> TryFromSliceError {
        match x {}
    }
}

macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

// macro for implementing n-element array functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "try_from", since = "1.34.0")]
            impl<T> TryFrom<&[T]> for [T; $N] where T: Copy {
                type Error = TryFromSliceError;

                fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> {
                    <&Self>::try_from(slice).map(|r| *r)
                }
            }

            #[stable(feature = "try_from", since = "1.34.0")]
            impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &[T]) -> Result<&[T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_ptr() as *const [T; $N];
                        unsafe { Ok(&*ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[stable(feature = "try_from", since = "1.34.0")]
            impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
                type Error = TryFromSliceError;

                fn try_from(slice: &mut [T]) -> Result<&mut [T; $N], TryFromSliceError> {
                    if slice.len() == $N {
                        let ptr = slice.as_mut_ptr() as *mut [T; $N];
                        unsafe { Ok(&mut *ptr) }
                    } else {
                        Err(TryFromSliceError(()))
                    }
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<|endoftext|>


<commit_before>use std::result::Result;

use silkthread_base::*;
use silkthread_base::basic::*;

use super::super::lex::lex_tool::*;
use super::script::*;

///
/// Represents a parse error
///
#[derive(Serialize, Deserialize, Debug)]
pub struct ParseError {
    pub message: String
}

///
/// Tool that parses our scripting language
///
pub struct ParseScriptTool {
}

impl ParseError {
    fn new<'a>(state: &ParseState<'a>, message: &str) -> ParseError {
        println!("{}", message);
        println!("{:?}", state.remaining);

        ParseError { message: String::from(message) }
    }
}

struct ParseState<'a> {
    remaining: &'a [ScriptToken]
}

impl<'a> ParseState<'a> {
    ///
    /// Returns true if a token is considered syntax (gets returned from lookahead)
    ///
    fn is_syntax(token: &ScriptToken) -> bool {
        match token.token {
            ScriptLexerToken::Whitespace    |
            ScriptLexerToken::Comment       => false,

            _                               => true
        }
    }

    ///
    /// Looks ahead to the next syntactically relevant lexer match (and returns the tokens after it)
    ///
    fn lookahead(&self) -> Option<(&'a ScriptToken, &'a [ScriptToken])> {
        let mut index   = 0;
        let len         = self.remaining.len();

        loop {
            if index >= len {
                return None;
            } else if ParseState::is_syntax(&self.remaining[index]) {
                let token       = &self.remaining[index];
                let remaining   = &self.remaining[index+1..len];
                return Some((token, remaining));
            }

            index += 1;
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn lookahead_is(&self, token: ScriptLexerToken) -> bool {
        if let Some((lookahead, _remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches
                true
            } else {
                // Token does not match
                false
            }
        } else {
            // End of file
            if token == ScriptLexerToken::EndOfFile {
                // With lookahead_is we can look for the end of file (but we can't accept it because there's no token data associated with it)
                true
            } else {
                false
            }
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn accept(&mut self, token: ScriptLexerToken) -> Option<&'a ScriptToken> {
        if let Some((lookahead, remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches: remove it from the input and return it
                self.remaining = remaining;
                Some(lookahead)
            } else {
                // Next token does not match
                None
            }
        } else {
            // Reached the end of file
            None
        }
    }

    ///
    /// Parses a statement
    ///
    fn parse_statement(&mut self) -> Result<Script, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Newlines are ignored
            self.parse_statement()

        } else if self.accept(ScriptLexerToken::Let).is_some() {
            // let identifier = expression
            self.parse_let()

        } else if self.accept(ScriptLexerToken::Var).is_some() {
            // var identifier = expression
            self.parse_var()

        } else if self.accept(ScriptLexerToken::Def).is_some() {
            // def fn args { statements }
            self.parse_def()

        } else if self.accept(ScriptLexerToken::If).is_some() {
            // if expression { statements }
            self.parse_if()

        } else if self.accept(ScriptLexerToken::Using).is_some() {
            // using expression { statements }
            self.parse_using()

        } else if self.accept(ScriptLexerToken::While).is_some() {
            // while expression { statements }
            self.parse_while()

        } else if self.accept(ScriptLexerToken::Loop).is_some() {
            // loop { statements }
            self.parse_loop()

        } else if self.accept(ScriptLexerToken::For).is_some() {
            // for identifier in expression { statements }
            self.parse_for()

        } else if self.lookahead_is(ScriptLexerToken::Identifier) {
            // While commands are either <Expression> or <Expression> <Expression>, we
            // force the first expression to be an identifier at the moment
            self.parse_command()

        } else {
            // Unrecognised token
            Err(ParseError::new(self, "Token cannot begin a statement"))
        }
    }

    ///
    /// Parses a command
    ///
    /// Syntax '<expression>', '<expression> <expression>'
    ///
    fn parse_command(&mut self) -> Result<Script, ParseError> {
        // Starts with an expression specifying the command to run
        self.parse_expression().and_then(move |command_expression| {
            // Followed by arguments (or an end-of-expression marker)
            if self.accept(ScriptLexerToken::Newline).is_some()
               || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                // Newline or EOF ends a command
                Ok(Script::RunCommand(command_expression, None))

            } else {
                // Anything else should be an argument expression
                self.parse_expression().and_then(move |argument_expression| {
                    Ok(Script::RunCommand(command_expression, Some(argument_expression)))

                }).and_then(move |command| {
                    // Command must be followed by a newline
                    if self.accept(ScriptLexerToken::Newline).is_some()
                       || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                        Ok(command)
                    } else {
                        Err(ParseError::new(self, "Found extra tokens after the end of a command"))
                    }

                })

            }
        })
    }

    ///
    /// Parses an Expression
    ///
    fn parse_expression(&mut self) -> Result<Expression, ParseError> {
        let left_expr = if self.lookahead_is(ScriptLexerToken::symbol("[")) {
            self.parse_array_expression()

        } else {
            // Simple expression
            self.parse_simple_expression()

        };

        // Look for a RHS
        left_expr.and_then(|left_expr| self.parse_expression_rhs(left_expr))
    }

    ///
    /// Parses the RHS of an expression (if there is one)
    ///
    fn parse_expression_rhs(&mut self, left_expr: Expression) -> Result<Expression, ParseError> {
        if self.accept(ScriptLexerToken::symbol(".")).is_some() {
            // 'a.b' field access
            let right_expr = self.parse_expression();

            right_expr.map(|right_expr| Expression::FieldAccess(Box::new((left_expr, right_expr))))

        } else if self.accept(ScriptLexerToken::symbol("[")).is_some() {
            // a[b] indexing
            let right_expr = self.parse_expression();

            right_expr.and_then(|right_expr| {
                if self.accept(ScriptLexerToken::symbol("]")).is_some() {
                    // Got all of a[b]
                    Ok(Expression::Index(Box::new((left_expr, right_expr))))
                } else {
                    // Missing ']'
                    Err(ParseError::new(self, "Missing ']'"))
                }
            })

        } else {
            Ok(left_expr)

        }
    }

    ///
    /// Skips any newlines
    ///
    fn skip_newlines(&mut self) {
        while self.accept(ScriptLexerToken::Newline).is_some() { }
    }

    ///
    /// Parses an array expression
    ///
    fn parse_array_expression(&mut self) -> Result<Expression, ParseError> {
        // Opening '['
        if self.accept(ScriptLexerToken::symbol("[")).is_none() {
            // Not an array
            return Err(ParseError::new(self, "Not an array"));
        }

        let mut components = vec![];

        // Array goes until the final ']'
        while self.accept(ScriptLexerToken::symbol("]")).is_none() {
            // Read the next component
            let next_component = self.parse_expression();

            // Add to the components
            match next_component {
                Err(failure)    => return Err(failure),
                Ok(component)   => components.push(component)
            };

            // Components separated by commas. Newlines are ignored
            self.skip_newlines();

            // Followed by a comma or the closing ']'
            if self.accept(ScriptLexerToken::symbol(",")).is_none()
                && !self.lookahead_is(ScriptLexerToken::symbol("]")) {
                // Expected ','
                return Err(ParseError::new(self, "Expected ',' or ']'"));
            }

            // Newlines allowed after the ','
            self.skip_newlines();
        }

        Ok(Expression::Array(components))
    }

    ///
    /// Parses a simple expression
    ///
    fn parse_simple_expression(&mut self) -> Result<Expression, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Ignore newlines within an expression
            self.parse_expression()

        } else if let Some(identifier) = self.accept(ScriptLexerToken::Identifier) {
            // Simple expression
            Ok(Expression::Identifier(identifier.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::Number) {
            // Simple expression
            Ok(Expression::Number(number.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::HexNumber) {
            // Hex numbers work like normal numbers
            Ok(Expression::Number(number.clone()))

        } else if let Some(string) = self.accept(ScriptLexerToken::String) {
            // Simple expression
            Ok(Expression::String(string.clone()))

        } else {
            // Syntax error
            Err(ParseError::new(self, "Syntax error (was expecting an expression)"))

        }
    }

    fn parse_let(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_var(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_def(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_if(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_using(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_while(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_loop(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_for(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }
}

impl ParseScriptTool {
    ///
    /// Creates a new tool from the parse script tool
    ///
    pub fn new_tool() -> Box<Tool> {
        Box::new(make_tool(move |script: Vec<LexerMatch>| -> Result<Vec<Script>, ParseError> {
            ParseScriptTool::parse(&script)
        }))
    }

    ///
    /// Tries to parse a script from the output of the lexer
    ///
    pub fn parse(input: &[LexerMatch]) -> Result<Vec<Script>, ParseError> {
        // Convert to script tokens
        let as_script_token: Vec<ScriptToken> = input
            .iter()
            .map(|token| ScriptToken::from_lexer_match(token))
            .collect();

        // Parse until we reach the end of the file
        let mut parser = ParseState { remaining: &as_script_token };
        let mut result = vec![];

        while !parser.lookahead_is(ScriptLexerToken::EndOfFile) {
            let next_statement = parser.parse_statement();

            match next_statement {
                // Fail out if we get a parse failure
                Err(failure)        => return Err(failure),

                // Build out the result otherwise
                Ok(next_statement)  => result.push(next_statement)
            }

            // Swallow any trailing newlines
            parser.skip_newlines();
        }

        Ok(result)
    }
}

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

    ///
    /// Performs lexing
    ///
    fn lex(text: &str) -> Vec<LexerMatch> {
        let lexer = create_lex_script_tool();

        lexer.lex(text)
    }

    fn parse(text: &str) -> Result<Vec<Script>, ParseError> {
        let lexed = lex(text);
        ParseScriptTool::parse(&lexed)
    }

    #[test]
    fn can_parse_command_statement() {
        let statement   = "some-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_field_access() {
        let statement   = "some-command.some-field";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::FieldAccess(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_array_indexing() {
        let statement   = "some-command[0]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Index(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_parameter() {
        let statement   = "some-command 1";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Number(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_empty_array_parameter() {
        let statement   = "some-command [ ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_single_array_parameter() {
        let statement   = "some-command [ 1 ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_multi_array_parameter() {
        let statement   = "some-command [ 1, 2, 3 ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_complex_array_parameter() {
        let statement   = "some-command [ some-command.access, indexed[2], 3 ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn cannot_try_to_put_multiple_statements_on_one_line() {
        let statement   = "some-command 1 some-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_err());
    }

    #[test]
    fn can_parse_multiple_lines() {
        let statement   = "some-command\nsome-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());
        assert!(parsed.unwrap().len() == 2);
    }
}
<commit_msg>Make the array parser work with custom open/close symbols<commit_after>use std::result::Result;

use silkthread_base::*;
use silkthread_base::basic::*;

use super::super::lex::lex_tool::*;
use super::script::*;

///
/// Represents a parse error
///
#[derive(Serialize, Deserialize, Debug)]
pub struct ParseError {
    pub message: String
}

///
/// Tool that parses our scripting language
///
pub struct ParseScriptTool {
}

impl ParseError {
    fn new<'a>(state: &ParseState<'a>, message: &str) -> ParseError {
        println!("{}", message);
        println!("{:?}", state.remaining);

        ParseError { message: String::from(message) }
    }
}

struct ParseState<'a> {
    remaining: &'a [ScriptToken]
}

impl<'a> ParseState<'a> {
    ///
    /// Returns true if a token is considered syntax (gets returned from lookahead)
    ///
    fn is_syntax(token: &ScriptToken) -> bool {
        match token.token {
            ScriptLexerToken::Whitespace    |
            ScriptLexerToken::Comment       => false,

            _                               => true
        }
    }

    ///
    /// Looks ahead to the next syntactically relevant lexer match (and returns the tokens after it)
    ///
    fn lookahead(&self) -> Option<(&'a ScriptToken, &'a [ScriptToken])> {
        let mut index   = 0;
        let len         = self.remaining.len();

        loop {
            if index >= len {
                return None;
            } else if ParseState::is_syntax(&self.remaining[index]) {
                let token       = &self.remaining[index];
                let remaining   = &self.remaining[index+1..len];
                return Some((token, remaining));
            }

            index += 1;
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn lookahead_is(&self, token: ScriptLexerToken) -> bool {
        if let Some((lookahead, _remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches
                true
            } else {
                // Token does not match
                false
            }
        } else {
            // End of file
            if token == ScriptLexerToken::EndOfFile {
                // With lookahead_is we can look for the end of file (but we can't accept it because there's no token data associated with it)
                true
            } else {
                false
            }
        }
    }

    ///
    /// If the next token matches the specified token, consumes it and returns
    /// its content.
    ///
    fn accept(&mut self, token: ScriptLexerToken) -> Option<&'a ScriptToken> {
        if let Some((lookahead, remaining)) = self.lookahead() {
            if lookahead.token == token {
                // Token matches: remove it from the input and return it
                self.remaining = remaining;
                Some(lookahead)
            } else {
                // Next token does not match
                None
            }
        } else {
            // Reached the end of file
            None
        }
    }

    ///
    /// Parses a statement
    ///
    fn parse_statement(&mut self) -> Result<Script, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Newlines are ignored
            self.parse_statement()

        } else if self.accept(ScriptLexerToken::Let).is_some() {
            // let identifier = expression
            self.parse_let()

        } else if self.accept(ScriptLexerToken::Var).is_some() {
            // var identifier = expression
            self.parse_var()

        } else if self.accept(ScriptLexerToken::Def).is_some() {
            // def fn args { statements }
            self.parse_def()

        } else if self.accept(ScriptLexerToken::If).is_some() {
            // if expression { statements }
            self.parse_if()

        } else if self.accept(ScriptLexerToken::Using).is_some() {
            // using expression { statements }
            self.parse_using()

        } else if self.accept(ScriptLexerToken::While).is_some() {
            // while expression { statements }
            self.parse_while()

        } else if self.accept(ScriptLexerToken::Loop).is_some() {
            // loop { statements }
            self.parse_loop()

        } else if self.accept(ScriptLexerToken::For).is_some() {
            // for identifier in expression { statements }
            self.parse_for()

        } else if self.lookahead_is(ScriptLexerToken::Identifier) {
            // While commands are either <Expression> or <Expression> <Expression>, we
            // force the first expression to be an identifier at the moment
            self.parse_command()

        } else {
            // Unrecognised token
            Err(ParseError::new(self, "Token cannot begin a statement"))
        }
    }

    ///
    /// Parses a command
    ///
    /// Syntax '<expression>', '<expression> <expression>'
    ///
    fn parse_command(&mut self) -> Result<Script, ParseError> {
        // Starts with an expression specifying the command to run
        self.parse_expression().and_then(move |command_expression| {
            // Followed by arguments (or an end-of-expression marker)
            if self.accept(ScriptLexerToken::Newline).is_some()
               || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                // Newline or EOF ends a command
                Ok(Script::RunCommand(command_expression, None))

            } else {
                // Anything else should be an argument expression
                self.parse_expression().and_then(move |argument_expression| {
                    Ok(Script::RunCommand(command_expression, Some(argument_expression)))

                }).and_then(move |command| {
                    // Command must be followed by a newline
                    if self.accept(ScriptLexerToken::Newline).is_some()
                       || self.lookahead_is(ScriptLexerToken::EndOfFile) {
                        Ok(command)
                    } else {
                        Err(ParseError::new(self, "Found extra tokens after the end of a command"))
                    }

                })

            }
        })
    }

    ///
    /// Parses an Expression
    ///
    fn parse_expression(&mut self) -> Result<Expression, ParseError> {
        let left_expr = if self.lookahead_is(ScriptLexerToken::symbol("[")) {
            self.parse_array_expression(ScriptLexerToken::symbol("["), ScriptLexerToken::symbol("]"))
                .map(|x| Expression::Array(x))

        } else {
            // Simple expression
            self.parse_simple_expression()

        };

        // Look for a RHS
        left_expr.and_then(|left_expr| self.parse_expression_rhs(left_expr))
    }

    ///
    /// Parses the RHS of an expression (if there is one)
    ///
    fn parse_expression_rhs(&mut self, left_expr: Expression) -> Result<Expression, ParseError> {
        if self.accept(ScriptLexerToken::symbol(".")).is_some() {
            // 'a.b' field access
            let right_expr = self.parse_expression();

            right_expr.map(|right_expr| Expression::FieldAccess(Box::new((left_expr, right_expr))))

        } else if self.accept(ScriptLexerToken::symbol("[")).is_some() {
            // a[b] indexing
            let right_expr = self.parse_expression();

            right_expr.and_then(|right_expr| {
                if self.accept(ScriptLexerToken::symbol("]")).is_some() {
                    // Got all of a[b]
                    Ok(Expression::Index(Box::new((left_expr, right_expr))))
                } else {
                    // Missing ']'
                    Err(ParseError::new(self, "Missing ']'"))
                }
            })

        } else {
            Ok(left_expr)

        }
    }

    ///
    /// Skips any newlines
    ///
    fn skip_newlines(&mut self) {
        while self.accept(ScriptLexerToken::Newline).is_some() { }
    }

    ///
    /// Parses an array expression
    ///
    fn parse_array_expression(&mut self, open_bracket: ScriptLexerToken, close_bracket: ScriptLexerToken) -> Result<Vec<Expression>, ParseError> {
        // Opening '['
        if self.accept(open_bracket.clone()).is_none() {
            // Not an array
            return Err(ParseError::new(self, "Not an array"));
        }

        let mut components = vec![];

        // Array goes until the final ']'
        while self.accept(close_bracket.clone()).is_none() {
            // Read the next component
            let next_component = self.parse_expression();

            // Add to the components
            match next_component {
                Err(failure)    => return Err(failure),
                Ok(component)   => components.push(component)
            };

            // Components separated by commas. Newlines are ignored
            self.skip_newlines();

            // Followed by a comma or the closing ']'
            if self.accept(ScriptLexerToken::symbol(",")).is_none()
                && !self.lookahead_is(close_bracket.clone()) {
                // Expected ','
                return Err(ParseError::new(self, "Expected ',' or ']'"));
            }

            // Newlines allowed after the ','
            self.skip_newlines();
        }

        Ok(components)
    }

    ///
    /// Parses a simple expression
    ///
    fn parse_simple_expression(&mut self) -> Result<Expression, ParseError> {
        if self.accept(ScriptLexerToken::Newline).is_some() {
            // Ignore newlines within an expression
            self.parse_expression()

        } else if let Some(identifier) = self.accept(ScriptLexerToken::Identifier) {
            // Simple expression
            Ok(Expression::Identifier(identifier.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::Number) {
            // Simple expression
            Ok(Expression::Number(number.clone()))

        } else if let Some(number) = self.accept(ScriptLexerToken::HexNumber) {
            // Hex numbers work like normal numbers
            Ok(Expression::Number(number.clone()))

        } else if let Some(string) = self.accept(ScriptLexerToken::String) {
            // Simple expression
            Ok(Expression::String(string.clone()))

        } else {
            // Syntax error
            Err(ParseError::new(self, "Syntax error (was expecting an expression)"))

        }
    }

    fn parse_let(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_var(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_def(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_if(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_using(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_while(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_loop(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }

    fn parse_for(&mut self) -> Result<Script, ParseError> {
        unimplemented!()
    }
}

impl ParseScriptTool {
    ///
    /// Creates a new tool from the parse script tool
    ///
    pub fn new_tool() -> Box<Tool> {
        Box::new(make_tool(move |script: Vec<LexerMatch>| -> Result<Vec<Script>, ParseError> {
            ParseScriptTool::parse(&script)
        }))
    }

    ///
    /// Tries to parse a script from the output of the lexer
    ///
    pub fn parse(input: &[LexerMatch]) -> Result<Vec<Script>, ParseError> {
        // Convert to script tokens
        let as_script_token: Vec<ScriptToken> = input
            .iter()
            .map(|token| ScriptToken::from_lexer_match(token))
            .collect();

        // Parse until we reach the end of the file
        let mut parser = ParseState { remaining: &as_script_token };
        let mut result = vec![];

        while !parser.lookahead_is(ScriptLexerToken::EndOfFile) {
            let next_statement = parser.parse_statement();

            match next_statement {
                // Fail out if we get a parse failure
                Err(failure)        => return Err(failure),

                // Build out the result otherwise
                Ok(next_statement)  => result.push(next_statement)
            }

            // Swallow any trailing newlines
            parser.skip_newlines();
        }

        Ok(result)
    }
}

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

    ///
    /// Performs lexing
    ///
    fn lex(text: &str) -> Vec<LexerMatch> {
        let lexer = create_lex_script_tool();

        lexer.lex(text)
    }

    fn parse(text: &str) -> Result<Vec<Script>, ParseError> {
        let lexed = lex(text);
        ParseScriptTool::parse(&lexed)
    }

    #[test]
    fn can_parse_command_statement() {
        let statement   = "some-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_field_access() {
        let statement   = "some-command.some-field";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::FieldAccess(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_array_indexing() {
        let statement   = "some-command[0]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Index(_), None) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_parameter() {
        let statement   = "some-command 1";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Number(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_empty_array_parameter() {
        let statement   = "some-command [ ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_single_array_parameter() {
        let statement   = "some-command [ 1 ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_multi_array_parameter() {
        let statement   = "some-command [ 1, 2, 3 ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn can_parse_command_statement_with_complex_array_parameter() {
        let statement   = "some-command [ some-command.access, indexed[2], 3 ]";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());

        let result = parsed.unwrap();
        assert!(result.len() == 1);

        let ref cmd = result[0];
        assert!(match cmd { &Script::RunCommand(Expression::Identifier(_), Some(Expression::Array(_))) => true, _ => false});
    }

    #[test]
    fn cannot_try_to_put_multiple_statements_on_one_line() {
        let statement   = "some-command 1 some-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_err());
    }

    #[test]
    fn can_parse_multiple_lines() {
        let statement   = "some-command\nsome-other-command";
        let parsed      = parse(statement);

        assert!(parsed.is_ok());
        assert!(parsed.unwrap().len() == 2);
    }
}
<|endoftext|>


<commit_before>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels
}

#[derive(Debug)]
pub enum TextEvent {
    RoomMessage(UserID, RoomID, String)
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<String>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        assert!(tokens[0] == "m");
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(i.as_string().unwrap().to_string()),
            None => None
        };
        Event {
            id: id,
            data: match tokens[1] {
                "room" =>
                    Self::from_room_json(tokens[2], json),
                "typing" =>
                    EventData::Typing(TypingEvent {
                        users: vec![],
                        room: RoomID::from_str(mjson::string(json, "room_id"))
                    }),
                "presence" =>
                    EventData::Presence(PresenceEvent{
                        presence: mjson::string(json, "content.presence").to_string(),
                        user: UserID::from_str(mjson::string(json, "content.user_id"))
                    }),
                e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" =>
                    RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string()),
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<commit_msg>matrix: events: drop old spec event<commit_after>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<String>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        assert!(tokens[0] == "m");
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(i.as_string().unwrap().to_string()),
            None => None
        };
        Event {
            id: id,
            data: match tokens[1] {
                "room" =>
                    Self::from_room_json(tokens[2], json),
                "typing" =>
                    EventData::Typing(TypingEvent {
                        users: vec![],
                        room: RoomID::from_str(mjson::string(json, "room_id"))
                    }),
                "presence" =>
                    EventData::Presence(PresenceEvent{
                        presence: mjson::string(json, "content.presence").to_string(),
                        user: UserID::from_str(mjson::string(json, "content.user_id"))
                    }),
                e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" =>
                    RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string()),
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<|endoftext|>


<commit_before>
// Copyright 2020 John Hanley.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// The software is provided "AS IS", without warranty of any kind, express or
// implied, including but not limited to the warranties of merchantability,
// fitness for a particular purpose and noninfringement. In no event shall
// the authors or copyright holders be liable for any claim, damages or
// other liability, whether in an action of contract, tort or otherwise,
// arising from, out of or in connection with the software or the use or
// other dealings in the software.

use std::env;

const MAX_ITER: i32 = 255;  // Rust lacks adequate support for default args.

fn mandelbrot_set(xc: f64, yc: f64, sz: f64, px_resolution: i32) {
    let step = (2.0 * sz) / (px_resolution as f64 - 1.0);

    for j in 0 .. px_resolution {
        for i in 0 .. px_resolution {
            let x0 = xc - sz + step * i as f64;
            let y0 = yc - sz + step * j as f64;
            plot(_cycles_to_escape(x0, y0));
        }
    }
}

fn _cycles_to_escape(x0: f64, y0: f64) -> i32 {
    let mut x = 0.0;
    let mut y = 0.0;
    let mut i = 0;
    while x * x + y * y <= 4.0 && i < MAX_ITER {
        let (a, b) = (x * x - y * y + x0, 2.0 * x * y + y0);
        x = a;
        y = b; // rust lacks tuple unpack, aka destructuring assignment
        i += 1;
        // println!("{} {} {} {} {}", x0, y0, i, x, y);
    }
    return i;
}

fn plot(grey_value: i32) {
    let v = grey_value;
    println!("{} {} {}", v, v, v);
}

fn getenv(key: &str) -> i32 {
    let s: String;
    match env::var(key) {
        Ok(v) => s = v,
        Err(_) => s = "400".to_string()
    }
    return stoi(s);
}

fn stoi(s: String) -> i32 {
    return s.parse::<i32>().unwrap();
}

fn stof(s: String) -> f64 {
    return s.parse::<f64>().unwrap();
}

fn main() {
    let px_resolution = getenv("MSET_PX_RESOLUTION");
    let args: Vec<String> = env::args().into_iter().collect();
    let xc = stof(args[1].to_string());
    let yc = stof(args[2].to_string());
    let sz = stof(args[3].to_string());

    println!("P3\n{} {}\n255", px_resolution, px_resolution);
    mandelbrot_set(xc, yc, sz, px_resolution);
}
<commit_msg>Show rust elapsed time<commit_after>
// Copyright 2020 John Hanley.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// The software is provided "AS IS", without warranty of any kind, express or
// implied, including but not limited to the warranties of merchantability,
// fitness for a particular purpose and noninfringement. In no event shall
// the authors or copyright holders be liable for any claim, damages or
// other liability, whether in an action of contract, tort or otherwise,
// arising from, out of or in connection with the software or the use or
// other dealings in the software.

use std::env;
use std::time::Instant;

const MAX_ITER: i32 = 255;  // Rust lacks adequate support for default args.

fn mandelbrot_set(xc: f64, yc: f64, sz: f64, px_resolution: i32) {
    let step = (2.0 * sz) / (px_resolution as f64 - 1.0);

    for j in 0 .. px_resolution {
        for i in 0 .. px_resolution {
            let x0 = xc - sz + step * i as f64;
            let y0 = yc - sz + step * j as f64;
            plot(_cycles_to_escape(x0, y0));
        }
    }
}

fn _cycles_to_escape(x0: f64, y0: f64) -> i32 {
    let mut x = 0.0;
    let mut y = 0.0;
    let mut i = 0;
    while x * x + y * y <= 4.0 && i < MAX_ITER {
        let (a, b) = (x * x - y * y + x0, 2.0 * x * y + y0);
        x = a;
        y = b;  // rust 1.47 lacks tuple unpack, aka destructuring assignment
        i += 1;
    }
    return i;
}

fn plot(grey_value: i32) {
    let v = grey_value;
    println!("{} {} {}", v, v, v);
}

fn getenv(key: &str) -> i32 {
    let s: String;
    match env::var(key) {
        Ok(v) => s = v,
        Err(_) => s = "400".to_string()
    }
    return stoi(s);
}

fn stoi(s: String) -> i32 {
    return s.parse::<i32>().unwrap();
}

fn stof(s: String) -> f64 {
    return s.parse::<f64>().unwrap();
}

pub fn main() {
    let px_resolution = getenv("MSET_PX_RESOLUTION");
    let args: Vec<String> = env::args().into_iter().collect();
    let xc = stof(args[1].to_string());
    let yc = stof(args[2].to_string());
    let sz = stof(args[3].to_string());
    println!("P3\n{} {}\n255", px_resolution, px_resolution);
    let t0 = Instant::now();

    mandelbrot_set(xc, yc, sz, px_resolution);

    let elapsed = t0.elapsed().as_millis() as f64;
    eprintln!("{} seconds", elapsed / 1e3);
}
<|endoftext|>


<commit_before>//! A module that represents equations and works with terms

use terms::*;
use equation::OperationType::DERIVE;
use equation::OperationType::JOIN;
use equation::OperationType::DELETE;
use equation::OperationType::BRANCH;

/// Represents an equation in LRS standard form where each
///  term is chained in an AND operation
struct Equation {
    terms: Vec<Term>,
}

/// Describes a reduce operation type
enum OperationType {
    DERIVE,
    JOIN,
    DELETE,
    BRANCH,
}

/// Represents a reduce operation and every piece of data involved
struct Operation<'a> {
    _type: OperationType,
    term: Vec<&'a Term>,
    symbol: Vec<&'a Symbol>,
}

impl Equation {
    /// Insert a term naively into an equation
    pub fn insert(&mut self, term: Term) {
        self.terms.push(term);
    }

    /// Run a single reduce step and return the exact reduce operation
    pub fn reduce(&mut self) -> Operation {
        /* First we search for single defined terms */
        let single = self.search_single_terms();
        match single {
            Some(term) => {}
            None => {}
        }

        return Operation {
            _type: DERIVE,
            term: Vec::new(),
            symbol: Vec::new(),
        };
    }

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

    /// Will return the first single-value term it encounters
    fn search_single_terms(&mut self) -> Option<&Term> {
        for term in self.terms.iter() {
            if term.symbols.len() == 1 {
                return Some(term);
            }
        }
        return None;
    }
}
<commit_msg>Documentation and stuff<commit_after>//! A module that represents equations and works with terms

use terms::*;
use equation::OperationType::DERIVE;
use equation::OperationType::JOIN;
use equation::OperationType::DELETE;
use equation::OperationType::BRANCH;

/// Represents an equation in LRS standard form where each
///  term is chained in an AND operation
pub struct Equation {
    pub terms: Vec<Term>,
}

/// Describes a reduce operation type
pub enum OperationType {
    /// Eliminates single symbol terms
    DERIVE,
    /// Joins two terms, eliminating at most one symbol
    JOIN,
    /// Delete a symbol from a term for different reasons
    DELETE,
    /// Run a branching scenario
    BRANCH,
}

/// Represents a reduce operation and every piece of data involved
pub struct Operation<'a> {
    _type: OperationType,
    term: Vec<&'a Term>,
    symbol: Vec<&'a Symbol>,
}

impl Equation {
    /// Insert a term naively into an equation
    pub fn insert(&mut self, term: Term) {
        self.terms.push(term);
    }

    /// Run a single reduce step and return the exact reduce operation
    pub fn reduce(&mut self) -> Operation {
        /* First we search for single defined terms */
        let single = self.search_single_terms();
        match single {
            Some(term) => {
                println!("Fooo");
            }
            None => {}
        }

        return Operation {
            _type: DERIVE,
            term: Vec::new(),
            symbol: Vec::new(),
        };
    }

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

    /// Will return the first single-value term it encounters
    fn search_single_terms(&mut self) -> Option<&Term> {
        for term in self.terms.iter() {
            if term.symbols.len() == 1 {
                return Some(term);
            }
        }
        return None;
    }
}
<|endoftext|>