<commit_before>use std::ptr;

use get_error;
use surface;
use video;

#[allow(non_camel_case_types)]
pub mod ll {
    use libc::{c_int, c_uint, c_void, uint8_t, uint32_t};
    use surface::ll::SDL_Surface;
    use video::ll::SDL_Window;

    pub type SDL_bool = c_int;
    pub type SDL_Cursor = c_void;

    pub type SDL_SystemCursor = c_uint;
    pub static SDL_SYSTEM_CURSOR_ARROW: SDL_SystemCursor = 0;
    pub static SDL_SYSTEM_CURSOR_IBEAM: SDL_SystemCursor = 1;
    pub static SDL_SYSTEM_CURSOR_WAIT: SDL_SystemCursor = 2;
    pub static SDL_SYSTEM_CURSOR_CROSSHAIR: SDL_SystemCursor = 3;
    pub static SDL_SYSTEM_CURSOR_WAITARROW: SDL_SystemCursor = 4;
    pub static SDL_SYSTEM_CURSOR_SIZENWSE: SDL_SystemCursor = 5;
    pub static SDL_SYSTEM_CURSOR_SIZENESW: SDL_SystemCursor = 6;
    pub static SDL_SYSTEM_CURSOR_SIZEWE: SDL_SystemCursor = 7;
    pub static SDL_SYSTEM_CURSOR_SIZENS: SDL_SystemCursor = 8;
    pub static SDL_SYSTEM_CURSOR_SIZEALL: SDL_SystemCursor = 9;
    pub static SDL_SYSTEM_CURSOR_NO: SDL_SystemCursor = 10;
    pub static SDL_SYSTEM_CURSOR_HAND: SDL_SystemCursor = 11;
    pub static SDL_NUM_SYSTEM_CURSORS: SDL_SystemCursor = 12;

    pub type SDL_MouseState = c_int;
    pub static SDL_DISABLE: SDL_MouseState = 0;
    pub static SDL_ENABLE: SDL_MouseState = 1;
    pub static SDL_QUERY: SDL_MouseState = -1;

    extern "C" {
        pub fn SDL_GetMouseFocus() -> *SDL_Window;
        pub fn SDL_GetMouseState(x: *c_int, y: *c_int) -> uint32_t;
        pub fn SDL_GetRelativeMouseState(x: *c_int, y: *c_int) -> uint32_t;
        pub fn SDL_WarpMouseInWindow(window: *SDL_Window, x: c_int, y: c_int);
        pub fn SDL_SetRelativeMouseMode(enabled: SDL_bool) -> c_int;
        pub fn SDL_GetRelativeMouseMode() -> SDL_bool;
        pub fn SDL_CreateCursor(data: *uint8_t, mask: *uint8_t, w: c_int,
                                      h: c_int, hot_x: c_int, hot_y: c_int) ->
                  *SDL_Cursor;
        pub fn SDL_CreateColorCursor(surface: *SDL_Surface, hot_x: c_int,
                                           hot_y: c_int) -> *SDL_Cursor;
        pub fn SDL_CreateSystemCursor(id: SDL_SystemCursor) -> *SDL_Cursor;
        pub fn SDL_SetCursor(cursor: *SDL_Cursor);
        pub fn SDL_GetCursor() -> *SDL_Cursor;
        pub fn SDL_GetDefaultCursor() -> *SDL_Cursor;
        pub fn SDL_FreeCursor(cursor: *SDL_Cursor);
        pub fn SDL_ShowCursor(toggle: SDL_MouseState) -> SDL_MouseState;
    }
}

#[deriving(Eq)]
pub enum SystemCursor {
    ArrowCursor = ll::SDL_SYSTEM_CURSOR_ARROW,
    IBeamCursor = ll::SDL_SYSTEM_CURSOR_IBEAM,
    WaitCursor = ll::SDL_SYSTEM_CURSOR_WAIT,
    CrosshairCursor = ll::SDL_SYSTEM_CURSOR_CROSSHAIR,
    WaitArrowCursor = ll::SDL_SYSTEM_CURSOR_WAITARROW,
    SizeNWSECursor = ll::SDL_SYSTEM_CURSOR_SIZENWSE,
    SizeNESWCursor = ll::SDL_SYSTEM_CURSOR_SIZENESW,
    SizeWECursor = ll::SDL_SYSTEM_CURSOR_SIZEWE,
    SizeNSCursor = ll::SDL_SYSTEM_CURSOR_SIZENS,
    SizeAllCursor = ll::SDL_SYSTEM_CURSOR_SIZEALL,
    NoCursor = ll::SDL_SYSTEM_CURSOR_NO,
    HandCursor = ll::SDL_SYSTEM_CURSOR_HAND,
}

#[deriving(Eq)] #[allow(raw_pointer_deriving)]
pub struct Cursor {
    raw: *ll::SDL_Cursor,
    owned: bool
}

impl Drop for Cursor {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeCursor(self.raw);
            }
        }
    }
}

impl Cursor {
    pub fn new(data: &[u8], mask: &[u8], width: int, height: int, hot_x: int, hot_y: int) -> Result<Cursor, ~str> {
        unsafe {
            let raw = ll::SDL_CreateCursor(data.as_ptr(),
                                           mask.as_ptr(),
                                           width as i32, height as i32,
                                           hot_x as i32, hot_y as i32);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Cursor{ raw: raw, owned: true })
            }
        }
    }

    pub fn from_surface(surface: &surface::Surface, hot_x: int, hot_y: int) -> Result<Cursor, ~str> {
        unsafe {
            let raw = ll::SDL_CreateColorCursor(surface.raw, hot_x as i32,
                                                hot_y as i32);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Cursor{ raw: raw, owned: true })
            }
        }
    }

    pub fn from_system(cursor: SystemCursor) -> Result<Cursor, ~str> {
        unsafe {
            let raw = ll::SDL_CreateSystemCursor(cursor as u32);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Cursor{ raw: raw, owned: true })
            }
        }
    }

    pub fn set(&self) {
        unsafe { ll::SDL_SetCursor(self.raw); }
    }
}

#[deriving(Eq)]
pub enum Mouse {
    LeftMouse,
    MiddleMouse,
    RightMouse,
    X1Mouse,
    X2Mouse,
    UnknownMouse(u8)
}

bitflags!(flags MouseState: u32 {
    static LeftMouseState = 0x01,
    static MiddleMouseState = 0x02,
    static RightMouseState = 0x04,
    static X1MouseState = 0x08,
    static X2MouseState = 0x10
})

pub fn wrap_mouse(bitflags: u8) -> Mouse {
    match bitflags {
        1 => LeftMouse,
        2 => MiddleMouse,
        3 => RightMouse,
        4 => X1Mouse,
        5 => X2Mouse,
        _ => UnknownMouse(bitflags)
    }
}

pub fn get_mouse_focus() -> Option<video::Window> {
    let raw = unsafe { ll::SDL_GetMouseFocus() };
    if raw == ptr::null() {
        None
    } else {
        Some(video::Window{ raw: raw, owned: false })
    }
}

pub fn get_mouse_state() -> (MouseState, int, int) {
    let x = 0;
    let y = 0;
    unsafe {
        let raw = ll::SDL_GetMouseState(&x, &y);
        return (MouseState::from_bits(raw).unwrap(), x as int, y as int);
    }
}

pub fn get_relative_mouse_state() -> (MouseState, int, int) {
    let x = 0;
    let y = 0;
    unsafe {
        let raw = ll::SDL_GetRelativeMouseState(&x, &y);
        return (MouseState::from_bits(raw).unwrap(), x as int, y as int);
    }
}

pub fn warp_mouse_in_window(window: &video::Window, x: i32, y: i32) {
    unsafe { ll::SDL_WarpMouseInWindow(window.raw, x, y); }
}

pub fn set_relative_mouse_mode(on: bool) {
    unsafe { ll::SDL_SetRelativeMouseMode(on as i32); }
}

pub fn get_relative_mouse_mode() -> bool {
    unsafe { ll::SDL_GetRelativeMouseMode() == 1 }
}

pub fn get_cursor() -> Option<Cursor> {
    let raw = unsafe { ll::SDL_GetCursor() };

    if raw == ptr::null() {
        None
    } else {
        Some(Cursor { raw: raw, owned: false })
    }
}

pub fn get_default_cursor() -> Option<Cursor> {
    let raw = unsafe { ll::SDL_GetDefaultCursor() };

    if raw == ptr::null() {
        None
    } else {
        Some(Cursor { raw: raw, owned: false })
    }
}

pub fn is_cursor_showing() -> bool {
    unsafe { ll::SDL_ShowCursor(ll::SDL_QUERY) == 1 }
}

pub fn show_cursor(show: bool) {
    unsafe { ll::SDL_ShowCursor(show as i32); }
}
<commit_msg>Added TODO note in mouse handling code<commit_after>use std::ptr;

use get_error;
use surface;
use video;

#[allow(non_camel_case_types)]
pub mod ll {
    use libc::{c_int, c_uint, c_void, uint8_t, uint32_t};
    use surface::ll::SDL_Surface;
    use video::ll::SDL_Window;

    pub type SDL_bool = c_int;
    pub type SDL_Cursor = c_void;

