<commit_before>use core;
use error;

use std::ffi::OsStr;
use std::io;
use std::mem;
use std::ptr;
use std::time::Duration;

use std::os::windows::prelude::*;

use core::{SerialDevice, SerialPortSettings};

use libc::c_void;
use ffi::*;

/// A serial port implementation for Windows COM ports.
///
/// The port will be closed when the value is dropped.
pub struct COMPort {
    handle: HANDLE,
    timeout: Duration,
}

unsafe impl Send for COMPort {}

impl COMPort {
    /// Opens a COM port as a serial device.
    ///
    /// `port` should be the name of a COM port, e.g., `COM1`.
    ///
    /// ```no_run
    /// serial_windows::COMPort::open("COM1").unwrap();
    /// ```
    ///
    /// ## Errors
    ///
    /// * `NoDevice` if the device could not be opened. This could indicate that the device is
    ///   already in use.
    /// * `InvalidInput` if `port` is not a valid device name.
    /// * `Io` for any other I/O error while opening or initializing the device.
    pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> core::Result<Self> {
        let mut name = Vec::<u16>::new();

        name.extend(OsStr::new("\\\\.\\").encode_wide());
        name.extend(port.as_ref().encode_wide());
        name.push(0);

        let handle = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ | GENERIC_WRITE, 0, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 as HANDLE)
        };

        let timeout = Duration::from_millis(100);

        if handle != INVALID_HANDLE_VALUE {
            let mut port = COMPort {
                handle: handle,
                timeout: timeout,
            };

            try!(port.set_timeout(timeout));
            Ok(port)
        }
        else {
            Err(error::last_os_error())
        }
    }

    fn escape_comm_function(&mut self, function: DWORD) -> core::Result<()> {
        match unsafe { EscapeCommFunction(self.handle, function) } {
            0 => Err(error::last_os_error()),
            _ => Ok(()),
        }
    }

    fn read_pin(&mut self, pin: DWORD) -> core::Result<bool> {
        let mut status: DWORD = unsafe { mem::uninitialized() };

        match unsafe { GetCommModemStatus(self.handle, &mut status) } {
            0 => Err(error::last_os_error()),
            _ => Ok(status & pin != 0),
        }
    }
}

impl Drop for COMPort {
    fn drop(&mut self) {
        unsafe {
            CloseHandle(self.handle);
        }
    }
}

impl AsRawHandle for COMPort {
    fn as_raw_handle(&self) -> RawHandle {
        unsafe {
            mem::transmute(self.handle)
        }
    }
}

impl io::Read for COMPort {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { ReadFile(self.handle, buf.as_mut_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => {
                if len != 0 {
                    Ok(len as usize)
                }
                else {
                    Err(io::Error::new(io::ErrorKind::TimedOut, "Operation timed out"))
                }
            }
        }
    }
}

impl io::Write for COMPort {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { WriteFile(self.handle, buf.as_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(len as usize),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match unsafe { FlushFileBuffers(self.handle) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(()),
        }
    }
}

impl SerialDevice for COMPort {
    type Settings = COMSettings;

    fn read_settings(&self) -> core::Result<COMSettings> {
        let mut dcb = DCB::new();

        match unsafe { GetCommState(self.handle, &mut dcb) } {
            0 => Err(error::last_os_error()),
            _ => Ok(COMSettings { inner: dcb }),

        }
    }

    fn write_settings(&mut self, settings: &COMSettings) -> core::Result<()> {
        match unsafe { SetCommState(self.handle, &settings.inner) } {
            0 => Err(error::last_os_error()),
            _ => Ok(()),
        }
    }

    fn timeout(&self) -> Duration {
        self.timeout
    }

    fn set_timeout(&mut self, timeout: Duration) -> core::Result<()> {
        let milliseconds = timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000;

        let timeouts = COMMTIMEOUTS {
            ReadIntervalTimeout: 0,
            ReadTotalTimeoutMultiplier: 0,
            ReadTotalTimeoutConstant: milliseconds as DWORD,
            WriteTotalTimeoutMultiplier: 0,
            WriteTotalTimeoutConstant: 0,
        };

        if unsafe { SetCommTimeouts(self.handle, &timeouts) } == 0 {
            return Err(error::last_os_error());
        }

        self.timeout = timeout;
        Ok(())
    }

    fn set_rts(&mut self, level: bool) -> core::Result<()> {
        if level {
            self.escape_comm_function(SETRTS)
        }
        else {
            self.escape_comm_function(CLRRTS)
        }
    }

    fn set_dtr(&mut self, level: bool) -> core::Result<()> {
        if level {
            self.escape_comm_function(SETDTR)
        }
        else {
            self.escape_comm_function(CLRDTR)
        }
    }

    fn read_cts(&mut self) -> core::Result<bool> {
        self.read_pin(MS_CTS_ON)
    }

    fn read_dsr(&mut self) -> core::Result<bool> {
        self.read_pin(MS_DSR_ON)
    }

    fn read_ri(&mut self) -> core::Result<bool> {
        self.read_pin(MS_RING_ON)
    }

    fn read_cd(&mut self) -> core::Result<bool> {
        self.read_pin(MS_RLSD_ON)
    }
}

/// Serial port settings for COM ports.
#[derive(Copy,Clone,Debug)]
pub struct COMSettings {
    inner: DCB,
}

impl SerialPortSettings for COMSettings {
    fn baud_rate(&self) -> Option<core::BaudRate> {
        match self.inner.BaudRate {
            CBR_110    => Some(core::Baud110),
            CBR_300    => Some(core::Baud300),
            CBR_600    => Some(core::Baud600),
            CBR_1200   => Some(core::Baud1200),
            CBR_2400   => Some(core::Baud2400),
            CBR_4800   => Some(core::Baud4800),
            CBR_9600   => Some(core::Baud9600),
            CBR_14400  => Some(core::BaudOther(14400)),
            CBR_19200  => Some(core::Baud19200),
            CBR_38400  => Some(core::Baud38400),
            CBR_56000  => Some(core::BaudOther(56000)),
            CBR_57600  => Some(core::Baud57600),
            CBR_115200 => Some(core::Baud115200),
            CBR_128000 => Some(core::BaudOther(128000)),
            CBR_256000 => Some(core::BaudOther(256000)),
            n          => Some(core::BaudOther(n as usize)),
        }
    }

    fn char_size(&self) -> Option<core::CharSize> {
        match self.inner.ByteSize {
            5 => Some(core::Bits5),
            6 => Some(core::Bits6),
            7 => Some(core::Bits7),
            8 => Some(core::Bits8),
            _ => None,
        }
    }

    fn parity(&self) -> Option<core::Parity> {
        match self.inner.Parity {
            ODDPARITY  => Some(core::ParityOdd),
            EVENPARITY => Some(core::ParityEven),
            NOPARITY   => Some(core::ParityNone),
            _          => None,
        }
    }

    fn stop_bits(&self) -> Option<core::StopBits> {
        match self.inner.StopBits {
            TWOSTOPBITS => Some(core::Stop2),
            ONESTOPBIT  => Some(core::Stop1),
            _           => None,
        }
    }

    fn flow_control(&self) -> Option<core::FlowControl> {
        if self.inner.fBits & (fOutxCtsFlow | fRtsControl) != 0 {
            Some(core::FlowHardware)
        }
        else if self.inner.fBits & (fOutX | fInX) != 0 {
            Some(core::FlowSoftware)
        }
        else {
            Some(core::FlowNone)
        }
    }

    fn set_baud_rate(&mut self, baud_rate: core::BaudRate) -> core::Result<()> {
        self.inner.BaudRate = match baud_rate {
            core::Baud110      => CBR_110,
            core::Baud300      => CBR_300,
            core::Baud600      => CBR_600,
            core::Baud1200     => CBR_1200,
            core::Baud2400     => CBR_2400,
            core::Baud4800     => CBR_4800,
            core::Baud9600     => CBR_9600,
            core::Baud19200    => CBR_19200,
            core::Baud38400    => CBR_38400,
            core::Baud57600    => CBR_57600,
            core::Baud115200   => CBR_115200,
            core::BaudOther(n) => n as DWORD,
        };

        Ok(())
    }

    fn set_char_size(&mut self, char_size: core::CharSize) {
        self.inner.ByteSize = match char_size {
            core::Bits5 => 5,
            core::Bits6 => 6,
            core::Bits7 => 7,
            core::Bits8 => 8,
        }
    }

    fn set_parity(&mut self, parity: core::Parity) {
        self.inner.Parity = match parity {
            core::ParityNone => NOPARITY,
            core::ParityOdd  => ODDPARITY,
            core::ParityEven => EVENPARITY,
        }
    }

    fn set_stop_bits(&mut self, stop_bits: core::StopBits) {
        self.inner.StopBits = match stop_bits {
            core::Stop1 => ONESTOPBIT,
            core::Stop2 => TWOSTOPBITS,
        }
    }

    fn set_flow_control(&mut self, flow_control: core::FlowControl) {
        match flow_control {
            core::FlowNone => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits &= !(fOutX | fInX);
            }
            core::FlowSoftware => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits |= fOutX | fInX;
            }
            core::FlowHardware => {
                self.inner.fBits |= fOutxCtsFlow | fRtsControl;
                self.inner.fBits &= !(fOutX | fInX);
            }
        }
    }
}
<commit_msg>sets binary, parity, and DTR handling for COM ports<commit_after>use core;
use error;

use std::ffi::OsStr;
use std::io;
use std::mem;
use std::ptr;
use std::time::Duration;

use std::os::windows::prelude::*;

use core::{SerialDevice, SerialPortSettings};

use libc::c_void;
use ffi::*;

/// A serial port implementation for Windows COM ports.
///
/// The port will be closed when the value is dropped.
pub struct COMPort {
    handle: HANDLE,
    timeout: Duration,
}

unsafe impl Send for COMPort {}

impl COMPort {
    /// Opens a COM port as a serial device.
    ///
    /// `port` should be the name of a COM port, e.g., `COM1`.
    ///
    /// ```no_run
    /// serial_windows::COMPort::open("COM1").unwrap();
    /// ```
    ///
    /// ## Errors
    ///
    /// * `NoDevice` if the device could not be opened. This could indicate that the device is
    ///   already in use.
    /// * `InvalidInput` if `port` is not a valid device name.
    /// * `Io` for any other I/O error while opening or initializing the device.
    pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> core::Result<Self> {
        let mut name = Vec::<u16>::new();

        name.extend(OsStr::new("\\\\.\\").encode_wide());
        name.extend(port.as_ref().encode_wide());
        name.push(0);

        let handle = unsafe {
            CreateFileW(name.as_ptr(), GENERIC_READ | GENERIC_WRITE, 0, ptr::null_mut(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 as HANDLE)
        };

        let timeout = Duration::from_millis(100);

        if handle != INVALID_HANDLE_VALUE {
            let mut port = COMPort {
                handle: handle,
                timeout: timeout,
            };

            try!(port.set_timeout(timeout));
            Ok(port)
        }
        else {
            Err(error::last_os_error())
        }
    }

    fn escape_comm_function(&mut self, function: DWORD) -> core::Result<()> {
        match unsafe { EscapeCommFunction(self.handle, function) } {
            0 => Err(error::last_os_error()),
            _ => Ok(()),
        }
    }

    fn read_pin(&mut self, pin: DWORD) -> core::Result<bool> {
        let mut status: DWORD = unsafe { mem::uninitialized() };

        match unsafe { GetCommModemStatus(self.handle, &mut status) } {
            0 => Err(error::last_os_error()),
            _ => Ok(status & pin != 0),
        }
    }
}

impl Drop for COMPort {
    fn drop(&mut self) {
        unsafe {
            CloseHandle(self.handle);
        }
    }
}

impl AsRawHandle for COMPort {
    fn as_raw_handle(&self) -> RawHandle {
        unsafe {
            mem::transmute(self.handle)
        }
    }
}

impl io::Read for COMPort {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { ReadFile(self.handle, buf.as_mut_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => {
                if len != 0 {
                    Ok(len as usize)
                }
                else {
                    Err(io::Error::new(io::ErrorKind::TimedOut, "Operation timed out"))
                }
            }
        }
    }
}

impl io::Write for COMPort {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut len: DWORD = 0;

        match unsafe { WriteFile(self.handle, buf.as_ptr() as *mut c_void, buf.len() as DWORD, &mut len, ptr::null_mut()) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(len as usize),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match unsafe { FlushFileBuffers(self.handle) } {
            0 => Err(io::Error::last_os_error()),
            _ => Ok(()),
        }
    }
}

impl SerialDevice for COMPort {
    type Settings = COMSettings;

    fn read_settings(&self) -> core::Result<COMSettings> {
        let mut dcb = DCB::new();

        match unsafe { GetCommState(self.handle, &mut dcb) } {
            0 => Err(error::last_os_error()),
            _ => {
                dcb.fBits |= fBinary;
                dcb.fBits &= fDtrControl;

                Ok(COMSettings { inner: dcb })
            }

        }
    }

    fn write_settings(&mut self, settings: &COMSettings) -> core::Result<()> {
        match unsafe { SetCommState(self.handle, &settings.inner) } {
            0 => Err(error::last_os_error()),
            _ => Ok(()),
        }
    }

    fn timeout(&self) -> Duration {
        self.timeout
    }

    fn set_timeout(&mut self, timeout: Duration) -> core::Result<()> {
        let milliseconds = timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1_000_000;

        let timeouts = COMMTIMEOUTS {
            ReadIntervalTimeout: 0,
            ReadTotalTimeoutMultiplier: 0,
            ReadTotalTimeoutConstant: milliseconds as DWORD,
            WriteTotalTimeoutMultiplier: 0,
            WriteTotalTimeoutConstant: 0,
        };

        if unsafe { SetCommTimeouts(self.handle, &timeouts) } == 0 {
            return Err(error::last_os_error());
        }

        self.timeout = timeout;
        Ok(())
    }

    fn set_rts(&mut self, level: bool) -> core::Result<()> {
        if level {
            self.escape_comm_function(SETRTS)
        }
        else {
            self.escape_comm_function(CLRRTS)
        }
    }

    fn set_dtr(&mut self, level: bool) -> core::Result<()> {
        if level {
            self.escape_comm_function(SETDTR)
        }
        else {
            self.escape_comm_function(CLRDTR)
        }
    }

    fn read_cts(&mut self) -> core::Result<bool> {
        self.read_pin(MS_CTS_ON)
    }

    fn read_dsr(&mut self) -> core::Result<bool> {
        self.read_pin(MS_DSR_ON)
    }

    fn read_ri(&mut self) -> core::Result<bool> {
        self.read_pin(MS_RING_ON)
    }

    fn read_cd(&mut self) -> core::Result<bool> {
        self.read_pin(MS_RLSD_ON)
    }
}

/// Serial port settings for COM ports.
#[derive(Copy,Clone,Debug)]
pub struct COMSettings {
    inner: DCB,
}

impl SerialPortSettings for COMSettings {
    fn baud_rate(&self) -> Option<core::BaudRate> {
        match self.inner.BaudRate {
            CBR_110    => Some(core::Baud110),
            CBR_300    => Some(core::Baud300),
            CBR_600    => Some(core::Baud600),
            CBR_1200   => Some(core::Baud1200),
            CBR_2400   => Some(core::Baud2400),
            CBR_4800   => Some(core::Baud4800),
            CBR_9600   => Some(core::Baud9600),
            CBR_14400  => Some(core::BaudOther(14400)),
            CBR_19200  => Some(core::Baud19200),
            CBR_38400  => Some(core::Baud38400),
            CBR_56000  => Some(core::BaudOther(56000)),
            CBR_57600  => Some(core::Baud57600),
            CBR_115200 => Some(core::Baud115200),
            CBR_128000 => Some(core::BaudOther(128000)),
            CBR_256000 => Some(core::BaudOther(256000)),
            n          => Some(core::BaudOther(n as usize)),
        }
    }

    fn char_size(&self) -> Option<core::CharSize> {
        match self.inner.ByteSize {
            5 => Some(core::Bits5),
            6 => Some(core::Bits6),
            7 => Some(core::Bits7),
            8 => Some(core::Bits8),
            _ => None,
        }
    }

    fn parity(&self) -> Option<core::Parity> {
        match self.inner.Parity {
            ODDPARITY  => Some(core::ParityOdd),
            EVENPARITY => Some(core::ParityEven),
            NOPARITY   => Some(core::ParityNone),
            _          => None,
        }
    }

    fn stop_bits(&self) -> Option<core::StopBits> {
        match self.inner.StopBits {
            TWOSTOPBITS => Some(core::Stop2),
            ONESTOPBIT  => Some(core::Stop1),
            _           => None,
        }
    }

    fn flow_control(&self) -> Option<core::FlowControl> {
        if self.inner.fBits & (fOutxCtsFlow | fRtsControl) != 0 {
            Some(core::FlowHardware)
        }
        else if self.inner.fBits & (fOutX | fInX) != 0 {
            Some(core::FlowSoftware)
        }
        else {
            Some(core::FlowNone)
        }
    }

    fn set_baud_rate(&mut self, baud_rate: core::BaudRate) -> core::Result<()> {
        self.inner.BaudRate = match baud_rate {
            core::Baud110      => CBR_110,
            core::Baud300      => CBR_300,
            core::Baud600      => CBR_600,
            core::Baud1200     => CBR_1200,
            core::Baud2400     => CBR_2400,
            core::Baud4800     => CBR_4800,
            core::Baud9600     => CBR_9600,
            core::Baud19200    => CBR_19200,
            core::Baud38400    => CBR_38400,
            core::Baud57600    => CBR_57600,
            core::Baud115200   => CBR_115200,
            core::BaudOther(n) => n as DWORD,
        };

        Ok(())
    }

    fn set_char_size(&mut self, char_size: core::CharSize) {
        self.inner.ByteSize = match char_size {
            core::Bits5 => 5,
            core::Bits6 => 6,
            core::Bits7 => 7,
            core::Bits8 => 8,
        };
    }

    fn set_parity(&mut self, parity: core::Parity) {
        self.inner.Parity = match parity {
            core::ParityNone => NOPARITY,
            core::ParityOdd  => ODDPARITY,
            core::ParityEven => EVENPARITY,
        };

        if parity == core::ParityNone {
            self.inner.fBits &= !fParity;
        }
        else {
            self.inner.fBits |= fParity;
        }
    }

    fn set_stop_bits(&mut self, stop_bits: core::StopBits) {
        self.inner.StopBits = match stop_bits {
            core::Stop1 => ONESTOPBIT,
            core::Stop2 => TWOSTOPBITS,
        };
    }

    fn set_flow_control(&mut self, flow_control: core::FlowControl) {
        match flow_control {
            core::FlowNone => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits &= !(fOutX | fInX);
            }
            core::FlowSoftware => {
                self.inner.fBits &= !(fOutxCtsFlow | fRtsControl);
                self.inner.fBits |= fOutX | fInX;
            }
            core::FlowHardware => {
                self.inner.fBits |= fOutxCtsFlow | fRtsControl;
                self.inner.fBits &= !(fOutX | fInX);
            }
        }
    }
}
<|endoftext|>


<commit_before>// lib/option::rs

tag t<@T> { none; some(T); }

fn get<@T>(opt: t<T>) -> &T {
    alt opt { some(x) { ret x; } none. { fail "option none"; } }
}

fn map<@T, @U>(f: block(T) -> U, opt: t<T>) -> t<U> {
    alt opt { some(x) { some(f(x)) } none. { none } }
}

fn is_none<@T>(opt: t<T>) -> bool {
    alt opt { none. { true } some(_) { false } }
}

fn is_some<@T>(opt: t<T>) -> bool { !is_none(opt) }

fn from_maybe<@T>(def: T, opt: t<T>) -> T {
    alt opt { some(x) { x } none. { def } }
}

fn maybe<@T, @U>(def: U, f: block(T) -> U, opt: t<T>) -> U {
    alt opt { none. { def } some(t) { f(t) } }
}