    pub type SDL_SystemCursor = c_uint;
    pub static SDL_SYSTEM_CURSOR_ARROW: SDL_SystemCursor = 0;
    pub static SDL_SYSTEM_CURSOR_IBEAM: SDL_SystemCursor = 1;
    pub static SDL_SYSTEM_CURSOR_WAIT: SDL_SystemCursor = 2;
    pub static SDL_SYSTEM_CURSOR_CROSSHAIR: SDL_SystemCursor = 3;
    pub static SDL_SYSTEM_CURSOR_WAITARROW: SDL_SystemCursor = 4;
    pub static SDL_SYSTEM_CURSOR_SIZENWSE: SDL_SystemCursor = 5;
    pub static SDL_SYSTEM_CURSOR_SIZENESW: SDL_SystemCursor = 6;
    pub static SDL_SYSTEM_CURSOR_SIZEWE: SDL_SystemCursor = 7;
    pub static SDL_SYSTEM_CURSOR_SIZENS: SDL_SystemCursor = 8;
    pub static SDL_SYSTEM_CURSOR_SIZEALL: SDL_SystemCursor = 9;
    pub static SDL_SYSTEM_CURSOR_NO: SDL_SystemCursor = 10;
    pub static SDL_SYSTEM_CURSOR_HAND: SDL_SystemCursor = 11;
    pub static SDL_NUM_SYSTEM_CURSORS: SDL_SystemCursor = 12;

    pub type SDL_MouseState = c_int;
    pub static SDL_DISABLE: SDL_MouseState = 0;
    pub static SDL_ENABLE: SDL_MouseState = 1;
    pub static SDL_QUERY: SDL_MouseState = -1;

    extern "C" {
        pub fn SDL_GetMouseFocus() -> *SDL_Window;
        pub fn SDL_GetMouseState(x: *c_int, y: *c_int) -> uint32_t;
        pub fn SDL_GetRelativeMouseState(x: *c_int, y: *c_int) -> uint32_t;
        pub fn SDL_WarpMouseInWindow(window: *SDL_Window, x: c_int, y: c_int);
        pub fn SDL_SetRelativeMouseMode(enabled: SDL_bool) -> c_int;
        pub fn SDL_GetRelativeMouseMode() -> SDL_bool;
        pub fn SDL_CreateCursor(data: *uint8_t, mask: *uint8_t, w: c_int,
                                      h: c_int, hot_x: c_int, hot_y: c_int) ->
                  *SDL_Cursor;
        pub fn SDL_CreateColorCursor(surface: *SDL_Surface, hot_x: c_int,
                                           hot_y: c_int) -> *SDL_Cursor;
        pub fn SDL_CreateSystemCursor(id: SDL_SystemCursor) -> *SDL_Cursor;
        pub fn SDL_SetCursor(cursor: *SDL_Cursor);
        pub fn SDL_GetCursor() -> *SDL_Cursor;
        pub fn SDL_GetDefaultCursor() -> *SDL_Cursor;
        pub fn SDL_FreeCursor(cursor: *SDL_Cursor);
        pub fn SDL_ShowCursor(toggle: SDL_MouseState) -> SDL_MouseState;
    }
}

#[deriving(Eq)]
pub enum SystemCursor {
    ArrowCursor = ll::SDL_SYSTEM_CURSOR_ARROW,
    IBeamCursor = ll::SDL_SYSTEM_CURSOR_IBEAM,
    WaitCursor = ll::SDL_SYSTEM_CURSOR_WAIT,
    CrosshairCursor = ll::SDL_SYSTEM_CURSOR_CROSSHAIR,
    WaitArrowCursor = ll::SDL_SYSTEM_CURSOR_WAITARROW,
    SizeNWSECursor = ll::SDL_SYSTEM_CURSOR_SIZENWSE,
    SizeNESWCursor = ll::SDL_SYSTEM_CURSOR_SIZENESW,
    SizeWECursor = ll::SDL_SYSTEM_CURSOR_SIZEWE,
    SizeNSCursor = ll::SDL_SYSTEM_CURSOR_SIZENS,
    SizeAllCursor = ll::SDL_SYSTEM_CURSOR_SIZEALL,
    NoCursor = ll::SDL_SYSTEM_CURSOR_NO,
    HandCursor = ll::SDL_SYSTEM_CURSOR_HAND,
}

#[deriving(Eq)] #[allow(raw_pointer_deriving)]
pub struct Cursor {
    raw: *ll::SDL_Cursor,
    owned: bool
}

impl Drop for Cursor {
    fn drop(&mut self) {
        if self.owned {
            unsafe {
                ll::SDL_FreeCursor(self.raw);
            }
        }
    }
}

impl Cursor {
    pub fn new(data: &[u8], mask: &[u8], width: int, height: int, hot_x: int, hot_y: int) -> Result<Cursor, ~str> {
        unsafe {
            let raw = ll::SDL_CreateCursor(data.as_ptr(),
                                           mask.as_ptr(),
                                           width as i32, height as i32,
                                           hot_x as i32, hot_y as i32);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Cursor{ raw: raw, owned: true })
            }
        }
    }

    // TODO: figure out how to pass Surface in here correctly
    pub fn from_surface(surface: &surface::Surface, hot_x: int, hot_y: int) -> Result<Cursor, ~str> {
        unsafe {
            let raw = ll::SDL_CreateColorCursor(surface.raw, hot_x as i32,
                                                hot_y as i32);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Cursor{ raw: raw, owned: true })
            }
        }
    }

    pub fn from_system(cursor: SystemCursor) -> Result<Cursor, ~str> {
        unsafe {
            let raw = ll::SDL_CreateSystemCursor(cursor as u32);

            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(Cursor{ raw: raw, owned: true })
            }
        }
    }

    pub fn set(&self) {
        unsafe { ll::SDL_SetCursor(self.raw); }
    }
}

#[deriving(Eq)]
pub enum Mouse {
    LeftMouse,
    MiddleMouse,
    RightMouse,
    X1Mouse,
    X2Mouse,
    UnknownMouse(u8)
}

bitflags!(flags MouseState: u32 {
    static LeftMouseState = 0x01,
    static MiddleMouseState = 0x02,
    static RightMouseState = 0x04,
    static X1MouseState = 0x08,
    static X2MouseState = 0x10
})

pub fn wrap_mouse(bitflags: u8) -> Mouse {
    match bitflags {
        1 => LeftMouse,
        2 => MiddleMouse,
        3 => RightMouse,
        4 => X1Mouse,
        5 => X2Mouse,
        _ => UnknownMouse(bitflags)
    }
}

pub fn get_mouse_focus() -> Option<video::Window> {
    let raw = unsafe { ll::SDL_GetMouseFocus() };
    if raw == ptr::null() {
        None
    } else {
        Some(video::Window{ raw: raw, owned: false })
    }
}

pub fn get_mouse_state() -> (MouseState, int, int) {
    let x = 0;
    let y = 0;
    unsafe {
        let raw = ll::SDL_GetMouseState(&x, &y);
        return (MouseState::from_bits(raw).unwrap(), x as int, y as int);
    }
}

pub fn get_relative_mouse_state() -> (MouseState, int, int) {
    let x = 0;
    let y = 0;
    unsafe {
        let raw = ll::SDL_GetRelativeMouseState(&x, &y);
        return (MouseState::from_bits(raw).unwrap(), x as int, y as int);
    }
}

pub fn warp_mouse_in_window(window: &video::Window, x: i32, y: i32) {
    unsafe { ll::SDL_WarpMouseInWindow(window.raw, x, y); }
}

pub fn set_relative_mouse_mode(on: bool) {
    unsafe { ll::SDL_SetRelativeMouseMode(on as i32); }
}

pub fn get_relative_mouse_mode() -> bool {
    unsafe { ll::SDL_GetRelativeMouseMode() == 1 }
}

pub fn get_cursor() -> Option<Cursor> {
    let raw = unsafe { ll::SDL_GetCursor() };

    if raw == ptr::null() {
        None
    } else {
        Some(Cursor { raw: raw, owned: false })
    }
}

pub fn get_default_cursor() -> Option<Cursor> {
    let raw = unsafe { ll::SDL_GetDefaultCursor() };

    if raw == ptr::null() {
        None
    } else {
        Some(Cursor { raw: raw, owned: false })
    }
}

pub fn is_cursor_showing() -> bool {
    unsafe { ll::SDL_ShowCursor(ll::SDL_QUERY) == 1 }
}

pub fn show_cursor(show: bool) {
    unsafe { ll::SDL_ShowCursor(show as i32); }
}
<|endoftext|>