// Can be defined in terms of the above when/if we have const bind.
fn may<@T>(f: block(T), opt: t<T>) {
    alt opt { none. {/* nothing */ } some(t) { f(t); } }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>Revert "Make option::get return the option contents by reference" due to memory corruption<commit_after>// lib/option::rs

tag t<@T> { none; some(T); }

fn get<@T>(opt: t<T>) -> T {
    alt opt { some(x) { x } none. { fail "option none" } }
}

fn map<@T, @U>(f: block(T) -> U, opt: t<T>) -> t<U> {
    alt opt { some(x) { some(f(x)) } none. { none } }
}

fn is_none<@T>(opt: t<T>) -> bool {
    alt opt { none. { true } some(_) { false } }
}

fn is_some<@T>(opt: t<T>) -> bool { !is_none(opt) }

fn from_maybe<@T>(def: T, opt: t<T>) -> T {
    alt opt { some(x) { x } none. { def } }
}

fn maybe<@T, @U>(def: U, f: block(T) -> U, opt: t<T>) -> U {
    alt opt { none. { def } some(t) { f(t) } }
}

// Can be defined in terms of the above when/if we have const bind.
fn may<@T>(f: block(T), opt: t<T>) {
    alt opt { none. {/* nothing */ } some(t) { f(t); } }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>extern crate reqwest;
extern crate serde_json;
extern crate url;

fn query_turbo(query: &str) -> Result<String, Box<dyn std::error::Error>> {
    let url = "http://overpass-api.de/api/interpreter";

    let client = reqwest::Client::new();
    let body = String::from(query);
    let mut buf = client.post(url)
        .body(body)
        .send()?;
    match buf.text() {
        Ok(value) => Ok(value),
        Err(error) => Err(Box::new(error)),
    }
}

fn query_nominatim(query: &str) -> Result<String, Box<dyn std::error::Error>> {
    let prefix = "http://nominatim.openstreetmap.org/search.php?";
    let encoded: String = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("q", query)
        .append_pair("format", "json")
        .finish();
    let url = format!("{}{}", prefix, encoded);

    let mut buf = reqwest::get(url.as_str())?;

    match buf.text() {
        Ok(value) => Ok(value),
        Err(error) => Err(Box::new(error)),
    }
}

fn osmify(query: &str) -> Result<(), Box<dyn std::error::Error>> {
    let nominatim = query_nominatim(query)?;
    let json: serde_json::Value = serde_json::from_str(&nominatim)?;
    let mut elements = json.as_array().ok_or("option::NoneError")?.clone();
    if elements.is_empty() {
        println!("No results from nominatim");
        return Ok(());
    }

    if elements.len() > 1 {
        // There are multiple elements, prefer buildings if possible.
        let buildings: Vec<serde_json::Value> = elements.iter().filter(|i| {
            let i = match i.as_object() {
                Some(value) => value,
                None => return false,
            };
            let class = match i.get("class") {
                Some(value) => value.as_str(),
                None => return false,
            };
            match class {
                Some(value) => value == "building",
                None => false,
            }
        } ).map(|i| i.clone()).collect();

        if !buildings.is_empty() {
            elements = buildings;
        }
    }

    let element = elements[0].as_object().ok_or("option::NoneError")?;
    let lat = element["lat"].as_str().ok_or("option::NoneError")?;
    let lon = element["lon"].as_str().ok_or("option::NoneError")?;
    let object_type = element["osm_type"].as_str().ok_or("option::NoneError")?;
    let object_id = element["osm_id"].as_str().ok_or("option::NoneError")?;

    // Use overpass to get the properties of the object.
    let overpass_query = format!(r#"[out:json];
(
    {}({});
);
out body;"#, object_type, object_id);
    let turbo = query_turbo(&overpass_query)?;
    let json: serde_json::Value = serde_json::from_str(&turbo)?;
    let json = json.as_object().ok_or("option::NoneError")?;
    let elements = &json["elements"].as_array().ok_or("option::NoneError")?;
    if elements.is_empty() {
        println!("No results from overpass");
        return Ok(());
    }

    let element = &elements[0];
    let tags = element["tags"].as_object().ok_or("option::NoneError")?;
    let city = tags["addr:city"].as_str().ok_or("option::NoneError")?;
    let housenumber = tags["addr:housenumber"].as_str().ok_or("option::NoneError")?;
    let postcode = tags["addr:postcode"].as_str().ok_or("option::NoneError")?;
    let street = tags["addr:street"].as_str().ok_or("option::NoneError")?;
    let addr = format!("{} {}, {} {}", postcode, city, street, housenumber);

    // Print the result.
    println!("geo:{},{} ({})", lat, lon, addr);
    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args: Vec<String> = std::env::args().collect();

    if args.len() > 1 {
        osmify(&args[1])?;
    } else {
        println!("usage: addr-osmify <query>");
        println!("");
        println!("e.g. addr-osmify 'Mészáros utca 58/a, Budapest'");
    }

    Ok(())
}
<commit_msg>addr-osmify-rust: improve error handling further<commit_after>extern crate reqwest;
extern crate serde_json;
extern crate url;

#[derive(Debug)]
struct OsmifyError {
    details: String
}

impl OsmifyError {
    fn new(msg: &str) -> OsmifyError {
        OsmifyError{details: msg.to_string()}
    }
}

impl std::fmt::Display for OsmifyError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.details)
    }
}

impl std::error::Error for OsmifyError {
    fn description(&self) -> &str {
        &self.details
    }
}

fn query_turbo(query: &str) -> Result<String, Box<dyn std::error::Error>> {
    let url = "http://overpass-api.de/api/interpreter";

    let client = reqwest::Client::new();
    let body = String::from(query);
    let mut buf = client.post(url)
        .body(body)
        .send()?;
    match buf.text() {
        Ok(value) => Ok(value),
        Err(error) => Err(Box::new(error)),
    }
}

fn query_nominatim(query: &str) -> Result<String, Box<dyn std::error::Error>> {
    let prefix = "http://nominatim.openstreetmap.org/search.php?";
    let encoded: String = url::form_urlencoded::Serializer::new(String::new())
        .append_pair("q", query)
        .append_pair("format", "json")
        .finish();
    let url = format!("{}{}", prefix, encoded);

    let mut buf = reqwest::get(url.as_str())?;

    Ok(buf.text()?)
}

fn osmify(query: &str) -> Result<String, Box<dyn std::error::Error>> {
    let nominatim = query_nominatim(query)?;
    let json: serde_json::Value = match serde_json::from_str(&nominatim) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from nominatim: {:?}", error))));
        },
    };
    let mut elements = json.as_array().ok_or("option::NoneError")?.clone();
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from nominatim")));
    }

    if elements.len() > 1 {
        // There are multiple elements, prefer buildings if possible.
        let buildings: Vec<serde_json::Value> = elements.iter().filter(|i| {
            let i = match i.as_object() {
                Some(value) => value,
                None => return false,
            };
            let class = match i.get("class") {
                Some(value) => value.as_str(),
                None => return false,
            };
            match class {
                Some(value) => value == "building",
                None => false,
            }
        } ).map(|i| i.clone()).collect();

        if !buildings.is_empty() {
            elements = buildings;
        }
    }

    let element = elements[0].as_object().ok_or("option::NoneError")?;
    let lat = element["lat"].as_str().ok_or("option::NoneError")?;
    let lon = element["lon"].as_str().ok_or("option::NoneError")?;
    let object_type = element["osm_type"].as_str().ok_or("option::NoneError")?;
    let object_id = element["osm_id"].as_str().ok_or("option::NoneError")?;

    // Use overpass to get the properties of the object.
    let overpass_query = format!(r#"[out:json];
(
    {}({});
);
out body;"#, object_type, object_id);
    let turbo = query_turbo(&overpass_query)?;
    let json: serde_json::Value = match serde_json::from_str(&turbo) {
        Ok(value) => value,
        Err(error) => {
            return Err(Box::new(OsmifyError::new(&format!("Failed to parse JSON from overpass: {:?}", error))));
        },
    };
    let json = json.as_object().ok_or("option::NoneError")?;
    let elements = &json["elements"].as_array().ok_or("option::NoneError")?;
    if elements.is_empty() {
        return Err(Box::new(OsmifyError::new("No results from overpass")));
    }

    let element = &elements[0];
    let tags = element["tags"].as_object().ok_or("option::NoneError")?;
    let city = tags["addr:city"].as_str().ok_or("option::NoneError")?;
    let housenumber = tags["addr:housenumber"].as_str().ok_or("option::NoneError")?;
    let postcode = tags["addr:postcode"].as_str().ok_or("option::NoneError")?;
    let street = tags["addr:street"].as_str().ok_or("option::NoneError")?;
    let addr = format!("{} {}, {} {}", postcode, city, street, housenumber);

    // Print the result.
    Ok(String::from(format!("geo:{},{} ({})", lat, lon, addr)))
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args: Vec<String> = std::env::args().collect();

    if args.len() > 1 {
        let result = osmify(&args[1])?;
        println!("{}", result);
    } else {
        println!("usage: addr-osmify <query>");
        println!("");
        println!("e.g. addr-osmify 'Mészáros utca 58/a, Budapest'");
    }

    Ok(())
}
<|endoftext|>


<commit_before>use super::AttestationData;
use crate::spec::ChainSpec;
use crate::test_utils::TestRandom;
use bls::AggregateSignature;
use rand::RngCore;
use serde_derive::Serialize;
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};

#[derive(Debug, PartialEq, Clone, Serialize)]
pub struct SlashableVoteData {
    pub custody_bit_0_indices: Vec<u32>,
    pub custody_bit_1_indices: Vec<u32>,
    pub data: AttestationData,
    pub aggregate_signature: AggregateSignature,
}

impl SlashableVoteData {
    pub fn is_double_vote(&self, other: &SlashableVoteData, spec: &ChainSpec) -> bool {
        self.data.slot.epoch(spec.epoch_length) == other.data.slot.epoch(spec.epoch_length)
    }

    pub fn is_surround_vote(&self, other: &SlashableVoteData, spec: &ChainSpec) -> bool {
        let source_epoch_1 = self.data.justified_epoch;
        let source_epoch_2 = other.data.justified_epoch;
        let target_epoch_1 = self.data.slot.epoch(spec.epoch_length);
        let target_epoch_2 = other.data.slot.epoch(spec.epoch_length);

        (source_epoch_1 < source_epoch_2) && (target_epoch_2 < target_epoch_1)
    }
}

impl Encodable for SlashableVoteData {
    fn ssz_append(&self, s: &mut SszStream) {
        s.append_vec(&self.custody_bit_0_indices);
        s.append_vec(&self.custody_bit_1_indices);
        s.append(&self.data);
        s.append(&self.aggregate_signature);
    }
}

impl Decodable for SlashableVoteData {
    fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
        let (custody_bit_0_indices, i) = <_>::ssz_decode(bytes, i)?;
        let (custody_bit_1_indices, i) = <_>::ssz_decode(bytes, i)?;
        let (data, i) = <_>::ssz_decode(bytes, i)?;
        let (aggregate_signature, i) = <_>::ssz_decode(bytes, i)?;

        Ok((
            SlashableVoteData {
                custody_bit_0_indices,
                custody_bit_1_indices,
                data,
                aggregate_signature,
            },
            i,
        ))
    }
}

impl TreeHash for SlashableVoteData {
    fn hash_tree_root(&self) -> Vec<u8> {
        let mut result: Vec<u8> = vec![];
        result.append(&mut self.custody_bit_0_indices.hash_tree_root());
        result.append(&mut self.custody_bit_1_indices.hash_tree_root());
        result.append(&mut self.data.hash_tree_root());
        result.append(&mut self.aggregate_signature.hash_tree_root());
        hash(&result)
    }
}

impl<T: RngCore> TestRandom<T> for SlashableVoteData {
    fn random_for_test(rng: &mut T) -> Self {
        Self {
            custody_bit_0_indices: <_>::random_for_test(rng),
            custody_bit_1_indices: <_>::random_for_test(rng),
            data: <_>::random_for_test(rng),
            aggregate_signature: <_>::random_for_test(rng),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::slot_epoch_height::{Epoch, Slot};
    use crate::spec::ChainSpec;
    use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
    use ssz::ssz_encode;

    #[test]
    pub fn test_is_double_vote_true() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(1, 1, &spec);

        assert_eq!(
            slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
            true
        )
    }

    #[test]
    pub fn test_is_double_vote_false() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(2, 1, &spec);

        assert_eq!(
            slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
            false
        );
    }

    #[test]
    pub fn test_is_surround_vote_true() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(2, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(1, 2, &spec);

        assert_eq!(
            slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
            true
        );
    }

    #[test]
    pub fn test_is_surround_vote_false_source_epoch_fails() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(2, 2, &spec);
        let slashable_vote_second = create_slashable_vote_data(1, 1, &spec);