<commit_before>//! Http server module
//!
//! The module contains everything necessary to setup
//! HTTP server.
//!
//! In order to start HTTP server, first you need to create and configure it
//! using factory that can be supplied to [new](fn.new.html).
//!
//! ## Factory
//!
//! Factory is a function that returns Application, describing how
//! to serve incoming HTTP requests.
//!
//! As the server uses worker pool, the factory function is restricted to trait bounds
//! `Send + Clone + 'static` so that each worker would be able to accept Application
//! without a need for synchronization.
//!
//! If you wish to share part of state among all workers you should
//! wrap it in `Arc` and potentially synchronization primitive like
//! [RwLock](https://doc.rust-lang.org/std/sync/struct.RwLock.html)
//! If the wrapped type is not thread safe.
//!
//! Note though that locking is not advisable for asynchronous programming
//! and you should minimize all locks in your request handlers
//!
//! ## HTTPS Support
//!
//! Actix-web provides support for major crates that provides TLS.
//! Each TLS implementation is provided with [AcceptorService](trait.AcceptorService.html)
//! that describes how HTTP Server accepts connections.
//!
//! For `bind` and `listen` there are corresponding `bind_ssl|tls|rustls` and `listen_ssl|tls|rustls` that accepts
//! these services.
//!
//! **NOTE:** `native-tls` doesn't support `HTTP2` yet
//!
//! ## Signal handling and shutdown
//!
//! By default HTTP Server listens for system signals
//! and, gracefully shuts down at most after 30 seconds.
//!
//! Both signal handling and shutdown timeout can be controlled
//! using corresponding methods.
//!
//! If worker, for some reason, unable to shut down within timeout
//! it is forcibly dropped.
//!
//! ## Example
//!
//! ```rust,ignore
//!extern crate actix;
//!extern crate actix_web;
//!extern crate rustls;
//!
//!use actix_web::{http, middleware, server, App, Error, HttpRequest, HttpResponse, Responder};
//!use std::io::BufReader;
//!use rustls::internal::pemfile::{certs, rsa_private_keys};
//!use rustls::{NoClientAuth, ServerConfig};
//!
//!fn index(req: &HttpRequest) -> Result<HttpResponse, Error> {
//!    Ok(HttpResponse::Ok().content_type("text/plain").body("Welcome!"))
//!}
//!
//!fn load_ssl() -> ServerConfig {
//!    use std::io::BufReader;
//!
//!    const CERT: &'static [u8] = include_bytes!("../cert.pem");
//!    const KEY: &'static [u8] = include_bytes!("../key.pem");
//!
//!    let mut cert = BufReader::new(CERT);
//!    let mut key = BufReader::new(KEY);
//!
//!    let mut config = ServerConfig::new(NoClientAuth::new());
//!    let cert_chain = certs(&mut cert).unwrap();
//!    let mut keys = rsa_private_keys(&mut key).unwrap();
//!    config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
//!
//!    config
//!}
//!
//!fn main() {
//!    let sys = actix::System::new("http-server");
//!    // load ssl keys
//!    let config = load_ssl();
//!
//!     // create and start server at once
//!     server::new(|| {
//!         App::new()
//!             // register simple handler, handle all methods
//!             .resource("/index.html", |r| r.f(index))
//!             }))
//!     }).bind_rustls("127.0.0.1:8443", config)
//!     .unwrap()
//!     .start();
//!
//!     println!("Started http server: 127.0.0.1:8080");
//!     //Run system so that server would start accepting connections
//!     let _ = sys.run();
//!}
//! ```
use std::net::{Shutdown, SocketAddr};
use std::rc::Rc;
use std::{io, time};

use bytes::{BufMut, BytesMut};
use futures::{Async, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_tcp::TcpStream;

pub use actix_net::server::{PauseServer, ResumeServer, StopServer};

pub(crate) mod acceptor;
pub(crate) mod builder;
mod channel;
mod error;
pub(crate) mod h1;
pub(crate) mod h1decoder;
mod h1writer;
mod h2;
mod h2writer;
mod handler;
pub(crate) mod helpers;
mod http;
pub(crate) mod incoming;
pub(crate) mod input;
pub(crate) mod message;
pub(crate) mod output;
pub(crate) mod service;
pub(crate) mod settings;
mod ssl;

pub use self::handler::*;
pub use self::http::HttpServer;
pub use self::message::Request;
pub use self::ssl::*;

pub use self::error::{AcceptorError, HttpDispatchError};
pub use self::settings::ServerSettings;

#[doc(hidden)]
pub use self::acceptor::AcceptorTimeout;

#[doc(hidden)]
pub use self::settings::{ServiceConfig, ServiceConfigBuilder};

#[doc(hidden)]
pub use self::service::{H1Service, HttpService, StreamConfiguration};

#[doc(hidden)]
pub use self::helpers::write_content_length;

use body::Binary;
use extensions::Extensions;
use header::ContentEncoding;
use httpresponse::HttpResponse;

/// max buffer size 64k
pub(crate) const MAX_WRITE_BUFFER_SIZE: usize = 65_536;

const LW_BUFFER_SIZE: usize = 4096;
const HW_BUFFER_SIZE: usize = 32_768;

/// Create new http server with application factory.
///
/// This is shortcut for `server::HttpServer::new()` method.
///
/// ```rust
/// # extern crate actix_web;
/// # extern crate actix;
/// use actix_web::{server, App, HttpResponse};
///
/// fn main() {
///     let sys = actix::System::new("example");  // <- create Actix system
///
///     server::new(
///         || App::new()
///             .resource("/", |r| r.f(|_| HttpResponse::Ok())))
///         .bind("127.0.0.1:59090").unwrap()
///         .start();
///
/// #       actix::System::current().stop();
///     sys.run();
/// }
/// ```
pub fn new<F, H>(factory: F) -> HttpServer<H, F>
where
    F: Fn() -> H + Send + Clone + 'static,
    H: IntoHttpHandler + 'static,
{
    HttpServer::new(factory)
}

#[doc(hidden)]
bitflags! {
    ///Flags that can be used to configure HTTP Server.
    pub struct ServerFlags: u8 {
        ///Use HTTP1 protocol
        const HTTP1 = 0b0000_0001;
        ///Use HTTP2 protocol
        const HTTP2 = 0b0000_0010;
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
/// Server keep-alive setting
pub enum KeepAlive {
    /// Keep alive in seconds
    Timeout(usize),
    /// Use `SO_KEEPALIVE` socket option, value in seconds
    Tcp(usize),
    /// Relay on OS to shutdown tcp connection
    Os,
    /// Disabled
    Disabled,
}

impl From<usize> for KeepAlive {
    fn from(keepalive: usize) -> Self {
        KeepAlive::Timeout(keepalive)
    }
}

impl From<Option<usize>> for KeepAlive {
    fn from(keepalive: Option<usize>) -> Self {
        if let Some(keepalive) = keepalive {
            KeepAlive::Timeout(keepalive)
        } else {
            KeepAlive::Disabled
        }
    }
}

#[doc(hidden)]
#[derive(Debug)]
pub enum WriterState {
    Done,
    Pause,
}

#[doc(hidden)]
/// Stream writer
pub trait Writer {
    /// number of bytes written to the stream
    fn written(&self) -> u64;

    #[doc(hidden)]
    fn set_date(&mut self);

    #[doc(hidden)]
    fn buffer(&mut self) -> &mut BytesMut;

    fn start(
        &mut self, req: &Request, resp: &mut HttpResponse, encoding: ContentEncoding,
    ) -> io::Result<WriterState>;

    fn write(&mut self, payload: &Binary) -> io::Result<WriterState>;

    fn write_eof(&mut self) -> io::Result<WriterState>;

    fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error>;
}

#[doc(hidden)]
/// Low-level io stream operations
pub trait IoStream: AsyncRead + AsyncWrite + 'static {
    fn shutdown(&mut self, how: Shutdown) -> io::Result<()>;

    /// Returns the socket address of the remote peer of this TCP connection.
    fn peer_addr(&self) -> Option<SocketAddr> {
        None
    }

    /// Sets the value of the TCP_NODELAY option on this socket.
    fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()>;

    fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()>;

    fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()>;

    fn read_available(&mut self, buf: &mut BytesMut) -> Poll<(bool, bool), io::Error> {
        let mut read_some = false;
        loop {
            if buf.remaining_mut() < LW_BUFFER_SIZE {
                buf.reserve(HW_BUFFER_SIZE);
            }

            let read = unsafe { self.read(buf.bytes_mut()) };
            match read {
                Ok(n) => {
                    if n == 0 {
                        return Ok(Async::Ready((read_some, true)));
                    } else {
                        read_some = true;
                        unsafe {
                            buf.advance_mut(n);
                        }
                    }
                }
                Err(e) => {
                    return if e.kind() == io::ErrorKind::WouldBlock {
                        if read_some {
                            Ok(Async::Ready((read_some, false)))
                        } else {
                            Ok(Async::NotReady)
                        }
                    } else {
                        Err(e)
                    };
                }
            }
        }
    }

    /// Extra io stream extensions
    fn extensions(&self) -> Option<Rc<Extensions>> {
        None
    }
}

#[cfg(all(unix, feature = "uds"))]
impl IoStream for ::tokio_uds::UnixStream {
    #[inline]
    fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
        ::tokio_uds::UnixStream::shutdown(self, how)
    }

    #[inline]
    fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> {
        Ok(())
    }

    #[inline]
    fn set_linger(&mut self, _dur: Option<time::Duration>) -> io::Result<()> {
        Ok(())
    }

    #[inline]
    fn set_keepalive(&mut self, _dur: Option<time::Duration>) -> io::Result<()> {
        Ok(())
    }
}

impl IoStream for TcpStream {
    #[inline]
    fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
        TcpStream::shutdown(self, how)
    }

    #[inline]
    fn peer_addr(&self) -> Option<SocketAddr> {
        TcpStream::peer_addr(self).ok()
    }

    #[inline]
    fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
        TcpStream::set_nodelay(self, nodelay)
    }

    #[inline]
    fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
        TcpStream::set_linger(self, dur)
    }

    #[inline]
    fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
        TcpStream::set_keepalive(self, dur)
    }
}
<commit_msg>Add io handling for ECONNRESET when data has already been received<commit_after>//! Http server module
//!
//! The module contains everything necessary to setup
//! HTTP server.
//!
//! In order to start HTTP server, first you need to create and configure it
//! using factory that can be supplied to [new](fn.new.html).
//!
//! ## Factory
//!
//! Factory is a function that returns Application, describing how
//! to serve incoming HTTP requests.
//!
//! As the server uses worker pool, the factory function is restricted to trait bounds
//! `Send + Clone + 'static` so that each worker would be able to accept Application
//! without a need for synchronization.
//!
//! If you wish to share part of state among all workers you should
//! wrap it in `Arc` and potentially synchronization primitive like
//! [RwLock](https://doc.rust-lang.org/std/sync/struct.RwLock.html)
//! If the wrapped type is not thread safe.
//!
//! Note though that locking is not advisable for asynchronous programming
//! and you should minimize all locks in your request handlers
//!
//! ## HTTPS Support
//!
//! Actix-web provides support for major crates that provides TLS.
//! Each TLS implementation is provided with [AcceptorService](trait.AcceptorService.html)
//! that describes how HTTP Server accepts connections.
//!
//! For `bind` and `listen` there are corresponding `bind_ssl|tls|rustls` and `listen_ssl|tls|rustls` that accepts
//! these services.
//!
//! **NOTE:** `native-tls` doesn't support `HTTP2` yet
//!
//! ## Signal handling and shutdown
//!
//! By default HTTP Server listens for system signals
//! and, gracefully shuts down at most after 30 seconds.
//!
//! Both signal handling and shutdown timeout can be controlled
//! using corresponding methods.
//!
//! If worker, for some reason, unable to shut down within timeout
//! it is forcibly dropped.
//!
//! ## Example
//!
//! ```rust,ignore
//!extern crate actix;
//!extern crate actix_web;
//!extern crate rustls;
//!
//!use actix_web::{http, middleware, server, App, Error, HttpRequest, HttpResponse, Responder};
//!use std::io::BufReader;
//!use rustls::internal::pemfile::{certs, rsa_private_keys};
//!use rustls::{NoClientAuth, ServerConfig};
//!
//!fn index(req: &HttpRequest) -> Result<HttpResponse, Error> {
//!    Ok(HttpResponse::Ok().content_type("text/plain").body("Welcome!"))
//!}
//!
//!fn load_ssl() -> ServerConfig {
//!    use std::io::BufReader;
//!
//!    const CERT: &'static [u8] = include_bytes!("../cert.pem");
//!    const KEY: &'static [u8] = include_bytes!("../key.pem");
//!
//!    let mut cert = BufReader::new(CERT);
//!    let mut key = BufReader::new(KEY);
//!
//!    let mut config = ServerConfig::new(NoClientAuth::new());
//!    let cert_chain = certs(&mut cert).unwrap();
//!    let mut keys = rsa_private_keys(&mut key).unwrap();
//!    config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
//!
//!    config
//!}
//!
//!fn main() {
//!    let sys = actix::System::new("http-server");
//!    // load ssl keys
//!    let config = load_ssl();
//!
//!     // create and start server at once
//!     server::new(|| {
//!         App::new()
//!             // register simple handler, handle all methods
//!             .resource("/index.html", |r| r.f(index))
//!             }))
//!     }).bind_rustls("127.0.0.1:8443", config)
//!     .unwrap()
//!     .start();
//!
//!     println!("Started http server: 127.0.0.1:8080");
//!     //Run system so that server would start accepting connections
//!     let _ = sys.run();
//!}
//! ```
use std::net::{Shutdown, SocketAddr};
use std::rc::Rc;
use std::{io, time};