        assert_eq!(
            slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
            false
        );
    }

    #[test]
    pub fn test_is_surround_vote_false_target_epoch_fails() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(2, 2, &spec);

        assert_eq!(
            slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
            false
        );
    }

    #[test]
    pub fn test_ssz_round_trip() {
        let mut rng = XorShiftRng::from_seed([42; 16]);
        let original = SlashableVoteData::random_for_test(&mut rng);

        let bytes = ssz_encode(&original);
        let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();

        assert_eq!(original, decoded);
    }

    #[test]
    pub fn test_hash_tree_root() {
        let mut rng = XorShiftRng::from_seed([42; 16]);
        let original = SlashableVoteData::random_for_test(&mut rng);

        let result = original.hash_tree_root();

        assert_eq!(result.len(), 32);
        // TODO: Add further tests
        // https://github.com/sigp/lighthouse/issues/170
    }

    fn create_slashable_vote_data(
        slot_factor: u64,
        justified_epoch: u64,
        spec: &ChainSpec,
    ) -> SlashableVoteData {
        let mut rng = XorShiftRng::from_seed([42; 16]);
        let mut slashable_vote = SlashableVoteData::random_for_test(&mut rng);

        slashable_vote.data.slot = Slot::new(slot_factor * spec.epoch_length);
        slashable_vote.data.justified_epoch = Epoch::new(justified_epoch);
        slashable_vote
    }
}
<commit_msg>adapted import due to renaming of crate slot_epoch_height -> slot_epoch (lighthouse-150)<commit_after>use super::AttestationData;
use crate::spec::ChainSpec;
use crate::test_utils::TestRandom;
use bls::AggregateSignature;
use rand::RngCore;
use serde_derive::Serialize;
use ssz::{hash, Decodable, DecodeError, Encodable, SszStream, TreeHash};

#[derive(Debug, PartialEq, Clone, Serialize)]
pub struct SlashableVoteData {
    pub custody_bit_0_indices: Vec<u32>,
    pub custody_bit_1_indices: Vec<u32>,
    pub data: AttestationData,
    pub aggregate_signature: AggregateSignature,
}

impl SlashableVoteData {
    pub fn is_double_vote(&self, other: &SlashableVoteData, spec: &ChainSpec) -> bool {
        self.data.slot.epoch(spec.epoch_length) == other.data.slot.epoch(spec.epoch_length)
    }

    pub fn is_surround_vote(&self, other: &SlashableVoteData, spec: &ChainSpec) -> bool {
        let source_epoch_1 = self.data.justified_epoch;
        let source_epoch_2 = other.data.justified_epoch;
        let target_epoch_1 = self.data.slot.epoch(spec.epoch_length);
        let target_epoch_2 = other.data.slot.epoch(spec.epoch_length);

        (source_epoch_1 < source_epoch_2) && (target_epoch_2 < target_epoch_1)
    }
}

impl Encodable for SlashableVoteData {
    fn ssz_append(&self, s: &mut SszStream) {
        s.append_vec(&self.custody_bit_0_indices);
        s.append_vec(&self.custody_bit_1_indices);
        s.append(&self.data);
        s.append(&self.aggregate_signature);
    }
}

impl Decodable for SlashableVoteData {
    fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
        let (custody_bit_0_indices, i) = <_>::ssz_decode(bytes, i)?;
        let (custody_bit_1_indices, i) = <_>::ssz_decode(bytes, i)?;
        let (data, i) = <_>::ssz_decode(bytes, i)?;
        let (aggregate_signature, i) = <_>::ssz_decode(bytes, i)?;

        Ok((
            SlashableVoteData {
                custody_bit_0_indices,
                custody_bit_1_indices,
                data,
                aggregate_signature,
            },
            i,
        ))
    }
}

impl TreeHash for SlashableVoteData {
    fn hash_tree_root(&self) -> Vec<u8> {
        let mut result: Vec<u8> = vec![];
        result.append(&mut self.custody_bit_0_indices.hash_tree_root());
        result.append(&mut self.custody_bit_1_indices.hash_tree_root());
        result.append(&mut self.data.hash_tree_root());
        result.append(&mut self.aggregate_signature.hash_tree_root());
        hash(&result)
    }
}

impl<T: RngCore> TestRandom<T> for SlashableVoteData {
    fn random_for_test(rng: &mut T) -> Self {
        Self {
            custody_bit_0_indices: <_>::random_for_test(rng),
            custody_bit_1_indices: <_>::random_for_test(rng),
            data: <_>::random_for_test(rng),
            aggregate_signature: <_>::random_for_test(rng),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::slot_epoch::{Epoch, Slot};
    use crate::spec::ChainSpec;
    use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
    use ssz::ssz_encode;

    #[test]
    pub fn test_is_double_vote_true() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(1, 1, &spec);

        assert_eq!(
            slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
            true
        )
    }

    #[test]
    pub fn test_is_double_vote_false() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(2, 1, &spec);

        assert_eq!(
            slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
            false
        );
    }

    #[test]
    pub fn test_is_surround_vote_true() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(2, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(1, 2, &spec);

        assert_eq!(
            slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
            true
        );
    }

    #[test]
    pub fn test_is_surround_vote_false_source_epoch_fails() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(2, 2, &spec);
        let slashable_vote_second = create_slashable_vote_data(1, 1, &spec);

        assert_eq!(
            slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
            false
        );
    }

    #[test]
    pub fn test_is_surround_vote_false_target_epoch_fails() {
        let spec = ChainSpec::foundation();
        let slashable_vote_first = create_slashable_vote_data(1, 1, &spec);
        let slashable_vote_second = create_slashable_vote_data(2, 2, &spec);

        assert_eq!(
            slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
            false
        );
    }

    #[test]
    pub fn test_ssz_round_trip() {
        let mut rng = XorShiftRng::from_seed([42; 16]);
        let original = SlashableVoteData::random_for_test(&mut rng);

        let bytes = ssz_encode(&original);
        let (decoded, _) = <_>::ssz_decode(&bytes, 0).unwrap();

        assert_eq!(original, decoded);
    }

    #[test]
    pub fn test_hash_tree_root() {
        let mut rng = XorShiftRng::from_seed([42; 16]);
        let original = SlashableVoteData::random_for_test(&mut rng);

        let result = original.hash_tree_root();

        assert_eq!(result.len(), 32);
        // TODO: Add further tests
        // https://github.com/sigp/lighthouse/issues/170
    }

    fn create_slashable_vote_data(
        slot_factor: u64,
        justified_epoch: u64,
        spec: &ChainSpec,
    ) -> SlashableVoteData {
        let mut rng = XorShiftRng::from_seed([42; 16]);
        let mut slashable_vote = SlashableVoteData::random_for_test(&mut rng);

        slashable_vote.data.slot = Slot::new(slot_factor * spec.epoch_length);
        slashable_vote.data.justified_epoch = Epoch::new(justified_epoch);
        slashable_vote
    }
}
<|endoftext|>


<commit_before>//! Connector with hyper backend.

use std::fmt;
use std::str::FromStr;
use std::rc::Rc;

use futures::{Future, Stream};
use futures::future::result;
use hyper;
use hyper::{Method, Uri};
use hyper::client::{Client, Connect};
use hyper::header::ContentType;
use hyper_tls::HttpsConnector;
use tokio_core::reactor::Handle;

use telegram_bot_raw::{Body as TelegramBody, HttpRequest, HttpResponse, Method as TelegramMethod};

use errors::Error;
use future::{NewTelegramFuture, TelegramFuture};

use super::_base::Connector;

/// This connector uses `hyper` backend.
pub struct HyperConnector<C> {
    inner: Rc<Client<C>>,
}

impl<C> fmt::Debug for HyperConnector<C> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        "hyper connector".fmt(formatter)
    }
}

impl<C> HyperConnector<C> {
    pub fn new(client: Client<C>) -> Self {
        HyperConnector {
            inner: Rc::new(client),
        }
    }
}

mod multipart {
    use multipart::client::lazy::*;
    use telegram_bot_raw::MultipartValue;
    use hyper::client::Request;

    struct Adapter<'d> {
        prepared: PreparedFields<'d>,
    }

    impl<'d> From<Vec<(String, MultipartValue)>> for Adapter<'d> {
        fn from(fields: Vec<(String, MultipartValue)>) -> Self {
            let mut data = Multipart::new();
            for (key, value) in fields.into_iter() {
                match value {
                    MultipartValue::Text(text) => {
                        data.add_text(key, text);
                    }
                    MultipartValue::File { filename: _, path } => {
                        data.add_file(key, path);
                    }
                }
            }
            Self {
                prepared: data.prepare().unwrap(),
            }
        }
    }

    impl<'d> Adapter<'d> {
        pub fn set_header(&mut self, req: &mut Request) {
            use hyper::header::ContentLength;

            let boundary = self.prepared.boundary();
            req.headers_mut().set_raw(
                "Content-Type",
                vec![
                    format!("multipart/form-data;boundary={bound}", bound = boundary).into_bytes(),
                ],
            );
            if let Some(len) = self.prepared.content_len() {
                req.headers_mut().set(ContentLength(len));
            }
        }

        pub fn set_body(&mut self, req: &mut Request) {
            use std::io::Read;

            let mut bytes = Vec::new();
            self.prepared.read_to_end(&mut bytes).unwrap();
            req.set_body(bytes);
        }
    }

}

impl<C: Connect> Connector for HyperConnector<C> {
    fn request(&self, token: &str, req: HttpRequest) -> TelegramFuture<HttpResponse> {
        let uri = result(Uri::from_str(&req.url.url(token))).map_err(From::from);

        let client = self.inner.clone();
        let request = uri.and_then(move |uri| {
            let method = match req.method {
                TelegramMethod::Get => Method::Get,
                TelegramMethod::Post => Method::Post,
            };
            let mut http_request = hyper::client::Request::new(method, uri);

            match req.body {
                TelegramBody::Empty => (),
                TelegramBody::Json(body) => {
                    http_request.set_body(body);
                    http_request.headers_mut().set(ContentType::json());
                }
                TelegramBody::Multipart(_parts) => {
                    // TODO
                }
                body => panic!("Unknown body type {:?}", body),
            }

            client.request(http_request).from_err()
        });

        let future = request.and_then(move |response| {
            response.body().map_err(From::from).fold(
                vec![],
                |mut result, chunk| -> Result<Vec<u8>, Error> {
                    result.extend_from_slice(&chunk);
                    Ok(result)
                },
            )
        });

        let future = future.and_then(|body| Ok(HttpResponse { body: Some(body) }));

        TelegramFuture::new(Box::new(future))
    }
}

/// Returns default hyper connector. Uses one resolve thread and `HttpsConnector`.
pub fn default_connector(handle: &Handle) -> Result<Box<Connector>, Error> {
    let connector = HttpsConnector::new(1, handle).map_err(|err| {
        ::std::io::Error::new(::std::io::ErrorKind::Other, format!("tls error: {}", err))
    })?;
    let config = Client::configure().connector(connector);
    Ok(Box::new(HyperConnector::new(config.build(handle))))
}
<commit_msg>handle Multipart for hyper connector<commit_after>//! Connector with hyper backend.

use std::fmt;
use std::str::FromStr;
use std::rc::Rc;

use futures::{Future, Stream};
use futures::future::result;
use hyper;
use hyper::{Method, Uri};
use hyper::client::{Client, Connect};
use hyper::header::ContentType;
use hyper_tls::HttpsConnector;
use tokio_core::reactor::Handle;

use telegram_bot_raw::{Body as TelegramBody, HttpRequest, HttpResponse, Method as TelegramMethod};

use errors::Error;
use future::{NewTelegramFuture, TelegramFuture};

use super::_base::Connector;

/// This connector uses `hyper` backend.
pub struct HyperConnector<C> {
    inner: Rc<Client<C>>,
}

impl<C> fmt::Debug for HyperConnector<C> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        "hyper connector".fmt(formatter)
    }
}

impl<C> HyperConnector<C> {
    pub fn new(client: Client<C>) -> Self {
        HyperConnector {
            inner: Rc::new(client),
        }
    }
}

mod multipart {
    use multipart::client::lazy::*;
    use telegram_bot_raw::MultipartValue;
    use hyper::client::Request;

    pub struct Adapter<'d> {
        prepared: PreparedFields<'d>,
    }

    impl<'d> From<Vec<(String, MultipartValue)>> for Adapter<'d> {
        fn from(fields: Vec<(String, MultipartValue)>) -> Self {
            let mut data = Multipart::new();
            for (key, value) in fields.into_iter() {
                match value {
                    MultipartValue::Text(text) => {
                        data.add_text(key, text);
                    }
                    MultipartValue::File { filename: _, path } => {
                        data.add_file(key, path);
                    }
                }
            }
            Self {
                prepared: data.prepare().unwrap(),
            }
        }
    }

    impl<'d> Adapter<'d> {
        pub fn set_header(&mut self, req: &mut Request) {
            use hyper::header::ContentLength;

            let boundary = self.prepared.boundary();
            req.headers_mut().set_raw(
                "Content-Type",
                vec![
                    format!("multipart/form-data;boundary={bound}", bound = boundary).into_bytes(),
                ],
            );
            if let Some(len) = self.prepared.content_len() {
                req.headers_mut().set(ContentLength(len));
            }
        }

        pub fn set_body(&mut self, req: &mut Request) {
            use std::io::Read;

            let mut bytes = Vec::new();
            self.prepared.read_to_end(&mut bytes).unwrap();
            req.set_body(bytes);
        }
    }

}

impl<C: Connect> Connector for HyperConnector<C> {
    fn request(&self, token: &str, req: HttpRequest) -> TelegramFuture<HttpResponse> {
        let uri = result(Uri::from_str(&req.url.url(token))).map_err(From::from);

        let client = self.inner.clone();
        let request = uri.and_then(move |uri| {
            let method = match req.method {
                TelegramMethod::Get => Method::Get,
                TelegramMethod::Post => Method::Post,
            };
            let mut http_request = hyper::client::Request::new(method, uri);

            match req.body {
                TelegramBody::Empty => (),
                TelegramBody::Json(body) => {
                    http_request.set_body(body);
                    http_request.headers_mut().set(ContentType::json());
                }
                TelegramBody::Multipart(parts) => {
                    let mut adapter = multipart::Adapter::from(parts);
                    adapter.set_header(&mut http_request);
                    adapter.set_body(&mut http_request);
                }
                body => panic!("Unknown body type {:?}", body),
            }

            client.request(http_request).from_err()
        });

        let future = request.and_then(move |response| {
            response.body().map_err(From::from).fold(
                vec![],
                |mut result, chunk| -> Result<Vec<u8>, Error> {
                    result.extend_from_slice(&chunk);
                    Ok(result)
                },
            )
        });

        let future = future.and_then(|body| Ok(HttpResponse { body: Some(body) }));

        TelegramFuture::new(Box::new(future))
    }
}

/// Returns default hyper connector. Uses one resolve thread and `HttpsConnector`.
pub fn default_connector(handle: &Handle) -> Result<Box<Connector>, Error> {
    let connector = HttpsConnector::new(1, handle).map_err(|err| {
        ::std::io::Error::new(::std::io::ErrorKind::Other, format!("tls error: {}", err))
    })?;
    let config = Client::configure().connector(connector);
    Ok(Box::new(HyperConnector::new(config.build(handle))))
}
<|endoftext|>


<commit_before>use enums::Enum;

pub trait CoSuspend<Output> {
    type Yield;
    type Continuation: Coroutine<Output>;
    type Suspension: CoSuspend<Output>;
}

impl<Output> CoSuspend<Output> for ! {
    type Yield = !;
    type Continuation = !;
    type Suspension = !;
}

impl<Output, Enumeration, Y, C> CoSuspend<Output> for Enumeration
    where C: Coroutine<Output>,
          Enumeration: Enum<Variant = (Y, C)>,
          Enumeration::Next: CoSuspend<Output>
{
    type Yield = Y;
    type Continuation = C;
    type Suspension = Enumeration::Next;
}

pub enum CoResult<Suspend, Output>
    where Suspend: CoSuspend<Output>
{
    Suspend(Suspend),
    Return(Output),
}

pub trait Coroutine<Output>: Sized {
    type Input;
    type Suspend: CoSuspend<Output>;

    fn send(self, i: Self::Input) -> CoResult<Self::Suspend, Output>;
}

impl<Output> Coroutine<Output> for ! {
    type Input = !;
    type Suspend = !;

    fn send(self, _: Self::Input) -> CoResult<Self::Suspend, Output> {
        unreachable!()
    }
}

#[cfg(test)]
mod tests {

    #![macro_use]

    use super::{Coroutine, CoResult};
    use enums::Match::*;

    struct Guess(i64);

    impl Coroutine<&'static str> for Guess {
        type Input = i64;

        type Suspend = enums![(&'static str, Guess), (&'static str, Guess)];