use bytes::{BufMut, BytesMut};
use futures::{Async, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_tcp::TcpStream;

pub use actix_net::server::{PauseServer, ResumeServer, StopServer};

pub(crate) mod acceptor;
pub(crate) mod builder;
mod channel;
mod error;
pub(crate) mod h1;
pub(crate) mod h1decoder;
mod h1writer;
mod h2;
mod h2writer;
mod handler;
pub(crate) mod helpers;
mod http;
pub(crate) mod incoming;
pub(crate) mod input;
pub(crate) mod message;
pub(crate) mod output;
pub(crate) mod service;
pub(crate) mod settings;
mod ssl;

pub use self::handler::*;
pub use self::http::HttpServer;
pub use self::message::Request;
pub use self::ssl::*;

pub use self::error::{AcceptorError, HttpDispatchError};
pub use self::settings::ServerSettings;

#[doc(hidden)]
pub use self::acceptor::AcceptorTimeout;

#[doc(hidden)]
pub use self::settings::{ServiceConfig, ServiceConfigBuilder};

#[doc(hidden)]
pub use self::service::{H1Service, HttpService, StreamConfiguration};

#[doc(hidden)]
pub use self::helpers::write_content_length;

use body::Binary;
use extensions::Extensions;
use header::ContentEncoding;
use httpresponse::HttpResponse;

/// max buffer size 64k
pub(crate) const MAX_WRITE_BUFFER_SIZE: usize = 65_536;

const LW_BUFFER_SIZE: usize = 4096;
const HW_BUFFER_SIZE: usize = 32_768;

/// Create new http server with application factory.
///
/// This is shortcut for `server::HttpServer::new()` method.
///
/// ```rust
/// # extern crate actix_web;
/// # extern crate actix;
/// use actix_web::{server, App, HttpResponse};
///
/// fn main() {
///     let sys = actix::System::new("example");  // <- create Actix system
///
///     server::new(
///         || App::new()
///             .resource("/", |r| r.f(|_| HttpResponse::Ok())))
///         .bind("127.0.0.1:59090").unwrap()
///         .start();
///
/// #       actix::System::current().stop();
///     sys.run();
/// }
/// ```
pub fn new<F, H>(factory: F) -> HttpServer<H, F>
where
    F: Fn() -> H + Send + Clone + 'static,
    H: IntoHttpHandler + 'static,
{
    HttpServer::new(factory)
}

#[doc(hidden)]
bitflags! {
    ///Flags that can be used to configure HTTP Server.
    pub struct ServerFlags: u8 {
        ///Use HTTP1 protocol
        const HTTP1 = 0b0000_0001;
        ///Use HTTP2 protocol
        const HTTP2 = 0b0000_0010;
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
/// Server keep-alive setting
pub enum KeepAlive {
    /// Keep alive in seconds
    Timeout(usize),
    /// Use `SO_KEEPALIVE` socket option, value in seconds
    Tcp(usize),
    /// Relay on OS to shutdown tcp connection
    Os,
    /// Disabled
    Disabled,
}

impl From<usize> for KeepAlive {
    fn from(keepalive: usize) -> Self {
        KeepAlive::Timeout(keepalive)
    }
}

impl From<Option<usize>> for KeepAlive {
    fn from(keepalive: Option<usize>) -> Self {
        if let Some(keepalive) = keepalive {
            KeepAlive::Timeout(keepalive)
        } else {
            KeepAlive::Disabled
        }
    }
}

#[doc(hidden)]
#[derive(Debug)]
pub enum WriterState {
    Done,
    Pause,
}

#[doc(hidden)]
/// Stream writer
pub trait Writer {
    /// number of bytes written to the stream
    fn written(&self) -> u64;

    #[doc(hidden)]
    fn set_date(&mut self);

    #[doc(hidden)]
    fn buffer(&mut self) -> &mut BytesMut;

    fn start(
        &mut self, req: &Request, resp: &mut HttpResponse, encoding: ContentEncoding,
    ) -> io::Result<WriterState>;

    fn write(&mut self, payload: &Binary) -> io::Result<WriterState>;

    fn write_eof(&mut self) -> io::Result<WriterState>;

    fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error>;
}

#[doc(hidden)]
/// Low-level io stream operations
pub trait IoStream: AsyncRead + AsyncWrite + 'static {
    fn shutdown(&mut self, how: Shutdown) -> io::Result<()>;

    /// Returns the socket address of the remote peer of this TCP connection.
    fn peer_addr(&self) -> Option<SocketAddr> {
        None
    }

    /// Sets the value of the TCP_NODELAY option on this socket.
    fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()>;

    fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()>;

    fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()>;

    fn read_available(&mut self, buf: &mut BytesMut) -> Poll<(bool, bool), io::Error> {
        let mut read_some = false;
        loop {
            if buf.remaining_mut() < LW_BUFFER_SIZE {
                buf.reserve(HW_BUFFER_SIZE);
            }

            let read = unsafe { self.read(buf.bytes_mut()) };
            match read {
                Ok(n) => {
                    if n == 0 {
                        return Ok(Async::Ready((read_some, true)));
                    } else {
                        read_some = true;
                        unsafe {
                            buf.advance_mut(n);
                        }
                    }
                }
                Err(e) => {
                    return if e.kind() == io::ErrorKind::WouldBlock {
                        if read_some {
                            Ok(Async::Ready((read_some, false)))
                        } else {
                            Ok(Async::NotReady)
                        }
                    } else if e.kind() == io::ErrorKind::ConnectionReset && read_some {
                        Ok(Async::Ready((read_some, true)))
                    } else {
                        Err(e)
                    };
                }
            }
        }
    }

    /// Extra io stream extensions
    fn extensions(&self) -> Option<Rc<Extensions>> {
        None
    }
}

#[cfg(all(unix, feature = "uds"))]
impl IoStream for ::tokio_uds::UnixStream {
    #[inline]
    fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
        ::tokio_uds::UnixStream::shutdown(self, how)
    }

    #[inline]
    fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> {
        Ok(())
    }

    #[inline]
    fn set_linger(&mut self, _dur: Option<time::Duration>) -> io::Result<()> {
        Ok(())
    }

    #[inline]
    fn set_keepalive(&mut self, _dur: Option<time::Duration>) -> io::Result<()> {
        Ok(())
    }
}

impl IoStream for TcpStream {
    #[inline]
    fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
        TcpStream::shutdown(self, how)
    }

    #[inline]
    fn peer_addr(&self) -> Option<SocketAddr> {
        TcpStream::peer_addr(self).ok()
    }

    #[inline]
    fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
        TcpStream::set_nodelay(self, nodelay)
    }

    #[inline]
    fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
        TcpStream::set_linger(self, dur)
    }

    #[inline]
    fn set_keepalive(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
        TcpStream::set_keepalive(self, dur)
    }
}
<|endoftext|>