        fn send(self, i: Self::Input) -> CoResult<Self::Suspend, &'static str> {
            if self.0 == i {
                CoResult::Return("You guessed it!")
            } else if i < self.0 {
                CoResult::Suspend(Variant(("Too small!", self)))
            } else {
                CoResult::Suspend(Next(Variant(("Too big!", self))))
            }
        }
    }

    fn play_guess(secret: i64) -> Guess {
        Guess(secret)
    }

    /*
    fn play_guess(secret: i64) {
        return move |guess: i64| {
            let mut guess = guess;
            loop {
                guess = if guess == secret {
                    return "You guessed it!";
                } else if guess < secret {
                    yield "Too small!";
                } else {
                    yield "Too big!";
                }
            }
        }
    */

    #[test]
    fn guess() {
        let game = play_guess(16);

        let suspend = match game.send(10) {
            CoResult::Suspend(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Variant((msg, guess_again)) => {
                assert_eq!(msg, "Too small!");
                guess_again
            }
            _ => panic!("The number was clearly too small! Why do you not see this?"),
        };

        let suspend = match game.send(19) {
            CoResult::Suspend(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Next(Variant((msg, guess_again))) => {
                assert_eq!(msg, "Too big!");
                guess_again
            }
            _ => panic!("The number was clearly too big! Why do you not see this?"),
        };

        match game.send(16) {
            CoResult::Return(msg) => assert_eq!(msg, "You guessed it!"),
            _ => panic!("The answer was correct! The coroutine should return."),
        }
    }
}
<commit_msg>Make `Output` an associated type<commit_after>use std::marker::PhantomData;
use enums::Enum;

pub trait CoSuspend {
    type Yield;
    type Output;
    type Continuation: Coroutine<Output = Self::Output>;
    type Suspension: CoSuspend<Output = Self::Output>;
}

pub struct NeverReach<Output>(PhantomData<Output>);

impl<T> Enum for NeverReach<T> {
    type Variant = !;
    type Next = !;
}

#[macro_export]
macro_rules! suspend {
    ($head:ty, $(($taily:ty, $tailc:ty)),+) => {
        $crate::enums::Match<$head, suspend![ $(($taily, $tailc)),* ]>
    };

    (($yields:ty, $continues:ty)) => {
        $crate::enums::Match<($yields, $continues), $crate::co::NeverReach<<$continues as $crate::co::Coroutine>::Output>>
    };
}

impl<T> CoSuspend for NeverReach<T> {
    type Yield = !;
    type Output = T;
    type Continuation = Self;
    type Suspension = Self;
}

impl<T> Coroutine for NeverReach<T> {
    type Input = !;
    type Output = T;
    type Suspend = Self;

    fn send(self, _: Self::Input) -> CoResult<Self::Suspend> {
        unreachable!()
    }
}

impl<Enumeration, Y, C> CoSuspend for Enumeration
    where C: Coroutine,
          Enumeration: Enum<Variant = (Y, C)>,
          Enumeration::Next: CoSuspend<Output = C::Output>
{
    type Yield = Y;
    type Output = C::Output;
    type Continuation = C;
    type Suspension = Enumeration::Next;
}

pub enum CoResult<Suspend>
    where Suspend: CoSuspend
{
    Suspend(Suspend),
    Return(Suspend::Output),
}

pub trait Coroutine: Sized {
    type Input;
    type Output;
    type Suspend: CoSuspend<Output = Self::Output>;

    fn send(self, i: Self::Input) -> CoResult<Self::Suspend>;
}

#[cfg(test)]
mod tests {

    #![macro_use]

    use super::{Coroutine, CoResult};
    use enums::Match::*;

    struct Guess(i64);

    impl Coroutine for Guess {
        type Input = i64;
        type Output = &'static str;

        type Suspend = suspend![(&'static str, Guess), (&'static str, Guess)];

        fn send(self, i: Self::Input) -> CoResult<Self::Suspend> {
            if self.0 == i {
                CoResult::Return("You guessed it!")
            } else if i < self.0 {
                CoResult::Suspend(Variant(("Too small!", self)))
            } else {
                CoResult::Suspend(Next(Variant(("Too big!", self))))
            }
        }
    }

    fn play_guess(secret: i64) -> Guess {
        Guess(secret)
    }

    /*
    fn play_guess(secret: i64) {
        return move |guess: i64| {
            let mut guess = guess;
            loop {
                guess = if guess == secret {
                    return "You guessed it!";
                } else if guess < secret {
                    yield "Too small!";
                } else {
                    yield "Too big!";
                }
            }
        }
    */

    #[test]
    fn guess() {
        let game = play_guess(16);

        let suspend = match game.send(10) {
            CoResult::Suspend(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Variant((msg, guess_again)) => {
                assert_eq!(msg, "Too small!");
                guess_again
            }
            _ => panic!("The number was clearly too small! Why do you not see this?"),
        };

        let suspend = match game.send(19) {
            CoResult::Suspend(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Next(Variant((msg, guess_again))) => {
                assert_eq!(msg, "Too big!");
                guess_again
            }
            _ => panic!("The number was clearly too big! Why do you not see this?"),
        };

        match game.send(16) {
            CoResult::Return(msg) => assert_eq!(msg, "You guessed it!"),
            _ => panic!("The answer was correct! The coroutine should return."),
        }
    }
}
<|endoftext|>


<commit_before>use super::common::Log;

use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::io::Write;
use std::time::Duration;

#[derive(Debug, Deserialize)]
pub struct SignedCertificateTimestamp {
    sct_version: u8,
    id: String,
    timestamp: u64,
    extensions: String,
    signature: String,
}

impl SignedCertificateTimestamp {
    pub fn to_raw_bytes(&self) -> Vec<u8> {
        let mut b = Vec::new();
        b.write_all(&[self.sct_version]).unwrap();

        let log_id = base64::decode(&self.id).unwrap();
        b.write_all(&log_id).unwrap();

        b.write_all(&self.timestamp.to_be_bytes()).unwrap();

        let extensions = base64::decode(&self.extensions).unwrap();
        b.write_all(&u16::try_from(extensions.len()).unwrap().to_be_bytes())
            .unwrap();
        b.write_all(&extensions).unwrap();

        let signature = base64::decode(&self.signature).unwrap();
        b.write_all(&signature).unwrap();

        b
    }
}

async fn submit_to_log(
    http_client: &reqwest::Client,
    log: &Log,
    payload: Vec<u8>,
) -> Result<SignedCertificateTimestamp, ()> {
    let mut url = "https://".to_string() + &log.url;
    if !url.ends_with('/') {
        url += "/";
    }
    url += "ct/v1/add-chain";

    let response = http_client
        .post(&url)
        .header("Content-Type", "application/json")
        .body(payload)
        .send()
        .await
        .map_err(|_| ())?;

    // 400, 403, and probably some others generally indicate a log doesn't accept certs from
    // this root, or that the log isn't accepting new submissions. Server errors mean there's
    // nothing we can do.
    if response.status().is_client_error() || response.status().is_server_error() {
        return Err(());
    }

    Ok(response.json().await.unwrap())
}

#[derive(Serialize, Deserialize)]
pub struct AddChainRequest {
    pub chain: Vec<String>,
}

pub async fn submit_cert_to_logs(
    http_client: &reqwest::Client,
    logs: &[Log],
    cert: &[Vec<u8>],
    timeout: Duration,
) -> Vec<(usize, SignedCertificateTimestamp)> {
    let payload = serde_json::to_vec(&AddChainRequest {
        chain: cert.iter().map(base64::encode).collect(),
    })
    .unwrap();

    let futures = logs
        .iter()
        .enumerate()
        .map(move |(idx, log)| {
            let s = tokio::time::timeout(timeout, submit_to_log(http_client, log, payload.clone()));
            async move {
                match s.await {
                    Ok(Ok(sct)) => Some((idx, sct)),
                    _ => None,
                }
            }
        })
        .collect::<Vec<_>>();

    let scts = futures::future::join_all(futures).await;
    scts.into_iter().filter_map(|s| s).collect()
}
<commit_msg>follow clippy's orders<commit_after>use super::common::Log;

use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::io::Write;
use std::time::Duration;

#[derive(Debug, Deserialize)]
pub struct SignedCertificateTimestamp {
    sct_version: u8,
    id: String,
    timestamp: u64,
    extensions: String,
    signature: String,
}

impl SignedCertificateTimestamp {
    pub fn to_raw_bytes(&self) -> Vec<u8> {
        let mut b = Vec::new();
        b.write_all(&[self.sct_version]).unwrap();

        let log_id = base64::decode(&self.id).unwrap();
        b.write_all(&log_id).unwrap();

        b.write_all(&self.timestamp.to_be_bytes()).unwrap();

        let extensions = base64::decode(&self.extensions).unwrap();
        b.write_all(&u16::try_from(extensions.len()).unwrap().to_be_bytes())
            .unwrap();
        b.write_all(&extensions).unwrap();

        let signature = base64::decode(&self.signature).unwrap();
        b.write_all(&signature).unwrap();

        b
    }
}

async fn submit_to_log(
    http_client: &reqwest::Client,
    log: &Log,
    payload: Vec<u8>,
) -> Result<SignedCertificateTimestamp, ()> {
    let mut url = "https://".to_string() + &log.url;
    if !url.ends_with('/') {
        url += "/";
    }
    url += "ct/v1/add-chain";

    let response = http_client
        .post(&url)
        .header("Content-Type", "application/json")
        .body(payload)
        .send()
        .await
        .map_err(|_| ())?;

    // 400, 403, and probably some others generally indicate a log doesn't accept certs from
    // this root, or that the log isn't accepting new submissions. Server errors mean there's
    // nothing we can do.
    if response.status().is_client_error() || response.status().is_server_error() {
        return Err(());
    }

    Ok(response.json().await.unwrap())
}

#[derive(Serialize, Deserialize)]
pub struct AddChainRequest {
    pub chain: Vec<String>,
}

pub async fn submit_cert_to_logs(
    http_client: &reqwest::Client,
    logs: &[Log],
    cert: &[Vec<u8>],
    timeout: Duration,
) -> Vec<(usize, SignedCertificateTimestamp)> {
    let payload = serde_json::to_vec(&AddChainRequest {
        chain: cert.iter().map(base64::encode).collect(),
    })
    .unwrap();

    let futures = logs
        .iter()
        .enumerate()
        .map(move |(idx, log)| {
            let s = tokio::time::timeout(timeout, submit_to_log(http_client, log, payload.clone()));
            async move {
                match s.await {
                    Ok(Ok(sct)) => Some((idx, sct)),
                    _ => None,
                }
            }
        })
        .collect::<Vec<_>>();

    let scts = futures::future::join_all(futures).await;
    scts.into_iter().flatten().collect()
}
<|endoftext|>


<commit_before>use consts::{OpCode, ZkError, ZkState};
use proto::{ByteBuf, ConnectRequest, ConnectResponse, ReadFrom, ReplyHeader, RequestHeader, WriteTo};
use watch::WatchMessage;
use zookeeper::{RawResponse, RawRequest};

use byteorder::{BigEndian, ByteOrder};
use bytes::{Buf, RingBuf};
use mio::{EventLoop, EventSet, Handler, PollOpt, Sender, Timeout, Token, TryRead, TryWrite};
use mio::tcp::TcpStream;
use time::PreciseTime;
use std::collections::VecDeque;
use std::io;
use std::io::Cursor;
use std::mem;
use std::net::SocketAddr;
use std::time::Duration;

const ZK: Token = Token(1);

lazy_static! {
    static ref PING: ByteBuf =
    RequestHeader{xid: -2, opcode: OpCode::Ping}.to_len_prefixed_buf().unwrap();
}

struct Hosts {
    addrs: Vec<SocketAddr>,
    index: usize
}

impl Hosts {
    fn new(addrs: Vec<SocketAddr>) -> Hosts {
        Hosts{addrs: addrs, index: 0}
    }

    fn next<'a>(&'a mut self) -> &'a SocketAddr {
        let addr = &self.addrs[self.index];
        if self.addrs.len() == self.index+1 {
            self.index = 0;
        } else {
            self.index += 1;
        }
        addr
    }
}

struct ZkHandler {
    sock: TcpStream,
    state: ZkState,
    hosts: Hosts,
    buffer: VecDeque<RawRequest>,
    inflight: VecDeque<RawRequest>,
    response: RingBuf,
    timeout: Option<Timeout>,
    timeout_ms: u64,
    watch_sender: Sender<WatchMessage>,
    conn_resp: ConnectResponse,
    zxid: i64,
    ping_sent: PreciseTime
}

impl ZkHandler {
    fn new(addrs: Vec<SocketAddr>, timeout_ms: u64, watch_sender: Sender<WatchMessage>) -> ZkHandler {
        ZkHandler{
            sock: unsafe{mem::dropped()},
            state: ZkState::NotConnected,
            hosts: Hosts::new(addrs),
            buffer: VecDeque::new(),
            inflight: VecDeque::new(),
            // TODO server reads max up to 1MB, otherwise drops the connection, size should be 1MB + tcp rcvBufsize
            response: RingBuf::new(1024 * 1024 * 2),
            timeout: None,
            timeout_ms: timeout_ms,
            watch_sender: watch_sender,
            conn_resp: ConnectResponse::initial(timeout_ms),
            zxid: 0,
            ping_sent: PreciseTime::now()
        }
    }

    fn register(&mut self, event_loop: &mut EventLoop<Self>, events: EventSet) {
        event_loop.register(&self.sock, ZK, events, PollOpt::edge() | PollOpt::oneshot())
        .ok().expect("Failed to register ZK handle");
    }

    fn reregister(&mut self, event_loop: &mut EventLoop<Self>, events: EventSet) {
        event_loop.reregister(&self.sock, ZK, events, PollOpt::edge() | PollOpt::oneshot())
        .ok().expect("Failed to reregister ZK handle");
    }

    fn handle_response(&mut self, event_loop: &mut EventLoop<Self>) {
        loop {
            if self.response.remaining() <= 4 {
                return
            }
            let len = BigEndian::read_i32(&self.response.bytes()[..4]) as usize;

            trace!("Response chunk len = {} buf len is {}", len, self.response.bytes().len());

            if self.response.remaining() - 4 < len {
                return
            } else {
                self.response.advance(4);
                {
                    self.handle_chunk(event_loop, len);
                }
                self.response.advance(len);
            }
        }
    }

    fn handle_chunk(&mut self, event_loop: &mut EventLoop<Self>, len: usize) {

        let mut data = Cursor::new(&self.response.bytes()[..len]);

        debug!("handle_response in {:?} state [{}]", self.state, data.bytes().len());

        if self.state != ZkState::NotConnected {
            let header = match ReplyHeader::read_from(&mut data) {
                Ok(header) => header,
                Err(e) => {
                    warn!("Failed to parse ReplyHeader {:?}", e);
                    self.inflight.pop_front();
                    return
                }
            };
            self.zxid = header.zxid;
            let response = RawResponse{header: header, data: Cursor::new(data.bytes().to_vec())}; // TODO COPY!
            match response.header.xid {
                -1 => {
                    debug!("handle_response Got a watch event!");
                    self.watch_sender.send(WatchMessage::Event(response)).unwrap();
                },
                -2 => {
                    debug!("Got ping response in {:?}", self.ping_sent.to(PreciseTime::now()));
                    self.inflight.pop_front();
                },
                _ => match self.inflight.pop_front() {
                    Some(request) => {
                        if request.opcode == OpCode::CloseSession {
                            self.state = ZkState::Closed;
                            event_loop.shutdown();
                        }
                        self.send_response(request, response);
                    },
                    None => panic!("Shouldn't happen, no inflight request")
                }
            }
        } else {
            self.inflight.pop_front(); // drop the connect request
            self.conn_resp = match ConnectResponse::read_from(&mut data) {
                Ok(conn_resp) => conn_resp,
                Err(e) => {
                    panic!("Failed to parse ConnectResponse {:?}", e);
                    //self.reconnect(event_loop);
                    //return
                }
            };
            info!("Connected: {:?}", self.conn_resp);
            self.timeout_ms = self.conn_resp.timeout / 3 * 2;
            self.state = if self.conn_resp.read_only {
                ZkState::ConnectedReadOnly } else {
                ZkState::Connected };
        }
    }

    fn send_response(&self, request: RawRequest, response: RawResponse) {
        match request.listener {
            Some(ref listener) => {
                debug!("send_response Opcode is {:?}", request.opcode);
                listener.send(response).unwrap();
            },
            None => debug!("Nobody is interested in respone {:?}", request.opcode)
        }
        if let Some(watch) = request.watch {
            self.watch_sender.send(WatchMessage::Watch(watch)).unwrap();
        }
    }

    fn clear_ping_timeout(&mut self, event_loop: &mut EventLoop<Self>) {
        if let Some(timeout) = self.timeout {
            event_loop.clear_timeout(timeout);
        }
    }

    fn reconnect(&mut self, event_loop: &mut EventLoop<Self>) {
        self.state = ZkState::Connecting;
        // TODO only until session times out
        loop {
            self.buffer.clear();
            self.inflight.clear();
            self.response.mark(); self.response.reset(); // TODO drop all read bytes once RingBuf.clear() is merged

            self.clear_ping_timeout(event_loop);

            {
                let host = self.hosts.next();
                info!("Connecting to new server {:?}", host);
                self.sock = match TcpStream::connect(host) {
                    Ok(sock) => sock,
                    Err(e) => {
                        warn!("Failed to connect {:?}: {:?}", host, e);
                        continue
                    }
                };
                info!("Connected to {:?}", host);
            }

            let request = self.connect_request();
            self.buffer.push_back(request);

            self.register(event_loop, EventSet::all());

            break
        }
    }

    fn connect_request(&self) -> RawRequest {
        let conn_req = ConnectRequest::from(&self.conn_resp, self.zxid);
        let buf = conn_req.to_len_prefixed_buf().unwrap();
        RawRequest{opcode: OpCode::Auth, data: buf, listener: None, watch: None}
    }
}

impl Handler for ZkHandler {
    type Message = RawRequest;
    type Timeout = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {

        trace!("ready {:?} {:?}", token, events);
        if events.is_writable() {
            loop {
                match self.buffer.pop_front() {
                    Some(mut request) => match self.sock.try_write_buf(&mut request.data) {
                        Ok(Some(written)) if written > 0 => {
                            trace!("Written {:?} bytes", written);
                            if request.data.has_remaining() {
                                self.buffer.push_front(request);
                                break
                            } else {
                                self.inflight.push_back(request);

                                // Sent a full message, clear the ping timeout
                                self.clear_ping_timeout(event_loop);
                            }
                        },
                        Ok(None) => trace!("Spurious write"),
                        Ok(Some(_)) => warn!("Connection closed: write"),
                        Err(e) => {
                            error!("Failed to write socket: {:?}", e);
                            self.reconnect(event_loop);
                        }
                    },
                    None => break
                }
            }
            self.timeout = Some(event_loop.timeout_ms((), self.timeout_ms).unwrap());
        }
        if events.is_readable() {
            match self.sock.try_read_buf(&mut self.response) {
                Ok(Some(read)) if read > 0 => {
                    trace!("Read {:?} bytes", read);
                    self.handle_response(event_loop);
                },
                Ok(None) => trace!("Spurious read"),
                Ok(Some(_)) => warn!("Connection closed: read"),
                Err(e) => {
                    error!("Failed to read socket: {:?}", e);
                    self.reconnect(event_loop);
                }
            }
        }
        if events.is_hup() {
            if self.state != ZkState::Closed {
                // If we were connected
                // fn send_watched_event(keeper_state: KeeperState) {
                //     match sender.send(WatchedEvent{event_type: WatchedEventType::None,
                //                                    keeper_state: keeper_state,
                //                                    path: None}) {
                //         Ok(()) => (),
                //         Err(e) => panic!("Reader/Writer: Event died {}", e)
                //     }
                // }
                self.state = ZkState::NotConnected;
                self.reconnect(event_loop);
            }
        }

        // Not sure that we need to write, but we always need to read, because of watches
        // If the output buffer has no content, we don't need to write again
        let mut event_set = EventSet::all();
        if self.buffer.is_empty() {
            event_set.remove(EventSet::writable());
        }

        // This tick is done, subscribe to a forthcoming one
        self.reregister(event_loop, event_set);
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, request: Self::Message) {
        trace!("notify {:?}", request.opcode);
        if self.state != ZkState::Closed {
            if self.buffer.is_empty() {
                self.reregister(event_loop, EventSet::all());
            }
            self.buffer.push_back(request);
        } else {
            let header = ReplyHeader{xid: 0, zxid: 0, err: ZkError::ConnectionLoss as i32};
            let response = RawResponse{header: header, data: ByteBuf::new(vec![])};
            self.send_response(request, response);
        }
    }

    fn timeout(&mut self, event_loop: &mut EventLoop<Self>, _: Self::Timeout) {
        debug!("Pinging {:?}", self.sock.peer_addr().unwrap());
        let ping = RawRequest{
            opcode: OpCode::Ping,
            data: PING.clone(),
            listener: None,
            watch: None
        };
        event_loop.channel().send(ping).unwrap();
        self.ping_sent = PreciseTime::now();
    }
}

pub struct ZkIo {
    event_loop: EventLoop<ZkHandler>,
    handler: ZkHandler,
}

impl ZkIo {
    pub fn new(addrs: Vec<SocketAddr>, timeout: Duration, event_sender: Sender<WatchMessage>) -> ZkIo {
        let event_loop = EventLoop::new().unwrap();
        let timeout_ms = timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1000000;
        let handler = ZkHandler::new(addrs, timeout_ms, event_sender);
        ZkIo{event_loop: event_loop, handler: handler}
    }

    pub fn sender(&self) -> Sender<RawRequest> {
        self.event_loop.channel()
    }

    pub fn run(mut self) -> io::Result<()> {
        self.handler.reconnect(&mut self.event_loop);
        self.event_loop.run(&mut self.handler)
    }
}
<commit_msg>transition to connected state. experimental.<commit_after>use consts::{OpCode, ZkError, ZkState};
use proto::{ByteBuf, ConnectRequest, ConnectResponse, ReadFrom, ReplyHeader, RequestHeader, WriteTo};
use watch::WatchMessage;
use zookeeper::{RawResponse, RawRequest};

use byteorder::{BigEndian, ByteOrder};
use bytes::{Buf, RingBuf};
use mio::{EventLoop, EventSet, Handler, PollOpt, Sender, Timeout, Token, TryRead, TryWrite};
use mio::tcp::TcpStream;
use time::PreciseTime;
use std::collections::VecDeque;
use std::io;
use std::io::Cursor;
use std::mem;
use std::net::SocketAddr;
use std::time::Duration;

const ZK: Token = Token(1);

lazy_static! {
    static ref PING: ByteBuf =
    RequestHeader{xid: -2, opcode: OpCode::Ping}.to_len_prefixed_buf().unwrap();
}

struct Hosts {
    addrs: Vec<SocketAddr>,
    index: usize
}

impl Hosts {
    fn new(addrs: Vec<SocketAddr>) -> Hosts {
        Hosts{addrs: addrs, index: 0}
    }

    fn next<'a>(&'a mut self) -> &'a SocketAddr {
        let addr = &self.addrs[self.index];
        if self.addrs.len() == self.index+1 {
            self.index = 0;
        } else {
            self.index += 1;
        }
        addr
    }
}