<commit_before>
struct CircularBuffer<T : Copy> {
  seqno : usize,
  data  : Vec<T>,
}

impl <T : Copy> CircularBuffer<T> {
  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno : 0,
      data  : vec![],
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize(size, default_value);
    ret
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    let mut setter = setter;

    // calculate where to put the data
    let pos = self.seqno % self.data.len();

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(pos);

    // make sure the index worked
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno += 1;
    self.seqno
  }
}

pub fn tests() {
  let mut x = CircularBuffer::new(4, 0 as i32);
  x.put(|v| *v = 1);
  let mut y = 0;
  x.put(|v| { *v = y; y += 1; });
}

#[test]
#[should_panic]
fn create_zero_sized() {
  let _x = CircularBuffer::new(0, 0 as i32);
}

#[test]
fn create_non_zero_sized() {
  let _x = CircularBuffer::new(1, 0 as i32);
}

#[test]
fn can_put() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  x.put(|v| *v = 1);
}

#[test]
fn can_put_with_env() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  let my_fn = |v : &mut i32| {
    *v = y;
    y += 1;
  };
  x.put(my_fn);
}

#[test]
fn can_put_with_env2() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  x.put(|v| { *v = y; y += 1; });
}
<commit_msg>add get_range<commit_after>
struct CircularBuffer<T : Copy> {
  seqno : usize,
  data  : Vec<T>,
}

impl <T : Copy> CircularBuffer<T> {
  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno : 0,
      data  : vec![],
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize(size, default_value);
    ret
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    let mut setter = setter;

    // calculate where to put the data
    let pos = self.seqno % self.data.len();

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(pos);

    // make sure the index worked
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno += 1;
    self.seqno
  }

  fn get_range<F>(&self, from: &usize, to: &usize, getter: F) -> usize
    where F : FnMut(&T)
  {
    if from > to { panic!("from:{} > to:{}", from, to); }

    // figure out the minimum and maximum position
    let min_pos : usize = if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    };

    let max_pos : usize = self.seqno;

    // cannot return past (overwritten) elements
    if *to < min_pos { return min_pos; }

    // cannot return future elements
    if *from >= max_pos { return max_pos; }

    // constrain start to min_pos
    let start : usize = if *from > min_pos {
      *from
    } else {
      min_pos
    };

    // constrain end to max_pos
    let end : usize = if *to > max_pos {
      max_pos
    } else {
      *to
    };

    let start_pos   = start % self.data.len();
    let end_pos     = end % self.data.len();
    let mut getter  = getter;

    let mut get_range_fn = |from_pos: usize, to_pos: usize| {
      for i in from_pos..to_pos {
        let act_value : Option<&T> = self.data.get(i);
        match act_value {
          Some(v) => { getter(v); }
          None => { panic!("index is out of range i={}",i); }
        };
      }
    };

    if end_pos > start_pos {
      // one contigous range
      get_range_fn(start_pos, end_pos);
    } else {
      // range split into two
      get_range_fn(start_pos, self.data.len());
      get_range_fn(0, end_pos);
    }

    end
  }
}

pub fn tests() {
  let mut x = CircularBuffer::new(4, 0 as i32);
  x.put(|v| *v = 1);
  let mut y = 2;
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });

  let ret = x.get_range( &0, &100, |val : &i32| {
    println!("A: {}", *val);
  });

  println!("ret={}", ret);
}

#[test]
#[should_panic]
fn create_zero_sized() {
  let _x = CircularBuffer::new(0, 0 as i32);
}

#[test]
fn create_non_zero_sized() {
  let _x = CircularBuffer::new(1, 0 as i32);
}

#[test]
fn can_put() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  x.put(|v| *v = 1);
}

#[test]
fn can_put_with_env() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  let my_fn = |v : &mut i32| {
    *v = y;
    y += 1;
  };
  x.put(my_fn);
}

#[test]
fn can_put_with_env2() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  x.put(|v| { *v = y; y += 1; });
}
<|endoftext|>


<commit_before>#![feature(convert)]
#![feature(slice_patterns)]
#![feature(collections)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

struct VM<'a> {
  stack: Vec<Expr>,
  instructions: Vec<&'a str>,
  locals: HashMap<&'a str, Expr>,
}

fn parse_labels<'a>(instructions: &Vec<&'a str>) -> HashMap<&'a str, usize> {
  let mut map = HashMap::new();
  for (i, instr)
     in instructions.iter().enumerate() {
    if instr.starts_with("$label") {
      match instr.split(' ').nth(1) {
        Some(label) => map.insert(label, i),
        None => panic!("VM error: missing label"),
      };
    }
  };
  map
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      stack: Vec::new(),
      instructions: instructions,
      locals: HashMap::new(),
    }
  }

  fn unsafe_pop(&mut self) -> Expr {
    match self.stack.pop() {
      Some(expr) => expr,
      None => panic!("VM error: stack is empty"),
    }
  }

  pub fn run(&mut self) {
    let len = self.instructions.len();

    // VM variables (might be moved back to the struct itself)
    let mut ip = 0; // instruction pointer
    let mut carry = false; // comparison carry

    let labels = parse_labels(&self.instructions);

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      if instr.starts_with("#") {
        continue;
      }
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        ["$label", _] => (),
        ["push", "int", n] => self.stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        ["push", "str", n] => self.stack.push(Expr::Str(String::from_str(n))),

        ["dup"] => {
          let expr = self.unsafe_pop();
          self.stack.push(expr.clone());
          self.stack.push(expr);
        },

        // convert to string
        ["convert", "int", "str"] => if let Some(&Expr::Int(arg)) = self.stack.last() {
          self.stack.push(Expr::Str(arg.to_string()));
        } else {
          panic!("VM error: cannot convert int to string");
        },

        ["convert", from, to] => panic!("VM error: cannot convert from {} to {}", from, to),

        // how = "always" | "carry"
        ["jump", how, n] => {
          let new_ip = if n.starts_with("$") {
            labels.get(n.trim_matches('$')).expect("VM error: no such label").clone()
          } else {
            n.parse::<usize>().unwrap()
          };

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how == "always" || (how == "carry" && carry) {
              ip = new_ip;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        ["carry", "set", val] => carry = val == "true",
        ["carry", "invert"] => carry = !carry,

        ["call", "say"] => if let Some(Expr::Str(arg)) = self.stack.pop() {
          println!("hey {}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        ["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 + arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          self.stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `add`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        ["cmp", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          carry = match op {
            "<" => arg1 < arg2,
            ">" => arg1 > arg2,
            "<=" => arg1 <= arg2,
            ">=" => arg1 >= arg2,
            "=" => arg1 == arg2,
            _ => panic!("VM error: unrecognized `cmp` operator: {}", op),
          };
        } else {
          panic!("VM error: not enough arguments to `cmp`");
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        ["local", "load", name] => match self.locals.get(name) {
          Some(expr) => self.stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        ["local", "store", name] => if let Some(arg) = self.stack.pop() {
          let _ = self.locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        [instr, ..] => panic!("VM error: no such instruction {}", instr),
        [..] => panic!("VM error: Unrecognized instruction!"),
      }
    }
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<commit_msg>unline<commit_after>#![feature(convert)]
#![feature(slice_patterns)]
#![feature(collections)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::collections::HashMap;

#[derive(Clone)]
enum Expr {
  Int(i64),
  Str(String)
}

struct VM<'a> {
  stack: Vec<Expr>,
  instructions: Vec<&'a str>,
  locals: HashMap<&'a str, Expr>,
}

fn parse_labels<'a>(instructions: &Vec<&'a str>) -> HashMap<&'a str, usize> {
  let mut map = HashMap::new();
  for (i, instr) in instructions.iter().enumerate() {
    if instr.starts_with("$label") {
      match instr.split(' ').nth(1) {
        Some(label) => map.insert(label, i),
        None => panic!("VM error: missing label"),
      };
    }
  };
  map
}

impl<'a> VM<'a> {
  pub fn new(instructions: Vec<&'a str>) -> VM {
    VM {
      stack: Vec::new(),
      instructions: instructions,
      locals: HashMap::new(),
    }
  }

  fn unsafe_pop(&mut self) -> Expr {
    match self.stack.pop() {
      Some(expr) => expr,
      None => panic!("VM error: stack is empty"),
    }
  }

  pub fn run(&mut self) {
    let len = self.instructions.len();

    // VM variables (might be moved back to the struct itself)
    let mut ip = 0; // instruction pointer
    let mut carry = false; // comparison carry

    let labels = parse_labels(&self.instructions);

    while ip < len {
      let instr = self.instructions[ip];
      ip += 1;
      if instr.starts_with("#") {
        continue;
      }
      match instr.split(" ").collect::<Vec<_>>().as_slice() {
        ["$label", _] => (),
        ["push", "int", n] => self.stack.push(Expr::Int(n.parse::<i64>().unwrap())),
        ["push", "str", n] => self.stack.push(Expr::Str(String::from_str(n))),

        ["dup"] => {
          let expr = self.unsafe_pop();
          self.stack.push(expr.clone());
          self.stack.push(expr);
        },

        // convert to string
        ["convert", "int", "str"] => if let Some(&Expr::Int(arg)) = self.stack.last() {
          self.stack.push(Expr::Str(arg.to_string()));
        } else {
          panic!("VM error: cannot convert int to string");
        },

        ["convert", from, to] => panic!("VM error: cannot convert from {} to {}", from, to),

        // how = "always" | "carry"
        ["jump", how, n] => {
          let new_ip = if n.starts_with("$") {
            labels.get(n.trim_matches('$')).expect("VM error: no such label").clone()
          } else {
            n.parse::<usize>().unwrap()
          };

          if new_ip < len {
            // only check carry if we are conditionally jumping
            if how == "always" || (how == "carry" && carry) {
              ip = new_ip;
            }
          } else {
            panic!("VM error: trying to jump past end of bytecode ({} > {})", new_ip, len);
          }
        },

        ["carry", "set", val] => carry = val == "true",
        ["carry", "invert"] => carry = !carry,

        ["call", "say"] => if let Some(Expr::Str(arg)) = self.stack.pop() {
          println!("hey {}", arg);
        } else {
          panic!("VM error: incorrect arguments to `say`");
        },

        // NOTE: it's stack[*-1] OP stack[*-2]
        // which means if have stack=[1, 2]
        // you'll have 2 OP 1
        /// XXX this should JUST be a call!
        ["math", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          let value = match op {
            "+" => arg1 + arg2,
            "-" => arg1 + arg2,
            //"/" => TODO. this should have very specific rules...
            "*" => arg1 * arg2,
            _ => panic!("VM error: unrecognized `op` operator: {}", op),
          };
          self.stack.push(Expr::Int(value));
        } else {
          panic!("VM error: not enough arguments to `add`");
        },

        // same note about "2 OP 1"
        // XXX same note about how this should be a `call`
        ["cmp", op] => if let
            (Some(Expr::Int(arg1)), Some(Expr::Int(arg2)))
            =
            (self.stack.pop(), self.stack.pop()) {
          carry = match op {
            "<" => arg1 < arg2,
            ">" => arg1 > arg2,
            "<=" => arg1 <= arg2,
            ">=" => arg1 >= arg2,
            "=" => arg1 == arg2,
            _ => panic!("VM error: unrecognized `cmp` operator: {}", op),
          };
        } else {
          panic!("VM error: not enough arguments to `cmp`");
        },

        // TODO this *shouldn't* be an identifier
        //      the backend should transform SSAF to tons of load/store
        //      (probably)
        //      (see backend#1)
        ["local", "load", name] => match self.locals.get(name) {
          Some(expr) => self.stack.push(expr.clone()),
          None       => panic!("VM error: unknown local variable {}", name),
        },

        ["local", "store", name] => if let Some(arg) = self.stack.pop() {
          let _ = self.locals.insert(name, arg);
        } else {
          panic!("VM error: not enough arguments for `local store`");
        },

        [instr, ..] => panic!("VM error: no such instruction {}", instr),
        [..] => panic!("VM error: Unrecognized instruction!"),
      }
    }
  }
}

fn main() {
	if let Some(path) = env::args().nth(1) {
		println!("Loading file {}", path);

    match File::open(&path) {
      Ok(mut file) => {
        let mut content = String::new();
        if let Ok(_) = file.read_to_string(&mut content) {
          // remove trailing newlines, split by line
          let instructions = content.trim_matches('\n').split('\n').collect();
          let mut vm = VM::new(instructions);
          vm.run();
        }
      },
      Err(err) => {
        panic!("Can't read file {} (error: {})", path, err);
      }
    }
	} else {
    panic!("Please give a file argument");
  }

  //     let path = Path::new("chry.fa");
  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //  print!("{}", line.unwrap());
  //      }
}
<|endoftext|>


<commit_before>// Copyright 2016 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use kernel::*;
use kernel::Trilean::*;
use propagators::PropagatorKind;
use propagators::cmp::{x_leq_y, XLessYPlusZ};
use propagation::*;
use propagation::events::*;
use term::ops::*;
use term::expr_inference::ExprInference;
use gcollections::ops::*;
use gcollections::IntervalKind;
use std::fmt::{Formatter, Debug, Error};
use num::traits::Num;
use num::PrimInt;
use std::ops::{Add, Sub};
//use propagation::CStoreFD;

pub type CStore<VStore> = CStoreFD<VStore>;

pub struct Cumulative<V, VStore>
{
  starts: Vec<V>,
  durations: Vec<usize>,
  resources: Vec<usize>,
  capacity: usize,
  cstore: CStore<VStore>,

}

impl<V, VStore> PropagatorKind for Cumulative<V, VStore> {}

impl<V, B, VStore, Domain,> Cumulative<V, VStore>  where
    V: StoreRead<VStore, Value=Domain> + ViewDependencies<FDEvent> + StoreMonotonicUpdate<VStore, Domain> + ExprInference + Clone,
    Domain: Bounded<Bound=B> + ShrinkLeft<B> + StrictShrinkRight<B> + Empty + IntervalKind + Add<B> + Sub<B>,
    B: PartialOrd + Num + PrimInt + Clone
  {
  pub fn new(starts: Vec<V>, durations: Vec<usize>, resources: Vec<usize>, capacity: usize) -> Cumulative<V, VStore>
  {

    let mut cstore = CStore::empty();
    for j in 0..starts.len() - 1 {
      for i in 0..starts.len() - 1 {
        if i != j {
          // `s[i] <= s[j] /\ s[j] < s[i] + d[i]`
          cstore.alloc(x_leq_y(starts[i].clone(), starts[j].clone()));
          cstore.alloc(XLessYPlusZ::new(starts[j].clone(), starts[i].clone(), durations[i].clone()));
        }
      }
    }

    Cumulative { starts: starts, durations: durations, resources: resources, capacity: capacity, cstore: cstore}
  }
}

impl<V, VStore> Debug for Cumulative<V, VStore> where
  V: Debug,
{
  fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
    formatter.write_fmt(format_args!("TO BE DONE capacity:{:?}", self.capacity))
  }
}

impl<V, VStore> Subsumption<VStore> for Cumulative<V, VStore>
{
  fn is_subsumed(&self, store: &VStore) -> Trilean {

    self.cstore.is_subsumed(store)
  }
}

impl<Store, B, DomV, V, VStore> Propagator<Store> for Cumulative<V, VStore> where
  V: StoreRead<Store, Value=DomV> + StoreMonotonicUpdate<Store, DomV>,
  DomV: Bounded<Bound=B> + StrictShrinkLeft<B>,
  B: PartialOrd + Num,
{
  fn propagate(&mut self, store: &mut Store) -> bool {
    true
  }
}

impl<V, VStore> PropagatorDependencies<FDEvent> for Cumulative<V, VStore> where
  V: ViewDependencies<FDEvent>
{
  fn dependencies(&self) -> Vec<(usize, FDEvent)> {
    let mut deps = self.starts.iter().flat_map(|v| v.dependencies(FDEvent::Bound)).collect::<Vec<(usize, FDEvent)>>();
//    deps.append(self.cstore.dependencies(FDEvent::Bound));
    deps
  }
}

#[cfg(test)]
mod test {
  use super::*;
  use kernel::*;
  use kernel::Trilean::*;
  use propagation::events::*;
  use propagation::events::FDEvent::*;
  use interval::interval::*;
  use propagators::test::*;

  #[test]
  fn cumulative_test() {
    let dom0_10 = (0,10).to_interval();
    let dom10_20 = (10,20).to_interval();
    let dom10_11 = (10,11).to_interval();
    let dom5_15 = (5,15).to_interval();
    let dom1_10 = (1,10).to_interval();
    let dom5_10 = (5,10).to_interval();
    let dom6_10 = (6,10).to_interval();
    let dom1_1 = (1,1).to_interval();
    let dom2_2 = (2,2).to_interval();

    culmulative_test_one(1, dom0_10, dom0_10, dom0_10,
      Unknown, Unknown, vec![(0, Bound), (1, Bound), (2, Bound)], true);
    culmulative_test_one(2, dom10_11, dom5_15, dom5_15,
      Unknown, True, vec![(0, Assignment), (1, Assignment), (2, Assignment)], true);
    culmulative_test_one(3, dom10_20, dom1_1, dom1_1,
      True, True, vec![], true);
    culmulative_test_one(4, dom1_1, dom1_1, dom1_1,
      False, False, vec![], false);
    culmulative_test_one(5, dom2_2, dom1_1, dom1_1,
      False, False, vec![], false);
    culmulative_test_one(6, dom6_10, dom5_10, dom1_10,
      Unknown, Unknown, vec![(0, Bound), (1, Bound), (2, Bound)], true);
  }

  fn culmulative_test_one(test_num: u32,
    x: Interval<i32>, y: Interval<i32>, z: Interval<i32>,
    before: Trilean, after: Trilean,
    delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool)
  {
    trinary_propagator_test(test_num, XGreaterYPlusZ::new, x, y, z, before, after, delta_expected, propagate_success);
  }
}
<commit_msg>new cumulative attempt<commit_after>// Copyright 2016 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use kernel::*;
use kernel::Trilean::*;
use propagators::PropagatorKind;
use propagators::cmp::{x_leq_y, XLessYPlusZ};
use propagation::*;
use propagation::events::*;
use term::ops::*;
use term::expr_inference::ExprInference;
use gcollections::ops::*;
use gcollections::IntervalKind;
use std::fmt::{Formatter, Debug, Error};
use num::traits::Num;
use num::PrimInt;
use std::ops::{Add, Sub};
use variable::VStoreFD;
use term::identity::Identity;
//use propagation::CStoreFD;

type CStore<VStore> = CStoreFD<VStore>;
type VStore = VStoreFD;

pub fn cumulative (vstore: &mut VStore, cstore: &mut CStore<VStore>, starts: Vec<Identity<usize>>, durations: Vec<usize>, resources: Vec<usize>, capacity: usize)
  {

    let mut cstore = CStore::empty();
    for j in 0..starts.len() - 1 {
      for i in 0..starts.len() - 1 {
        if i != j {
          // `s[i] <= s[j] /\ s[j] < s[i] + d[i]`
          cstore.alloc(x_leq_y(starts[i], starts[j]));
 //         cstore.alloc(XLessYPlusZ::new(starts[j].clone(), starts[i].clone(), durations[i].clone()));
        }
      }
    }
}

pub struct Cumulative<V, VStore>
{
  starts: Vec<V>,
  durations: Vec<usize>,
  resources: Vec<usize>,
  capacity: usize,
  cstore: CStore<VStore>,

}

impl<V, VStore> PropagatorKind for Cumulative<V, VStore> {}

impl<V, B, VStore, Domain,> Cumulative<V, VStore>  where
    V: StoreRead<VStore, Value=Domain> + ViewDependencies<FDEvent> + StoreMonotonicUpdate<VStore, Domain> + ExprInference + Clone,
    Domain: Bounded<Bound=B> + ShrinkLeft<B> + StrictShrinkRight<B> + Empty + IntervalKind + Add<B> + Sub<B>,
    B: PartialOrd + Num + PrimInt + Clone
  {
  pub fn new(starts: Vec<V>, durations: Vec<usize>, resources: Vec<usize>, capacity: usize) -> Cumulative<V, VStore>
  {

    let mut cstore = CStore::empty();
    for j in 0..starts.len() - 1 {
      for i in 0..starts.len() - 1 {
        if i != j {
          // `s[i] <= s[j] /\ s[j] < s[i] + d[i]`
 //         cstore.alloc(x_leq_y(starts[i].clone(), starts[j].clone()));
  //        cstore.alloc(XLessYPlusZ::new(starts[j].clone(), starts[i].clone(), durations[i].clone()));
        }
      }
    }

    Cumulative { starts: starts, durations: durations, resources: resources, capacity: capacity, cstore: cstore}
  }
}

impl<V, VStore> Debug for Cumulative<V, VStore> where
  V: Debug,
{
  fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
    formatter.write_fmt(format_args!("TO BE DONE capacity:{:?}", self.capacity))
  }
}

impl<V, VStore> Subsumption<VStore> for Cumulative<V, VStore>
{
  fn is_subsumed(&self, store: &VStore) -> Trilean {

    self.cstore.is_subsumed(store)
  }
}

impl<Store, B, DomV, V, VStore> Propagator<Store> for Cumulative<V, VStore> where
  V: StoreRead<Store, Value=DomV> + StoreMonotonicUpdate<Store, DomV>,
  DomV: Bounded<Bound=B> + StrictShrinkLeft<B>,
  B: PartialOrd + Num,
{
  fn propagate(&mut self, store: &mut Store) -> bool {
    true
  }
}

impl<V, VStore> PropagatorDependencies<FDEvent> for Cumulative<V, VStore> where
  V: ViewDependencies<FDEvent>
{
  fn dependencies(&self) -> Vec<(usize, FDEvent)> {
    let mut deps = self.starts.iter().flat_map(|v| v.dependencies(FDEvent::Bound)).collect::<Vec<(usize, FDEvent)>>();
//    deps.append(self.cstore.dependencies(FDEvent::Bound));
    deps
  }
}

#[cfg(test)]
mod test {
  use super::*;
  use kernel::*;
  use kernel::Trilean::*;
  use propagation::events::*;
  use propagation::events::FDEvent::*;
  use interval::interval::*;
  use propagators::test::*;

  #[test]
  fn cumulative_test() {
    let dom0_10 = (0,10).to_interval();
    let dom10_20 = (10,20).to_interval();
    let dom10_11 = (10,11).to_interval();
    let dom5_15 = (5,15).to_interval();
    let dom1_10 = (1,10).to_interval();
    let dom5_10 = (5,10).to_interval();
    let dom6_10 = (6,10).to_interval();
    let dom1_1 = (1,1).to_interval();
    let dom2_2 = (2,2).to_interval();

    culmulative_test_one(1, dom0_10, dom0_10, dom0_10,
      Unknown, Unknown, vec![(0, Bound), (1, Bound), (2, Bound)], true);
    culmulative_test_one(2, dom10_11, dom5_15, dom5_15,
      Unknown, True, vec![(0, Assignment), (1, Assignment), (2, Assignment)], true);
    culmulative_test_one(3, dom10_20, dom1_1, dom1_1,
      True, True, vec![], true);
    culmulative_test_one(4, dom1_1, dom1_1, dom1_1,
      False, False, vec![], false);
    culmulative_test_one(5, dom2_2, dom1_1, dom1_1,
      False, False, vec![], false);
    culmulative_test_one(6, dom6_10, dom5_10, dom1_10,
      Unknown, Unknown, vec![(0, Bound), (1, Bound), (2, Bound)], true);
  }

  fn culmulative_test_one(test_num: u32,
    x: Interval<i32>, y: Interval<i32>, z: Interval<i32>,
    before: Trilean, after: Trilean,
    delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool)
  {
    trinary_propagator_test(test_num, XGreaterYPlusZ::new, x, y, z, before, after, delta_expected, propagate_success);
  }
}
<|endoftext|>


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

//! Hash Function
//!
//! Primary hash function used in the protocol
//!

use byteorder::{BigEndian, ByteOrder};
use std::cmp::min;
use std::convert::AsRef;
use std::ops::Add;
use std::{fmt, ops};

use crate::blake2::blake2b::Blake2b;

use crate::ser::{self, AsFixedBytes, Error, FixedLength, Readable, Reader, Writeable, Writer};
use crate::util;

/// A hash consisting of all zeroes, used as a sentinel. No known preimage.
pub const ZERO_HASH: Hash = Hash([0; 32]);

/// A hash to uniquely (or close enough) identify one of the main blockchain
/// constructs. Used pervasively for blocks, transactions and outputs.
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct Hash([u8; 32]);

impl fmt::Debug for Hash {
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		for i in self.0[..4].iter() {
			write!(f, "{:02x}", i)?;
		}
		Ok(())
	}
}

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