struct ZkHandler {
    sock: TcpStream,
    state: ZkState,
    hosts: Hosts,
    buffer: VecDeque<RawRequest>,
    inflight: VecDeque<RawRequest>,
    response: RingBuf,
    timeout: Option<Timeout>,
    timeout_ms: u64,
    watch_sender: Sender<WatchMessage>,
    conn_resp: ConnectResponse,
    zxid: i64,
    ping_sent: PreciseTime
}

impl ZkHandler {
    fn new(addrs: Vec<SocketAddr>, timeout_ms: u64, watch_sender: Sender<WatchMessage>) -> ZkHandler {
        ZkHandler{
            sock: unsafe{mem::dropped()},
            state: ZkState::NotConnected,
            hosts: Hosts::new(addrs),
            buffer: VecDeque::new(),
            inflight: VecDeque::new(),
            // TODO server reads max up to 1MB, otherwise drops the connection, size should be 1MB + tcp rcvBufsize
            response: RingBuf::new(1024 * 1024 * 2),
            timeout: None,
            timeout_ms: timeout_ms,
            watch_sender: watch_sender,
            conn_resp: ConnectResponse::initial(timeout_ms),
            zxid: 0,
            ping_sent: PreciseTime::now()
        }
    }

    fn register(&mut self, event_loop: &mut EventLoop<Self>, events: EventSet) {
        event_loop.register(&self.sock, ZK, events, PollOpt::edge() | PollOpt::oneshot())
        .ok().expect("Failed to register ZK handle");
    }

    fn reregister(&mut self, event_loop: &mut EventLoop<Self>, events: EventSet) {
        event_loop.reregister(&self.sock, ZK, events, PollOpt::edge() | PollOpt::oneshot())
        .ok().expect("Failed to reregister ZK handle");
    }

    fn handle_response(&mut self, event_loop: &mut EventLoop<Self>) {
        loop {
            if self.response.remaining() <= 4 {
                return
            }
            let len = BigEndian::read_i32(&self.response.bytes()[..4]) as usize;

            trace!("Response chunk len = {} buf len is {}", len, self.response.bytes().len());

            if self.response.remaining() - 4 < len {
                return
            } else {
                self.response.advance(4);
                {
                    self.handle_chunk(event_loop, len);
                }
                self.response.advance(len);
            }
        }
    }

    fn handle_chunk(&mut self, event_loop: &mut EventLoop<Self>, len: usize) {

        let mut data = Cursor::new(&self.response.bytes()[..len]);

        debug!("handle_response in {:?} state [{}]", self.state, data.bytes().len());

        if self.state != ZkState::Connecting {
            let header = match ReplyHeader::read_from(&mut data) {
                Ok(header) => header,
                Err(e) => {
                    warn!("Failed to parse ReplyHeader {:?}", e);
                    self.inflight.pop_front();
                    return
                }
            };
            self.zxid = header.zxid;
            let response = RawResponse{header: header, data: Cursor::new(data.bytes().to_vec())}; // TODO COPY!
            match response.header.xid {
                -1 => {
                    debug!("handle_response Got a watch event!");
                    self.watch_sender.send(WatchMessage::Event(response)).unwrap();
                },
                -2 => {
                    debug!("Got ping response in {:?}", self.ping_sent.to(PreciseTime::now()));
                    self.inflight.pop_front();
                },
                _ => match self.inflight.pop_front() {
                    Some(request) => {
                        if request.opcode == OpCode::CloseSession {
                            self.state = ZkState::Closed;
                            event_loop.shutdown();
                        }
                        self.send_response(request, response);
                    },
                    None => panic!("Shouldn't happen, no inflight request")
                }
            }
        } else {
            self.inflight.pop_front(); // drop the connect request
            self.conn_resp = match ConnectResponse::read_from(&mut data) {
                Ok(conn_resp) => conn_resp,
                Err(e) => {
                    panic!("Failed to parse ConnectResponse {:?}", e);
                    //self.reconnect(event_loop);
                    //return
                }
            };
            info!("Connected: {:?}", self.conn_resp);
            self.timeout_ms = self.conn_resp.timeout / 3 * 2;
            self.state = if self.conn_resp.read_only {
                ZkState::ConnectedReadOnly } else {
                ZkState::Connected };
        }
    }

    fn send_response(&self, request: RawRequest, response: RawResponse) {
        match request.listener {
            Some(ref listener) => {
                debug!("send_response Opcode is {:?}", request.opcode);
                listener.send(response).unwrap();
            },
            None => debug!("Nobody is interested in respone {:?}", request.opcode)
        }
        if let Some(watch) = request.watch {
            self.watch_sender.send(WatchMessage::Watch(watch)).unwrap();
        }
    }

    fn clear_ping_timeout(&mut self, event_loop: &mut EventLoop<Self>) {
        if let Some(timeout) = self.timeout {
            event_loop.clear_timeout(timeout);
        }
    }

    fn reconnect(&mut self, event_loop: &mut EventLoop<Self>) {
        self.state = ZkState::Connecting;
        // TODO only until session times out
        loop {
            self.buffer.clear();
            self.inflight.clear();
            self.response.mark(); self.response.reset(); // TODO drop all read bytes once RingBuf.clear() is merged

            self.clear_ping_timeout(event_loop);

            {
                let host = self.hosts.next();
                info!("Connecting to new server {:?}", host);
                self.sock = match TcpStream::connect(host) {
                    Ok(sock) => sock,
                    Err(e) => {
                        warn!("Failed to connect {:?}: {:?}", host, e);
                        continue
                    }
                };
                info!("Connected to {:?}", host);
            }

            let request = self.connect_request();
            self.buffer.push_back(request);

            self.register(event_loop, EventSet::all());

            break
        }
    }

    fn connect_request(&self) -> RawRequest {
        let conn_req = ConnectRequest::from(&self.conn_resp, self.zxid);
        let buf = conn_req.to_len_prefixed_buf().unwrap();
        RawRequest{opcode: OpCode::Auth, data: buf, listener: None, watch: None}
    }
}

impl Handler for ZkHandler {
    type Message = RawRequest;
    type Timeout = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {

        trace!("ready {:?} {:?}", token, events);
        if events.is_writable() {
            loop {
                match self.buffer.pop_front() {
                    Some(mut request) => match self.sock.try_write_buf(&mut request.data) {
                        Ok(Some(written)) if written > 0 => {
                            trace!("Written {:?} bytes", written);
                            if request.data.has_remaining() {
                                self.buffer.push_front(request);
                                break
                            } else {
                                self.inflight.push_back(request);

                                // Sent a full message, clear the ping timeout
                                self.clear_ping_timeout(event_loop);
                            }
                        },
                        Ok(None) => trace!("Spurious write"),
                        Ok(Some(_)) => warn!("Connection closed: write"),
                        Err(e) => {
                            error!("Failed to write socket: {:?}", e);
                            self.reconnect(event_loop);
                        }
                    },
                    None => break
                }
            }
            self.timeout = Some(event_loop.timeout_ms((), self.timeout_ms).unwrap());
        }
        if events.is_readable() {
            match self.sock.try_read_buf(&mut self.response) {
                Ok(Some(read)) if read > 0 => {
                    trace!("Read {:?} bytes", read);
                    self.handle_response(event_loop);
                },
                Ok(None) => trace!("Spurious read"),
                Ok(Some(_)) => warn!("Connection closed: read"),
                Err(e) => {
                    error!("Failed to read socket: {:?}", e);
                    self.reconnect(event_loop);
                }
            }
        }
        if events.is_hup() {
            if self.state != ZkState::Closed {
                // If we were connected
                // fn send_watched_event(keeper_state: KeeperState) {
                //     match sender.send(WatchedEvent{event_type: WatchedEventType::None,
                //                                    keeper_state: keeper_state,
                //                                    path: None}) {
                //         Ok(()) => (),
                //         Err(e) => panic!("Reader/Writer: Event died {}", e)
                //     }
                // }
                self.state = ZkState::NotConnected;
                self.reconnect(event_loop);
            }
        }

        // Not sure that we need to write, but we always need to read, because of watches
        // If the output buffer has no content, we don't need to write again
        let mut event_set = EventSet::all();
        if self.buffer.is_empty() {
            event_set.remove(EventSet::writable());
        }

        // This tick is done, subscribe to a forthcoming one
        self.reregister(event_loop, event_set);
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Self>, request: Self::Message) {
        trace!("notify {:?}", request.opcode);
        if self.state != ZkState::Closed {
            if self.buffer.is_empty() {
                self.reregister(event_loop, EventSet::all());
            }
            self.buffer.push_back(request);
        } else {
            let header = ReplyHeader{xid: 0, zxid: 0, err: ZkError::ConnectionLoss as i32};
            let response = RawResponse{header: header, data: ByteBuf::new(vec![])};
            self.send_response(request, response);
        }
    }

    fn timeout(&mut self, event_loop: &mut EventLoop<Self>, _: Self::Timeout) {
        debug!("Pinging {:?}", self.sock.peer_addr().unwrap());
        let ping = RawRequest{
            opcode: OpCode::Ping,
            data: PING.clone(),
            listener: None,
            watch: None
        };
        event_loop.channel().send(ping).unwrap();
        self.ping_sent = PreciseTime::now();
    }
}

pub struct ZkIo {
    event_loop: EventLoop<ZkHandler>,
    handler: ZkHandler,
}

impl ZkIo {
    pub fn new(addrs: Vec<SocketAddr>, timeout: Duration, event_sender: Sender<WatchMessage>) -> ZkIo {
        let event_loop = EventLoop::new().unwrap();
        let timeout_ms = timeout.as_secs() * 1000 + timeout.subsec_nanos() as u64 / 1000000;
        let handler = ZkHandler::new(addrs, timeout_ms, event_sender);
        ZkIo{event_loop: event_loop, handler: handler}
    }

    pub fn sender(&self) -> Sender<RawRequest> {
        self.event_loop.channel()
    }

    pub fn run(mut self) -> io::Result<()> {
        self.handler.reconnect(&mut self.event_loop);
        self.event_loop.run(&mut self.handler)
    }
}
<|endoftext|>


<commit_before>use std::io::{Result, Read, Write};

use super::{ConduitM, produce, consume, defer, Flush};

fn read<R: Read>(r: &mut R, z: usize) -> Result<Vec<u8>> {
    let mut v = Vec::with_capacity(z);
    unsafe { v.set_len(z); }
    match r.read(&mut v) {
        Err(e) => Err(e),
        Ok(n) => {
            unsafe { v.set_len(n); }
            Ok(v)
        }
    }
}

/// A conduit that produces bytes it reads from the given `Read`.
pub fn reader<'a, R: 'a + Read>(mut r: R, z: usize) -> ConduitM<'a, (), Vec<u8>, Result<()>> {
    defer().and_then(move |_| {
        match read(&mut r, z) {
            Err(e) => Err(e).into(),
            Ok(v) => {
                if v.len() == 0 {
                    Ok(()).into()
                } else {
                    produce(v).and_then(move |_| reader(r, z))
                }
            }
        }
    })
}

/// A conduit that consumes bytes and writes them to the given `Write`.
pub fn writer<'a, W: 'a + Write>(mut w: W) -> ConduitM<'a, Vec<u8>, (), Result<()>> {
    consume().and_then(|vo: Option<Vec<u8>>| {
        match vo {
            None => Ok(()).into(),
            Some(v) => match w.write_all(&v) {
                Err(e) => Err(e).into(),
                Ok(_) => writer(w)
            }
        }
    })
}

fn write_flush<W: Write>(w: &mut W, f: Flush<Vec<u8>>) -> Result<()> {
    match f {
        Flush::Chunk(v) => w.write_all(&v),
        Flush::Flush => w.flush()
    }
}

/// A conduit that consumes bytes and writes them to the given `Write`,
/// while also providing flushing capabilities.
pub fn writer_flush<'a, W: 'a + Write>(mut w: W) -> ConduitM<'a, Flush<Vec<u8>>, (), Result<()>> {
    consume().and_then(|fo| {
        match fo {
            None => Ok(()).into(),
            Some(f) => match write_flush(&mut w, f) {
                Err(e) => Err(e).into(),
                Ok(_) => writer_flush(w)
            }
        }
    })
}
<commit_msg>add mpsc sinks/sources<commit_after>use std::io;
use std::io::{Read, Write};
use std::sync::mpsc::{Receiver, RecvError, Sender, SyncSender, SendError};

use super::{ConduitM, produce, consume, defer, leftover, Flush};

fn read<R: Read>(r: &mut R, z: usize) -> io::Result<Vec<u8>> {
    let mut v = Vec::with_capacity(z);
    unsafe { v.set_len(z); }
    match r.read(&mut v) {
        Err(e) => Err(e),
        Ok(n) => {
            unsafe { v.set_len(n); }
            Ok(v)
        }
    }
}

/// A conduit that produces bytes it reads from the given `Read`.
pub fn reader<'a, R: 'a + Read>(mut r: R, z: usize) -> ConduitM<'a, (), Vec<u8>, io::Result<()>> {
    defer().and_then(move |_| {
        match read(&mut r, z) {
            Err(e) => Err(e).into(),
            Ok(v) => {
                if v.len() == 0 {
                    Ok(()).into()
                } else {
                    produce(v).and_then(move |_| reader(r, z))
                }
            }
        }
    })
}

/// A conduit that consumes bytes and writes them to the given `Write`.
pub fn writer<'a, W: 'a + Write>(mut w: W) -> ConduitM<'a, Vec<u8>, (), io::Result<()>> {
    consume().and_then(|vo: Option<Vec<u8>>| {
        match vo {
            None => Ok(()).into(),
            Some(v) => match w.write_all(&v) {
                Err(e) => Err(e).into(),
                Ok(_) => writer(w)
            }
        }
    })
}

fn write_flush<W: Write>(w: &mut W, f: Flush<Vec<u8>>) -> io::Result<()> {
    match f {
        Flush::Chunk(v) => w.write_all(&v),
        Flush::Flush => w.flush()
    }
}

/// A conduit that consumes bytes and writes them to the given `Write`,
/// while also providing flushing capabilities.
pub fn writer_flush<'a, W: 'a + Write>(mut w: W) -> ConduitM<'a, Flush<Vec<u8>>, (), io::Result<()>> {
    consume().and_then(|fo| {
        match fo {
            None => Ok(()).into(),
            Some(f) => match write_flush(&mut w, f) {
                Err(e) => Err(e).into(),
                Ok(_) => writer_flush(w)
            }
        }
    })
}

pub fn receiver<'a, T: 'a>(r: Receiver<T>) -> ConduitM<'a, (), T, ()> {
    defer().and_then(|_| {
        match r.recv() {
            Err(RecvError) => ().into(),
            Ok(x) => produce(x).and(receiver(r))
        }
    })
}

pub fn sender<'a, T: 'a>(s: Sender<T>) -> ConduitM<'a, T, (), ()> {
    consume().and_then(|xo| {
        match xo {
            None => ().into(),
            Some(x) => match s.send(x) {
                Err(SendError(x)) => leftover(x),
                Ok(_) => sender(s)
            }
        }
    })
}

pub fn sync_sender<'a, T: 'a>(s: SyncSender<T>) -> ConduitM<'a, T, (), ()> {
    consume().and_then(|xo| {
        match xo {
            None => ().into(),
            Some(x) => match s.send(x) {
                Err(SendError(x)) => leftover(x),
                Ok(_) => sync_sender(s)
            }
        }
    })
}
<|endoftext|>