impl FixedLength for Hash {
	/// Size of a hash in bytes.
	const LEN: usize = 32;
}

impl Hash {
	/// Builds a Hash from a byte vector. If the vector is too short, it will be
	/// completed by zeroes. If it's too long, it will be truncated.
	pub fn from_vec(v: &[u8]) -> Hash {
		let mut h = [0; Hash::LEN];
		let copy_size = min(v.len(), Hash::LEN);
		h[..copy_size].copy_from_slice(&v[..copy_size]);
		Hash(h)
	}

	/// Converts the hash to a byte vector
	pub fn to_vec(&self) -> Vec<u8> {
		self.0.to_vec()
	}

	/// Returns a byte slice of the hash contents.
	pub fn as_bytes(&self) -> &[u8] {
		&self.0
	}

	/// Convert a hash to hex string format.
	pub fn to_hex(&self) -> String {
		util::to_hex(self.to_vec())
	}

	/// Convert hex string back to hash.
	pub fn from_hex(hex: &str) -> Result<Hash, Error> {
		let bytes = util::from_hex(hex.to_string())
			.map_err(|_| Error::HexError(format!("failed to decode {}", hex)))?;
		Ok(Hash::from_vec(&bytes))
	}

	/// Most significant 64 bits
	pub fn to_u64(&self) -> u64 {
		BigEndian::read_u64(&self.0)
	}
}

impl ops::Index<usize> for Hash {
	type Output = u8;

	fn index(&self, idx: usize) -> &u8 {
		&self.0[idx]
	}
}

impl ops::Index<ops::Range<usize>> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::Range<usize>) -> &[u8] {
		&self.0[idx]
	}
}

impl ops::Index<ops::RangeTo<usize>> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::RangeTo<usize>) -> &[u8] {
		&self.0[idx]
	}
}

impl ops::Index<ops::RangeFrom<usize>> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::RangeFrom<usize>) -> &[u8] {
		&self.0[idx]
	}
}

impl ops::Index<ops::RangeFull> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::RangeFull) -> &[u8] {
		&self.0[idx]
	}
}

impl AsRef<[u8]> for Hash {
	fn as_ref(&self) -> &[u8] {
		&self.0
	}
}

impl Readable for Hash {
	fn read(reader: &mut dyn Reader) -> Result<Hash, ser::Error> {
		let v = reader.read_fixed_bytes(32)?;
		let mut a = [0; 32];
		a.copy_from_slice(&v[..]);
		Ok(Hash(a))
	}
}

impl Writeable for Hash {
	fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
		writer.write_fixed_bytes(&self.0)
	}
}

impl Add for Hash {
	type Output = Hash;
	fn add(self, other: Hash) -> Hash {
		self.hash_with(other)
	}
}

impl Default for Hash {
	fn default() -> Hash {
		ZERO_HASH
	}
}

/// Serializer that outputs a hash of the serialized object
pub struct HashWriter {
	state: Blake2b,
}

impl HashWriter {
	/// Consume the `HashWriter`, outputting its current hash into a 32-byte
	/// array
	pub fn finalize(self, output: &mut [u8]) {
		output.copy_from_slice(self.state.finalize().as_bytes());
	}

	/// Consume the `HashWriter`, outputting a `Hash` corresponding to its
	/// current state
	pub fn into_hash(self) -> Hash {
		let mut res = [0; 32];
		res.copy_from_slice(self.state.finalize().as_bytes());
		Hash(res)
	}
}

impl Default for HashWriter {
	fn default() -> HashWriter {
		HashWriter {
			state: Blake2b::new(32),
		}
	}
}

impl ser::Writer for HashWriter {
	fn serialization_mode(&self) -> ser::SerializationMode {
		ser::SerializationMode::Hash
	}

	fn write_fixed_bytes<T: AsFixedBytes>(&mut self, b32: &T) -> Result<(), ser::Error> {
		self.state.update(b32.as_ref());
		Ok(())
	}
}

/// A trait for types that have a canonical hash
pub trait Hashed {
	/// Obtain the hash of the object
	fn hash(&self) -> Hash;
	/// Hash the object together with another writeable object
	fn hash_with<T: Writeable>(&self, other: T) -> Hash;
}

impl<W: ser::Writeable> Hashed for W {
	fn hash(&self) -> Hash {
		let mut hasher = HashWriter::default();
		ser::Writeable::write(self, &mut hasher).unwrap();
		let mut ret = [0; 32];
		hasher.finalize(&mut ret);
		Hash(ret)
	}

	fn hash_with<T: Writeable>(&self, other: T) -> Hash {
		let mut hasher = HashWriter::default();
		ser::Writeable::write(self, &mut hasher).unwrap();
		ser::Writeable::write(&other, &mut hasher).unwrap();
		let mut ret = [0; 32];
		hasher.finalize(&mut ret);
		Hash(ret)
	}
}
<commit_msg>Replace default fmt::Display on core::Hash (#2325)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Hash Function
//!
//! Primary hash function used in the protocol
//!

use byteorder::{BigEndian, ByteOrder};
use std::cmp::min;
use std::convert::AsRef;
use std::ops::Add;
use std::{fmt, ops};

use crate::blake2::blake2b::Blake2b;

use crate::ser::{self, AsFixedBytes, Error, FixedLength, Readable, Reader, Writeable, Writer};
use crate::util;

/// A hash consisting of all zeroes, used as a sentinel. No known preimage.
pub const ZERO_HASH: Hash = Hash([0; 32]);

/// A hash to uniquely (or close enough) identify one of the main blockchain
/// constructs. Used pervasively for blocks, transactions and outputs.
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct Hash([u8; 32]);

impl fmt::Debug for Hash {
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		let hash_hex = self.to_hex();
		const NUM_SHOW: usize = 12;

		write!(f, "{}...", &hash_hex[..NUM_SHOW])
	}
}

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

impl FixedLength for Hash {
	/// Size of a hash in bytes.
	const LEN: usize = 32;
}

impl Hash {
	/// Builds a Hash from a byte vector. If the vector is too short, it will be
	/// completed by zeroes. If it's too long, it will be truncated.
	pub fn from_vec(v: &[u8]) -> Hash {
		let mut h = [0; Hash::LEN];
		let copy_size = min(v.len(), Hash::LEN);
		h[..copy_size].copy_from_slice(&v[..copy_size]);
		Hash(h)
	}

	/// Converts the hash to a byte vector
	pub fn to_vec(&self) -> Vec<u8> {
		self.0.to_vec()
	}

	/// Returns a byte slice of the hash contents.
	pub fn as_bytes(&self) -> &[u8] {
		&self.0
	}

	/// Convert a hash to hex string format.
	pub fn to_hex(&self) -> String {
		util::to_hex(self.to_vec())
	}

	/// Convert hex string back to hash.
	pub fn from_hex(hex: &str) -> Result<Hash, Error> {
		let bytes = util::from_hex(hex.to_string())
			.map_err(|_| Error::HexError(format!("failed to decode {}", hex)))?;
		Ok(Hash::from_vec(&bytes))
	}

	/// Most significant 64 bits
	pub fn to_u64(&self) -> u64 {
		BigEndian::read_u64(&self.0)
	}
}

impl ops::Index<usize> for Hash {
	type Output = u8;

	fn index(&self, idx: usize) -> &u8 {
		&self.0[idx]
	}
}

impl ops::Index<ops::Range<usize>> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::Range<usize>) -> &[u8] {
		&self.0[idx]
	}
}

impl ops::Index<ops::RangeTo<usize>> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::RangeTo<usize>) -> &[u8] {
		&self.0[idx]
	}
}

impl ops::Index<ops::RangeFrom<usize>> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::RangeFrom<usize>) -> &[u8] {
		&self.0[idx]
	}
}

impl ops::Index<ops::RangeFull> for Hash {
	type Output = [u8];

	fn index(&self, idx: ops::RangeFull) -> &[u8] {
		&self.0[idx]
	}
}

impl AsRef<[u8]> for Hash {
	fn as_ref(&self) -> &[u8] {
		&self.0
	}
}

impl Readable for Hash {
	fn read(reader: &mut dyn Reader) -> Result<Hash, ser::Error> {
		let v = reader.read_fixed_bytes(32)?;
		let mut a = [0; 32];
		a.copy_from_slice(&v[..]);
		Ok(Hash(a))
	}
}

impl Writeable for Hash {
	fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
		writer.write_fixed_bytes(&self.0)
	}
}

impl Add for Hash {
	type Output = Hash;
	fn add(self, other: Hash) -> Hash {
		self.hash_with(other)
	}
}

impl Default for Hash {
	fn default() -> Hash {
		ZERO_HASH
	}
}

/// Serializer that outputs a hash of the serialized object
pub struct HashWriter {
	state: Blake2b,
}

impl HashWriter {
	/// Consume the `HashWriter`, outputting its current hash into a 32-byte
	/// array
	pub fn finalize(self, output: &mut [u8]) {
		output.copy_from_slice(self.state.finalize().as_bytes());
	}

	/// Consume the `HashWriter`, outputting a `Hash` corresponding to its
	/// current state
	pub fn into_hash(self) -> Hash {
		let mut res = [0; 32];
		res.copy_from_slice(self.state.finalize().as_bytes());
		Hash(res)
	}
}

impl Default for HashWriter {
	fn default() -> HashWriter {
		HashWriter {
			state: Blake2b::new(32),
		}
	}
}

impl ser::Writer for HashWriter {
	fn serialization_mode(&self) -> ser::SerializationMode {
		ser::SerializationMode::Hash
	}

	fn write_fixed_bytes<T: AsFixedBytes>(&mut self, b32: &T) -> Result<(), ser::Error> {
		self.state.update(b32.as_ref());
		Ok(())
	}
}

/// A trait for types that have a canonical hash
pub trait Hashed {
	/// Obtain the hash of the object
	fn hash(&self) -> Hash;
	/// Hash the object together with another writeable object
	fn hash_with<T: Writeable>(&self, other: T) -> Hash;
}

impl<W: ser::Writeable> Hashed for W {
	fn hash(&self) -> Hash {
		let mut hasher = HashWriter::default();
		ser::Writeable::write(self, &mut hasher).unwrap();
		let mut ret = [0; 32];
		hasher.finalize(&mut ret);
		Hash(ret)
	}

	fn hash_with<T: Writeable>(&self, other: T) -> Hash {
		let mut hasher = HashWriter::default();
		ser::Writeable::write(self, &mut hasher).unwrap();
		ser::Writeable::write(&other, &mut hasher).unwrap();
		let mut ret = [0; 32];
		hasher.finalize(&mut ret);
		Hash(ret)
	}
}
<|endoftext|>