<commit_before>use mqtt::ffiasync;

use libc::{c_char, c_int, c_void};
use std::ffi::{CStr, CString};
use std::mem;
use std::ptr;
use std::slice;
use std::sync::Barrier;

pub enum PersistenceType {
    Default = 0,
    Nothing = 1,
    User    = 2,
}

#[derive(Debug)]
pub enum ConnectReturnCode {
    Success               = 0,
    UnacceptableProtocol  = 1,
    IdentifierRejected    = 2,
    ServerUnavailable     = 3,
    BadUsernameOrPassword = 4,
    NotAuthorized         = 5,
    Reserved              = 6,
}

#[derive(Debug)]
pub enum ConnectErr {
    ReturnCode(ConnectReturnCode),
    Callback
}

#[derive(Debug, Copy, Clone)]
pub enum MqttError {
    Code(i32),
    Bad
}

#[derive(Debug)]
pub enum Qos {
    FireAndForget  = 0,
    AtLeastOnce    = 1,
    OnceAndOneOnly = 2,
}

#[derive(Debug, Copy, Clone)]
pub enum ActionResult {
    None,
    Ok,
    Err(MqttError)
}

pub struct AsyncClient {
    handle        : ffiasync::MQTTAsync,
    pub random    : i32,
    barrier       : Barrier,
    action_result : ActionResult
}
impl AsyncClient {

    /// Ensures the FFI struct is consistent for callback invocation.
    ///
    /// Because the user may move this struct, the `context` pointer
    /// passed back to FFI callbacks might be invalidated. This function
    /// should be called before FFI actions that might fire callbacks to ensure
    /// the self-pointer is valid.
    fn context(&mut self) -> *mut c_void {
        self as *mut _ as *mut c_void
    }

    pub fn new(address: &str, clientid: &str, persistence: PersistenceType) -> Result<AsyncClient, MqttError> {
        let mut handle                      = unsafe{mem::zeroed()};
        let mut persistence_context: c_void = unsafe{mem::zeroed()};

        let c_url          = CString::new(address).unwrap();
        let c_clientid     = CString::new(clientid).unwrap();
        let array_url      = c_url.as_bytes_with_nul();
        let array_clientid = c_clientid.as_bytes_with_nul();

        let mut error = unsafe {
            ffiasync::MQTTAsync_create(&mut handle,
                                       mem::transmute::<&u8, *const c_char>(&array_url[0]),
                                       mem::transmute::<&u8, *const c_char>(&array_clientid[0]),
                                       persistence as i32,
                                       &mut persistence_context)
        };

        match error {
            0   => { Ok( AsyncClient {
                        handle          : handle,
                        random          : 33,
                        barrier         : Barrier::new(2),
                        action_result   : ActionResult::None
                    })},
            err => Err(MqttError::Code(err))
        }
    }

    pub fn connect(&mut self, options: &mut AsyncConnectOptions) -> Result<(), ConnectErr> {
        unsafe {
            ffiasync::MQTTAsync_setCallbacks(self.handle,
                                             self.context(),
                                             Some(Self::disconnected),
                                             Some(Self::received),
                                             None);
        }

        // fill in FFI private struct
        options.options.keepAliveInterval = options.keep_alive_interval;
        options.options.cleansession      = options.cleansession;
        options.options.maxInflight       = options.max_in_flight;
        options.options.connectTimeout    = options.connect_timeout;
        options.options.retryInterval     = options.retry_interval;

        // register callbacks
        options.options.context   = self.context();
        options.options.onSuccess = Some(Self::connect_succeeded);
        options.options.onFailure = Some(Self::connect_failed);

        self.action_result = ActionResult::None;
        let mut error = unsafe {
            ffiasync::MQTTAsync_connect(self.handle, &options.options)
        };
        if error == 0 {
            self.barrier.wait();
            if self.is_connected() {
                Ok(())
            } else {
                Err(ConnectErr::Callback)
            }
        } else {
            Err(ConnectErr::ReturnCode(
                match error {
                    1 => ConnectReturnCode::UnacceptableProtocol,
                    2 => ConnectReturnCode::IdentifierRejected,
                    3 => ConnectReturnCode::ServerUnavailable,
                    4 => ConnectReturnCode::BadUsernameOrPassword,
                    5 => ConnectReturnCode::NotAuthorized,
                    _ => ConnectReturnCode::Reserved,
            }))
        }
    }

    extern "C" fn connect_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        println!("connect succeeded");
        assert!(!context.is_null());

        let selfclient: &mut AsyncClient = unsafe {mem::transmute(context)};
        selfclient.action_result = ActionResult::Ok;
        selfclient.barrier.wait();
        selfclient.random = 69;
    }

    extern "C" fn connect_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        println!("connect failed");
        assert!(!context.is_null());
        let selfclient : &mut AsyncClient = unsafe {mem::transmute(context)};
        if response.is_null() {
            selfclient.action_result = ActionResult::Err(MqttError::Bad);
        } else {
            let resp : &mut ffiasync::MQTTAsync_failureData = unsafe {mem::transmute(response)};
            selfclient.action_result = ActionResult::Err(MqttError::Code(resp.code));
        }
        selfclient.barrier.wait();
    }

    extern "C" fn disconnected(context: *mut c_void, cause: *mut c_char) -> () {
        println!("disconnected");
        assert!(!context.is_null());
    }

    pub fn is_connected(&mut self) -> bool {
        let mut ret = unsafe {
            ffiasync::MQTTAsync_isConnected(self.handle)
        };

        match ret {
            1 => true,
            _ => false,
        }
    }

    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError>{
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::send_succeeded),
            onFailure       : Some(Self::send_failed),
            context         : self.context(),
            token           : 0,
        };

        let mut message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : data.len() as i32,
            payload         : unsafe {mem::transmute::<&u8, *mut c_void>(&data[0])},
            qos             : qos as c_int,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        let c_topic        = CString::new(topic).unwrap();
        let array_topic    = c_topic.as_bytes_with_nul();
        self.action_result = ActionResult::None;

        let mut error = unsafe {
            ffiasync::MQTTAsync_sendMessage(self.handle,
                                            mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                            &mut message,
                                            &mut responseoption)
        };
        if error == 0 {
            self.barrier.wait();
            match self.action_result {
                ActionResult::None   => unreachable!(),
                ActionResult::Ok     => Ok(()),
                ActionResult::Err(x) => Err(x)
            }
        } else { Err(MqttError::Code(error)) }
    }

    extern "C" fn send_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        println!("send succeeded");
        assert!(!context.is_null());
        let selfclient: &mut AsyncClient = unsafe {mem::transmute(context)};
        selfclient.action_result = ActionResult::Ok;
        selfclient.barrier.wait();
    }

    extern "C" fn send_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        println!("send failed");
        assert!(!context.is_null());
        let selfclient : &mut AsyncClient                     = unsafe {mem::transmute(context)};
        if response.is_null() {
            selfclient.action_result = ActionResult::Err(MqttError::Bad);
        } else {
            let resp : &mut ffiasync::MQTTAsync_failureData = unsafe {mem::transmute(response)};
            selfclient.action_result = ActionResult::Err(MqttError::Code(resp.code));
        }
        selfclient.barrier.wait();
    }

    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::subscribe_succeeded),
            onFailure       : Some(Self::subscribe_failed),
            context         : self.context(),
            token           : 0,
        };

        let c_topic     = CString::new(topic).unwrap();
        let array_topic = c_topic.as_bytes_with_nul();

        let c_qos: i32 = match qos {
            Qos::FireAndForget  => 0,
            Qos::AtLeastOnce    => 1,
            Qos::OnceAndOneOnly => 2,
        };

        let mut error = unsafe {
            ffiasync::MQTTAsync_subscribe(self.handle,
                                          mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                          c_qos,
                                          &mut responseoption)
        };

        match error {
            0   => Ok(()),
            err => Err(MqttError::Code(err)),
        }
    }

    extern "C" fn subscribe_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        println!("subscribe succeeded");
        assert!(!context.is_null());
    }

    extern "C" fn subscribe_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        println!("subscribe failed");
        assert!(!context.is_null());
    }

    extern "C" fn received(context: *mut ::libc::c_void, topic_name: *mut ::libc::c_char, topic_len: ::libc::c_int, amessage: *mut ffiasync::MQTTAsync_message) -> i32 {
        let c_topic = unsafe {CStr::from_ptr(topic_name).to_bytes()};
        let topic   = String::from_utf8(c_topic.to_vec()).unwrap();
        assert_eq!(topic.len(), topic_len as usize);

        assert!(!amessage.is_null());
        let transmessage: &mut ffiasync::MQTTAsync_message = unsafe {mem::transmute(amessage)};
        let message: &[u8] = unsafe {
                slice::from_raw_parts(transmessage.payload as *mut u8, transmessage.payloadlen as usize)
        };

        let strmessage = String::from_utf8(message.to_vec()).unwrap();
        println!("received from topic: {}", topic);
        println!("       utf8 message: {}", strmessage);
        println!("        raw message: {:?}", message);

        let mut msg = amessage;
        unsafe{ffiasync::MQTTAsync_freeMessage(&mut msg)};
        unsafe{ffiasync::MQTTAsync_free(mem::transmute(topic_name))};

        1
    }
}

impl Drop for AsyncClient {
    fn drop(&mut self) {
        unsafe{ffiasync::MQTTAsync_destroy(&mut self.handle)};
    }
}

pub struct AsyncConnectOptions {
    options: ffiasync::MQTTAsync_connectOptions,

    pub keep_alive_interval : i32,
    pub cleansession        : i32,
    pub max_in_flight       : i32,
    pub connect_timeout     : i32,
    pub retry_interval      : i32,
}

impl AsyncConnectOptions {

    pub fn new() -> AsyncConnectOptions {
        let ffioptions = ffiasync::MQTTAsync_connectOptions {
            struct_id           : ['M' as i8, 'Q' as i8, 'T' as i8, 'C' as i8],
            struct_version      : 3,
            keepAliveInterval   : 60,
            cleansession        : 1,
            maxInflight         : 10,
            will                : ptr::null_mut(),
            username            : ptr::null_mut(),
            password            : ptr::null_mut(),
            connectTimeout      : 30,
            retryInterval       : 0,
            ssl                 : ptr::null_mut(),
            onSuccess           : None,
            onFailure           : None,
            context             : ptr::null_mut(),
            serverURIcount      : 0,
            serverURIs          : ptr::null_mut(),
            MQTTVersion         : 0,
        };

        let options = AsyncConnectOptions {
            options             : ffioptions,

            keep_alive_interval : 20,
            cleansession        : 1,
            max_in_flight       : 10,
            connect_timeout     : 30,
            retry_interval      : 0,
        };

        options
    }
}

pub struct AsyncDisconnectOptions {
    options: ffiasync::MQTTAsync_disconnectOptions,
}

impl AsyncDisconnectOptions {

    pub fn new() -> ffiasync::MQTTAsync_disconnectOptions {
        let options = ffiasync::MQTTAsync_disconnectOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'D' as i8],
            struct_version  : 0,
            timeout         : 0,
            onSuccess       : ptr::null_mut(),
            onFailure       : ptr::null_mut(),
            context         : ptr::null_mut(),
        };

        options
    }
}

pub struct AsyncMessage {
    options: ffiasync::MQTTAsync_message,
}

impl AsyncMessage {

    pub fn new() -> ffiasync::MQTTAsync_message {
        let message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : 0,
            payload         : ptr::null_mut(),
            qos             : 0,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        message
    }
}
<commit_msg>synchronous subscribe<commit_after>use mqtt::ffiasync;

use libc::{c_char, c_int, c_void};
use std::ffi::{CStr, CString};
use std::mem;
use std::ptr;
use std::slice;
use std::sync::Barrier;

pub enum PersistenceType {
    Default = 0,
    Nothing = 1,
    User    = 2,
}

#[derive(Debug)]
pub enum ConnectReturnCode {
    Success               = 0,
    UnacceptableProtocol  = 1,
    IdentifierRejected    = 2,
    ServerUnavailable     = 3,
    BadUsernameOrPassword = 4,
    NotAuthorized         = 5,
    Reserved              = 6,
}

#[derive(Debug)]
pub enum ConnectErr {
    ReturnCode(ConnectReturnCode),
    Callback
}

#[derive(Debug, Copy, Clone)]
pub enum MqttError {
    Code(i32),
    Bad
}

#[derive(Debug)]
pub enum Qos {
    FireAndForget  = 0,
    AtLeastOnce    = 1,
    OnceAndOneOnly = 2,
}

#[derive(Debug, Copy, Clone)]
pub enum ActionResult {
    None,
    Ok,
    Err(MqttError)
}

pub struct AsyncClient {
    handle        : ffiasync::MQTTAsync,
    pub random    : i32,
    barrier       : Barrier,
    action_result : ActionResult
}
impl AsyncClient {

    /// Ensures the FFI struct is consistent for callback invocation.
    ///
    /// Because the user may move this struct, the `context` pointer
    /// passed back to FFI callbacks might be invalidated. This function
    /// should be called before FFI actions that might fire callbacks to ensure
    /// the self-pointer is valid.
    fn context(&mut self) -> *mut c_void {
        self as *mut _ as *mut c_void
    }

    pub fn new(address: &str, clientid: &str, persistence: PersistenceType) -> Result<AsyncClient, MqttError> {
        let mut handle                      = unsafe{mem::zeroed()};
        let mut persistence_context: c_void = unsafe{mem::zeroed()};

        let c_url          = CString::new(address).unwrap();
        let c_clientid     = CString::new(clientid).unwrap();
        let array_url      = c_url.as_bytes_with_nul();
        let array_clientid = c_clientid.as_bytes_with_nul();

        let mut error = unsafe {
            ffiasync::MQTTAsync_create(&mut handle,
                                       mem::transmute::<&u8, *const c_char>(&array_url[0]),
                                       mem::transmute::<&u8, *const c_char>(&array_clientid[0]),
                                       persistence as i32,
                                       &mut persistence_context)
        };

        match error {
            0   => { Ok( AsyncClient {
                        handle          : handle,
                        random          : 33,
                        barrier         : Barrier::new(2),
                        action_result   : ActionResult::None
                    })},
            err => Err(MqttError::Code(err))
        }
    }

    pub fn connect(&mut self, options: &mut AsyncConnectOptions) -> Result<(), ConnectErr> {
        unsafe {
            ffiasync::MQTTAsync_setCallbacks(self.handle,
                                             self.context(),
                                             Some(Self::disconnected),
                                             Some(Self::received),
                                             None);
        }

        // fill in FFI private struct
        options.options.keepAliveInterval = options.keep_alive_interval;
        options.options.cleansession      = options.cleansession;
        options.options.maxInflight       = options.max_in_flight;
        options.options.connectTimeout    = options.connect_timeout;
        options.options.retryInterval     = options.retry_interval;

        // register callbacks
        options.options.context   = self.context();
        options.options.onSuccess = Some(Self::action_succeeded);
        options.options.onFailure = Some(Self::action_failed);

        self.action_result = ActionResult::None;
        let mut error = unsafe {
            ffiasync::MQTTAsync_connect(self.handle, &options.options)
        };
        if error == 0 {
            self.barrier.wait();
            if self.is_connected() {
                Ok(())
            } else {
                Err(ConnectErr::Callback)
            }
        } else {
            Err(ConnectErr::ReturnCode(
                match error {
                    1 => ConnectReturnCode::UnacceptableProtocol,
                    2 => ConnectReturnCode::IdentifierRejected,
                    3 => ConnectReturnCode::ServerUnavailable,
                    4 => ConnectReturnCode::BadUsernameOrPassword,
                    5 => ConnectReturnCode::NotAuthorized,
                    _ => ConnectReturnCode::Reserved,
            }))
        }
    }

    extern "C" fn disconnected(context: *mut c_void, cause: *mut c_char) -> () {
        println!("disconnected");
        assert!(!context.is_null());
    }

    pub fn is_connected(&mut self) -> bool {
        let mut ret = unsafe {
            ffiasync::MQTTAsync_isConnected(self.handle)
        };

        match ret {
            1 => true,
            _ => false,
        }
    }

    pub fn send(&mut self, data: &[u8], topic: &str, qos: Qos) -> Result<(), MqttError>{
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let mut message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : data.len() as i32,
            payload         : unsafe {mem::transmute::<&u8, *mut c_void>(&data[0])},
            qos             : qos as c_int,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        let c_topic        = CString::new(topic).unwrap();
        let array_topic    = c_topic.as_bytes_with_nul();
        self.action_result = ActionResult::None;

        let mut error = unsafe {
            ffiasync::MQTTAsync_sendMessage(self.handle,
                                            mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                            &mut message,
                                            &mut responseoption)
        };
        if error == 0 {
            self.barrier.wait();
            match self.action_result {
                ActionResult::None   => unreachable!(),
                ActionResult::Ok     => Ok(()),
                ActionResult::Err(x) => Err(x)
            }
        } else { Err(MqttError::Code(error)) }
    }

    pub fn subscribe(&mut self, topic: &str, qos: Qos) -> Result<(), MqttError> {
        let mut responseoption = ffiasync::MQTTAsync_responseOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'R' as i8],
            struct_version  : 0,
            onSuccess       : Some(Self::action_succeeded),
            onFailure       : Some(Self::action_failed),
            context         : self.context(),
            token           : 0,
        };

        let c_topic     = CString::new(topic).unwrap();
        let array_topic = c_topic.as_bytes_with_nul();

        let c_qos: i32 = match qos {
            Qos::FireAndForget  => 0,
            Qos::AtLeastOnce    => 1,
            Qos::OnceAndOneOnly => 2,
        };
        self.action_result = ActionResult::None;

        let mut error = unsafe {
            ffiasync::MQTTAsync_subscribe(self.handle,
                                          mem::transmute::<&u8, *const c_char>(&array_topic[0]),
                                          c_qos,
                                          &mut responseoption)
        };

        if error == 0 {
            self.barrier.wait();
            match self.action_result {
                ActionResult::None   => unreachable!(),
                ActionResult::Ok     => Ok(()),
                ActionResult::Err(x) => Err(x)
            }
        } else { Err(MqttError::Code(error)) }
    }

    extern "C" fn action_succeeded(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_successData) -> () {
        assert!(!context.is_null());
        let selfclient: &mut AsyncClient = unsafe {mem::transmute(context)};
        selfclient.action_result = ActionResult::Ok;
        selfclient.barrier.wait();
    }

    extern "C" fn action_failed(context: *mut ::libc::c_void, response: *mut ffiasync::MQTTAsync_failureData) -> () {
        assert!(!context.is_null());
        let selfclient : &mut AsyncClient                     = unsafe {mem::transmute(context)};
        if response.is_null() {
            selfclient.action_result = ActionResult::Err(MqttError::Bad);
        } else {
            let resp : &mut ffiasync::MQTTAsync_failureData = unsafe {mem::transmute(response)};
            selfclient.action_result = ActionResult::Err(MqttError::Code(resp.code));
        }
        selfclient.barrier.wait();
    }

    extern "C" fn received(context: *mut ::libc::c_void, topic_name: *mut ::libc::c_char, topic_len: ::libc::c_int, amessage: *mut ffiasync::MQTTAsync_message) -> i32 {
        let c_topic = unsafe {CStr::from_ptr(topic_name).to_bytes()};
        let topic   = String::from_utf8(c_topic.to_vec()).unwrap();
        assert_eq!(topic.len(), topic_len as usize);

        assert!(!amessage.is_null());
        let transmessage: &mut ffiasync::MQTTAsync_message = unsafe {mem::transmute(amessage)};
        let message: &[u8] = unsafe {
                slice::from_raw_parts(transmessage.payload as *mut u8, transmessage.payloadlen as usize)
        };

        let strmessage = String::from_utf8(message.to_vec()).unwrap();
        println!("received from topic: {}", topic);
        println!("       utf8 message: {}", strmessage);
        println!("        raw message: {:?}", message);

        let mut msg = amessage;
        unsafe{ffiasync::MQTTAsync_freeMessage(&mut msg)};
        unsafe{ffiasync::MQTTAsync_free(mem::transmute(topic_name))};

        1
    }
}

impl Drop for AsyncClient {
    fn drop(&mut self) {
        unsafe{ffiasync::MQTTAsync_destroy(&mut self.handle)};
    }
}

pub struct AsyncConnectOptions {
    options: ffiasync::MQTTAsync_connectOptions,

    pub keep_alive_interval : i32,
    pub cleansession        : i32,
    pub max_in_flight       : i32,
    pub connect_timeout     : i32,
    pub retry_interval      : i32,
}
impl AsyncConnectOptions {
    pub fn new() -> AsyncConnectOptions {
        let ffioptions = ffiasync::MQTTAsync_connectOptions {
            struct_id           : ['M' as i8, 'Q' as i8, 'T' as i8, 'C' as i8],
            struct_version      : 3,
            keepAliveInterval   : 60,
            cleansession        : 1,
            maxInflight         : 10,
            will                : ptr::null_mut(),
            username            : ptr::null_mut(),
            password            : ptr::null_mut(),
            connectTimeout      : 30,
            retryInterval       : 0,
            ssl                 : ptr::null_mut(),
            onSuccess           : None,
            onFailure           : None,
            context             : ptr::null_mut(),
            serverURIcount      : 0,
            serverURIs          : ptr::null_mut(),
            MQTTVersion         : 0,
        };

        let options = AsyncConnectOptions {
            options             : ffioptions,

            keep_alive_interval : 20,
            cleansession        : 1,
            max_in_flight       : 10,
            connect_timeout     : 30,
            retry_interval      : 0,
        };

        options
    }
}

pub struct AsyncDisconnectOptions {
    options: ffiasync::MQTTAsync_disconnectOptions,
}
impl AsyncDisconnectOptions {

    pub fn new() -> ffiasync::MQTTAsync_disconnectOptions {
        let options = ffiasync::MQTTAsync_disconnectOptions {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'D' as i8],
            struct_version  : 0,
            timeout         : 0,
            onSuccess       : ptr::null_mut(),
            onFailure       : ptr::null_mut(),
            context         : ptr::null_mut(),
        };

        options
    }
}

pub struct AsyncMessage {
    options: ffiasync::MQTTAsync_message,
}
impl AsyncMessage {

    pub fn new() -> ffiasync::MQTTAsync_message {
        let message = ffiasync::MQTTAsync_message {
            struct_id       : ['M' as i8, 'Q' as i8, 'T' as i8, 'M' as i8],
            struct_version  : 0,
            payloadlen      : 0,
            payload         : ptr::null_mut(),
            qos             : 0,
            retained        : 0,
            dup             : 0,
            msgid           : 0,
        };

        message
    }
}
<|endoftext|>


<commit_before>#![feature(async_await, await_macro, futures_api)]

use futures::channel::mpsc;
use futures::executor::block_on;
use futures::future::poll_fn;
use futures::stream::StreamExt;
use futures::sink::SinkExt;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::thread;

#[test]
fn sequence() {
    let (tx, rx) = mpsc::channel(1);

    let amt = 20;
    let t = thread::spawn(move || {
        block_on(send_sequence(amt, tx))
    });
    let list: Vec<_> = block_on(rx.collect());
    let mut list = list.into_iter();
    for i in (1..amt + 1).rev() {
        assert_eq!(list.next(), Some(i));
    }
    assert_eq!(list.next(), None);

    t.join().unwrap();
}

async fn send_sequence(n: u32, mut sender: mpsc::Sender<u32>) {
    for x in 0..n {
        await!(sender.send(n - x)).unwrap();
    }
}

#[test]
fn drop_sender() {
    let (tx, mut rx) = mpsc::channel::<u32>(1);
    drop(tx);
    let f = poll_fn(|lw| {
        rx.poll_next_unpin(lw)
    });
    assert_eq!(block_on(f), None)
}

#[test]
fn drop_rx() {
    let (mut tx, rx) = mpsc::channel::<u32>(1);
    block_on(tx.send(1)).unwrap();
    drop(rx);
    assert!(block_on(tx.send(1)).is_err());
}

#[test]
fn drop_order() {
    static DROPS: AtomicUsize = ATOMIC_USIZE_INIT;
    let (mut tx, rx) = mpsc::channel(1);

    struct A;

    impl Drop for A {
        fn drop(&mut self) {
            DROPS.fetch_add(1, Ordering::SeqCst);
        }
    }

    block_on(tx.send(A)).unwrap();
    assert_eq!(DROPS.load(Ordering::SeqCst), 0);
    drop(rx);
    assert_eq!(DROPS.load(Ordering::SeqCst), 1);
    assert!(block_on(tx.send(A)).is_err());
    assert_eq!(DROPS.load(Ordering::SeqCst), 2);
}
<commit_msg>Remove deprecated ATOMIC_USIZE_INIT<commit_after>#![feature(async_await, await_macro, futures_api)]

use futures::channel::mpsc;
use futures::executor::block_on;
use futures::future::poll_fn;
use futures::stream::StreamExt;
use futures::sink::SinkExt;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

#[test]
fn sequence() {
    let (tx, rx) = mpsc::channel(1);

    let amt = 20;
    let t = thread::spawn(move || {
        block_on(send_sequence(amt, tx))
    });
    let list: Vec<_> = block_on(rx.collect());
    let mut list = list.into_iter();
    for i in (1..amt + 1).rev() {
        assert_eq!(list.next(), Some(i));
    }
    assert_eq!(list.next(), None);

    t.join().unwrap();
}

async fn send_sequence(n: u32, mut sender: mpsc::Sender<u32>) {
    for x in 0..n {
        await!(sender.send(n - x)).unwrap();
    }
}

#[test]
fn drop_sender() {
    let (tx, mut rx) = mpsc::channel::<u32>(1);
    drop(tx);
    let f = poll_fn(|lw| {
        rx.poll_next_unpin(lw)
    });
    assert_eq!(block_on(f), None)
}

#[test]
fn drop_rx() {
    let (mut tx, rx) = mpsc::channel::<u32>(1);
    block_on(tx.send(1)).unwrap();
    drop(rx);
    assert!(block_on(tx.send(1)).is_err());
}

#[test]
fn drop_order() {
    static DROPS: AtomicUsize = AtomicUsize::new(0);
    let (mut tx, rx) = mpsc::channel(1);

    struct A;

    impl Drop for A {
        fn drop(&mut self) {
            DROPS.fetch_add(1, Ordering::SeqCst);
        }
    }

    block_on(tx.send(A)).unwrap();
    assert_eq!(DROPS.load(Ordering::SeqCst), 0);
    drop(rx);
    assert_eq!(DROPS.load(Ordering::SeqCst), 1);
    assert!(block_on(tx.send(A)).is_err());
    assert_eq!(DROPS.load(Ordering::SeqCst), 2);
}
<|endoftext|>


<commit_before>
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;

use gitlab::errors::*;

fn main() {
    if let Err(ref e) = run() {
        println!("error: {}", e);

        for e in e.iter().skip(1) {
            println!("caused by: {}", e);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            println!("backtrace: {:?}", backtrace);
        }

        ::std::process::exit(1);
    }
}

fn run() -> Result<()> {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token).chain_err(|| "failure to create GitLab instance")?;
    // let gl = GitLab::new(&hostname, &token).chain_err(|| "failure to create GitLab instance")?.scheme("http").port(80);
    // let gl = gl.scheme("http").port(80);

    let projects = gl.projects().list().chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    let projects = gl.projects().archived(false).list().chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    let projects =
        gl.projects().owned().archived(false).list().chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    let projects = gl.projects()
        .all()
        .order_by(gitlab::projects::ListingOrderBy::Name)
        .list()
        .chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    Ok(())
}
<commit_msg>Add examples how to use the chaining methods<commit_after>
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;
// use gitlab::Pagination;

use gitlab::errors::*;

fn main() {
    if let Err(ref e) = run() {
        println!("error: {}", e);

        for e in e.iter().skip(1) {
            println!("caused by: {}", e);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            println!("backtrace: {:?}", backtrace);
        }

        ::std::process::exit(1);
    }
}

fn run() -> Result<()> {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token).chain_err(|| "failure to create GitLab instance")?;
    // let gl = GitLab::new(&hostname, &token).chain_err(|| "failure to create GitLab instance")?.scheme("http").port(80);
    // let gl = gl.scheme("http").port(80);

    let projects = gl.projects().list().chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    let projects = gl.projects().archived(false).list().chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    let projects =
        gl.projects().owned().archived(false).list().chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    let projects = gl.projects()
        .all()
        .order_by(gitlab::projects::ListingOrderBy::Name)
        .list()
        .chain_err(|| "cannot get projects")?;
    println!("projects: {:?}", projects);

    let project = gl
        .projects()
        .id(gitlab::projects::ListingId::Id(9))
        .list()
        .chain_err(|| "failure to find project")?;
    println!("project: {:?}", project);

    let issues = project
        .issues(&gl)
        .list()
        .chain_err(|| "failure to find project's issues")?;
    println!("issues: {:?}", issues);

    let issues = gl
        .projects()
        .id(gitlab::projects::ListingId::Id(9))
        .issues()
        .chain_err(|| "failure to build a gitlab::issues::project::IssuesLister")?
        .list()
        .chain_err(|| "failure to find issues")?;
    println!("issues: {:?}", issues);

    let merge_requests = gl
        .projects()
        .id(gitlab::projects::ListingId::Id(9))
        .merge_requests()
        .chain_err(|| "failure to build a gitlab::merge_requests::project::IssuesLister")?
        .list()
        .chain_err(|| "failure to find merge requests")?;
    println!("merge_requests: {:?}", merge_requests);

    Ok(())
}
<|endoftext|>


<commit_before>extern crate test;

use std::cmp;
use std::cmp::TotalOrd;
use test::BenchHarness;

enum AVLNode<T> {
  // left, right, height, value
  Branch(~AVLNode<T>, ~AVLNode<T>, int, T),
  Nil
}

impl<T:TotalOrd> AVLNode<T> {
  fn in_order_traverse(&self, f: |&T|) {
    match self {
      &Branch(ref left, ref right, _, ref value) => {
        left.in_order_traverse(|x| f(x));
        f(value);
        right.in_order_traverse(|x| f(x));
      },
      &Nil => {}
    }
  }

  // immutable insert function since mutable is horrible
  fn insert(self, insValue: T) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        let (newLeft, newRight) = match insValue.cmp(&value) {
          Equal => (left, right),
          Less => (~left.insert(insValue), right),
          Greater => (left, ~right.insert(insValue))
        };
        let newHeight = cmp::max(newLeft.get_height(), newRight.get_height()) + 1;

        // if newHeight is not old height balance could have changed
        Branch(newLeft, newRight, newHeight, value).balance()
      }
      Nil => {
        Branch(~Nil, ~Nil, 0, insValue)
      }
    }
  }

  fn balance(self) -> AVLNode<T> {
    let balance = self.get_balance();
    match self {
      Branch(left, right, height, value) => {
        if balance > 1 {
          if left.get_balance() == -1 {
            return Branch(~left.left_rotate(), right, height, value).right_rotate();
          } else {
            return Branch(left, right, height, value).right_rotate();
          }
        } else if balance < -1 {
          if right.get_balance() == 1 {
            return Branch(left, ~right.right_rotate(), height, value).left_rotate();
          } else {
            return Branch(left, right, height, value).left_rotate();
          }
        } else {
          return Branch(left, right, height, value);
        }
      },
      Nil => return Nil
    }
  }

  fn left_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        match right {
          ~Branch(pivleft, pivright, pivheight, pivval) => {
            // the math is weird but this works
            let left_height = cmp::max(left.get_height(), pivleft.get_height()) + 1;
            let root_height = cmp::max(left_height + 1, pivright.get_height());
            return Branch(~Branch(left, pivleft, left_height, value), pivright, root_height, pivval);
          },
          ~Nil => fail!("nope")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn right_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        match left {
          ~Branch(pivleft, pivright, pivheight, pivval) => {
            let right_height = cmp::max(right.get_height(), pivright.get_height()) + 1;
            let root_height = cmp::max(right_height + 1, pivleft.get_height());

            return Branch(pivleft, ~Branch(pivright, right, right_height, value), root_height, pivval);
          },
          ~Nil => fail!("no")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn get_balance(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => left.get_height() - right.get_height(),
      &Nil => 0
    }
  }

  fn get_height(&self) -> int {
    match self {
      &Branch(_, _, height, _) => height,
      &Nil => -1
    }
  }

  // please be log(n)
  fn get_depth(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => cmp::max(left.get_depth(), right.get_depth())+1,
      &Nil => 0
    }
  }

  fn find(self, findValue: T) -> bool {
    match self {
      Branch(left, right, _, value) => {
        if value < findValue {
          return left.find(findValue);
        } else if value > findValue {
          return right.find(findValue);
        } else {
          return true;
        }
      },
      Nil => {
        return false;
      }
    }
  }

  fn good(&self) -> bool {
    match self {
      &Branch(ref left, ref right, height, ref value) => {
        match left {
          &~Branch(_, _, _, ref leftValue) => {
            if leftValue > value {
              println!("{:?} is not less than {:?}", leftValue, value);
              return false;
            }
          },
          &~Nil => {}
        }
        match right {
          &~Branch(_, _, _, ref rightValue) => {
            if rightValue < value {
              println!("{:?} is not greater than {:?}", rightValue, value);
              return false;
            }
          },
          &~Nil => {}
        }
        let trueHeight = cmp::max(left.get_depth(), right.get_depth());
        if trueHeight != height {
          println!("incorrect height {}, should be {}", height, trueHeight);
          return false;
        }

        return left.good() && right.good();
      },
      &Nil => return true
    }
  }
}

#[test]
fn test_left_rotate() {
  // let tree = Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5);
  // assert_eq!(tree.left_rotate(), Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5));
}

#[bench]
fn bench_insert_10(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(10);
  });
}

#[bench]
fn bench_insert_100(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(100);
  });
}

#[bench]
fn bench_insert_500(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(500);
  });
}

#[bench]
fn bench_insert_1000(bh: &mut BenchHarness) {
  bh.iter(|| {
    bench_insert(1000);
  });
}

fn bench_insert(n: uint) {
  let mut tree : AVLNode<int> = Branch(~Nil, ~Nil, 0, 0);
  for i in range(0,n) {
    tree = tree.insert(i as int);
    if !tree.good() {
      fail!("incorrect tree...ONE MILLION YEARS DUNGEON");
    }
  }
}

fn main() {
  // println!("depth: {:?}", tree.get_depth());
  // println!("tree: {:?}", tree);

  // let left_right_tree = Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3), ~Nil, 2, 5);
  // tree = Branch(~Nil, ~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 3), -1, 2), -2, 1);
  // println!("tree: {:?}", tree);
  // println!("tree: {:?}", tree.left_rotate());
  // println!("left_rotate left child: {:?}", Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3).left_rotate(), ~Nil, 2, 5));
  // println!("bal?: {:?}", tree.balance());
  // println!("bal: {:?}", Branch(~Branch(~Nil, ~Branch(~Nil, ~Nil, 0, 4), -1, 3).left_rotate(), ~Nil, 2, 5).right_rotate());
}

<commit_msg>Fix up avl_tree for Rust box changes<commit_after>extern crate time;

use std::cmp;
use std::cmp::TotalOrd;
use time::precise_time_ns;

enum AVLNode<T> {
  // left, right, height, value
  Branch(Box<AVLNode<T>>, Box<AVLNode<T>>, int, T),
  Nil
}

impl<T:TotalOrd> AVLNode<T> {
  fn in_order_traverse(&self, f: |&T|) {
    match self {
      &Branch(ref left, ref right, _, ref value) => {
        left.in_order_traverse(|x| f(x));
        f(value);
        right.in_order_traverse(|x| f(x));
      },
      &Nil => {}
    }
  }

  // immutable insert function since mutable is horrible
  fn insert(self, insValue: T) -> AVLNode<T> {
    match self {
      Branch(left, right, height, value) => {
        let (newLeft, newRight) = match insValue.cmp(&value) {
          Equal => (left, right),
          Less => (box left.insert(insValue), right),
          Greater => (left, box right.insert(insValue))
        };
        let newHeight = cmp::max(newLeft.get_height(), newRight.get_height()) + 1;

        // if newHeight is not old height balance could have changed
        if newHeight != height {
          Branch(newLeft, newRight, newHeight, value).balance()
        } else {
          Branch(newLeft, newRight, newHeight, value)
        }
      }
      Nil => {
        Branch(box Nil, box Nil, 0, insValue)
      }
    }
  }

  fn balance(self) -> AVLNode<T> {
    let balance = self.get_balance();
    match self {
      Branch(left, right, height, value) => {
        if balance > 1 {
          if left.get_balance() == -1 {
            return Branch(box left.left_rotate(), right, height, value).right_rotate();
          } else {
            return Branch(left, right, height, value).right_rotate();
          }
        } else if balance < -1 {
          if right.get_balance() == 1 {
            return Branch(left, box right.right_rotate(), height, value).left_rotate();
          } else {
            return Branch(left, right, height, value).left_rotate();
          }
        } else {
          return Branch(left, right, height, value);
        }
      },
      Nil => return Nil
    }
  }

  fn left_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, _, value) => {
        match right {
          box Branch(pivleft, pivright, _, pivval) => {
            // the math is weird but this works
            let left_height = cmp::max(left.get_height(), pivleft.get_height()) + 1;
            let root_height = cmp::max(left_height + 1, pivright.get_height());
            return Branch(box Branch(left, pivleft, left_height, value), pivright, root_height, pivval);
          },
          box Nil => fail!("nope")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn right_rotate(self) -> AVLNode<T> {
    match self {
      Branch(left, right, _, value) => {
        match left {
          box Branch(pivleft, pivright, _, pivval) => {
            let right_height = cmp::max(right.get_height(), pivright.get_height()) + 1;
            let root_height = cmp::max(right_height + 1, pivleft.get_height());

            return Branch(pivleft, box Branch(pivright, right, right_height, value), root_height, pivval);
          },
          box Nil => fail!("no")
        }
      },
      Nil => fail!("not even once")
    }
  }

  fn get_balance(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => left.get_height() - right.get_height(),
      &Nil => 0
    }
  }

  fn get_height(&self) -> int {
    match self {
      &Branch(_, _, height, _) => height,
      &Nil => -1
    }
  }

  // please be log(n)
  fn get_depth(&self) -> int {
    match self {
      &Branch(ref left, ref right, _, _) => cmp::max(left.get_depth(), right.get_depth())+1,
      &Nil => 0
    }
  }

  fn find(self, findValue: T) -> bool {
    match self {
      Branch(left, right, _, value) => {
        if value < findValue {
          return left.find(findValue);
        } else if value > findValue {
          return right.find(findValue);
        } else {
          return true;
        }
      },
      Nil => {
        return false;
      }
    }
  }

  fn good(&self) -> bool {
    match self {
      &Branch(ref left, ref right, height, ref value) => {
        match left {
          &box Branch(_, _, _, ref leftValue) => {
            if leftValue > value {
              println!("{:?} is not less than {:?}", leftValue, value);
              return false;
            }
          },
          &box Nil => {}
        }
        match right {
          &box Branch(_, _, _, ref rightValue) => {
            if rightValue < value {
              println!("{:?} is not greater than {:?}", rightValue, value);
              return false;
            }
          },
          &box Nil => {}
        }
        let trueHeight = cmp::max(left.get_depth(), right.get_depth());
        if trueHeight != height {
          println!("incorrect height {}, should be {}", height, trueHeight);
          return false;
        }

        return left.good() && right.good();
      },
      &Nil => return true
    }
  }
}

#[test]
fn test_left_rotate() {
  // let tree = Branch(box Branch(box Nil, box Branch(box Nil, box Nil, 0, 4), -1, 3), box Nil, 2, 5);
  // assert_eq!(tree.left_rotate(), Branch(box Branch(box Nil, box Branch(box Nil, box Nil, 0, 4), -1, 3), box Nil, 2, 5));
}

fn bench_insert(n: uint) {
  let mut tree : AVLNode<int> = Branch(box Nil, box Nil, 0, 0);
  for i in range(0,n) {
    tree = tree.insert(i as int);
  }
}

fn main() {
  for i in range(1,16) {
    let count = 1 << i;
    let start = precise_time_ns();
    bench_insert(count);
    let end = precise_time_ns();
    println!("({}, {}),", count, end-start);
  }
  // println!("depth: {:?}", tree.get_depth());
  // println!("tree: {:?}", tree);

  // let left_right_tree = Branch(box Branch(box Nil, box Branch(box Nil, box Nil, 0, 4), -1, 3), box Nil, 2, 5);
  // tree = Branch(box Nil, box Branch(box Nil, box Branch(box Nil, box Nil, 0, 3), -1, 2), -2, 1);
  // println!("tree: {:?}", tree);
  // println!("tree: {:?}", tree.left_rotate());
  // println!("left_rotate left child: {:?}", Branch(box Branch(box Nil, box Branch(box Nil, box Nil, 0, 4), -1, 3).left_rotate(), box Nil, 2, 5));
  // println!("bal?: {:?}", tree.balance());
  // println!("bal: {:?}", Branch(box Branch(box Nil, box Branch(box Nil, box Nil, 0, 4), -1, 3).left_rotate(), box Nil, 2, 5).right_rotate());
}

<|endoftext|>


<commit_before>use core::{mem, ptr};

use core::intrinsics::{volatile_load, volatile_store};

use crate::memory::Frame;
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags};
use crate::paging::entry::EntryFlags;

use super::sdt::Sdt;
use super::{ACPI_TABLE, find_sdt};

#[repr(packed)]
#[derive(Clone, Copy, Debug, Default)]
pub struct GenericAddressStructure {
    _address_space: u8,
    _bit_width: u8,
    _bit_offset: u8,
    _access_size: u8,
    pub address: u64,
}

#[repr(packed)]
#[derive(Clone, Copy, Debug)]
pub struct Hpet {
    pub header: Sdt,

    pub hw_rev_id: u8,
    pub comparator_descriptor: u8,
    pub pci_vendor_id: u16,

    pub base_address: GenericAddressStructure,

    pub hpet_number: u8,
    pub min_periodic_clk_tick: u16,
    pub oem_attribute: u8
}

impl Hpet {
    pub fn init() {
        let hpet_sdt = find_sdt("HPET");
        let hpet = if hpet_sdt.len() == 1 {
            Hpet::new(hpet_sdt[0])
        } else {
            println!("Unable to find HPET");
            return;
        };

        if let Some(hpet) = hpet {
            println!("  HPET: {:X}", hpet.hpet_number);

            let mut hpet_t = ACPI_TABLE.hpet.write();
            *hpet_t = Some(hpet);
        }
    }

    pub fn new(sdt: &'static Sdt) -> Option<Hpet> {
        if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::<Hpet>() {
            let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) };
            unsafe { s.base_address.init(&mut KernelMapper::lock()) };
            Some(s)
        } else {
            None
        }
    }
}

//TODO: x86 use assumes only one HPET and only one GenericAddressStructure
#[cfg(target_arch = "x86")]
impl GenericAddressStructure {
    pub unsafe fn init(&self, mapper: &mut KernelMapper) {
        let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
        let page = Page::containing_address(VirtualAddress::new(crate::HPET_OFFSET));

        mapper
            .get_mut()
            .expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
            .map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
            .expect("failed to map memory for GenericAddressStructure")
            .flush();
    }

    pub unsafe fn read_u64(&self, offset: usize) -> u64{
        volatile_load((crate::HPET_OFFSET + offset) as *const u64)
    }

    pub unsafe fn write_u64(&mut self, offset: usize, value: u64) {
        volatile_store((crate::HPET_OFFSET + offset) as *mut u64, value);
    }
}

#[cfg(not(target_arch = "x86"))]
impl GenericAddressStructure {
    pub unsafe fn init(&self, mapper: &mut KernelMapper) {
        let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
        let (_, result) = mapper
            .get_mut()
            .expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
            .map_linearly(frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
            .expect("failed to map memory for GenericAddressStructure");
        result.flush();
    }

    pub unsafe fn read_u64(&self, offset: usize) -> u64{
        volatile_load((self.address as usize + offset + crate::PHYS_OFFSET) as *const u64)
    }

    pub unsafe fn write_u64(&mut self, offset: usize, value: u64) {
        volatile_store((self.address as usize + offset + crate::PHYS_OFFSET) as *mut u64, value);
    }
}
<commit_msg>Fix compilation on i686<commit_after>use core::{mem, ptr};

use core::intrinsics::{volatile_load, volatile_store};

use crate::memory::Frame;
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags};
use crate::paging::entry::EntryFlags;

use super::sdt::Sdt;
use super::{ACPI_TABLE, find_sdt};

#[repr(packed)]
#[derive(Clone, Copy, Debug, Default)]
pub struct GenericAddressStructure {
    _address_space: u8,
    _bit_width: u8,
    _bit_offset: u8,
    _access_size: u8,
    pub address: u64,
}

#[repr(packed)]
#[derive(Clone, Copy, Debug)]
pub struct Hpet {
    pub header: Sdt,

    pub hw_rev_id: u8,
    pub comparator_descriptor: u8,
    pub pci_vendor_id: u16,

    pub base_address: GenericAddressStructure,

    pub hpet_number: u8,
    pub min_periodic_clk_tick: u16,
    pub oem_attribute: u8
}

impl Hpet {
    pub fn init() {
        let hpet_sdt = find_sdt("HPET");
        let hpet = if hpet_sdt.len() == 1 {
            Hpet::new(hpet_sdt[0])
        } else {
            println!("Unable to find HPET");
            return;
        };

        if let Some(hpet) = hpet {
            println!("  HPET: {:X}", hpet.hpet_number);

            let mut hpet_t = ACPI_TABLE.hpet.write();
            *hpet_t = Some(hpet);
        }
    }

    pub fn new(sdt: &'static Sdt) -> Option<Hpet> {
        if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::<Hpet>() {
            let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) };
            unsafe { s.base_address.init(&mut KernelMapper::lock()) };
            Some(s)
        } else {
            None
        }
    }
}

//TODO: x86 use assumes only one HPET and only one GenericAddressStructure
#[cfg(target_arch = "x86")]
impl GenericAddressStructure {
    pub unsafe fn init(&self, mapper: &mut KernelMapper) {
        use crate::paging::{Page, VirtualAddress};

        let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
        let page = Page::containing_address(VirtualAddress::new(crate::HPET_OFFSET));

        mapper
            .get_mut()
            .expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
            .map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
            .expect("failed to map memory for GenericAddressStructure")
            .flush();
    }

    pub unsafe fn read_u64(&self, offset: usize) -> u64{
        volatile_load((crate::HPET_OFFSET + offset) as *const u64)
    }

    pub unsafe fn write_u64(&mut self, offset: usize, value: u64) {
        volatile_store((crate::HPET_OFFSET + offset) as *mut u64, value);
    }
}

#[cfg(not(target_arch = "x86"))]
impl GenericAddressStructure {
    pub unsafe fn init(&self, mapper: &mut KernelMapper) {
        let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
        let (_, result) = mapper
            .get_mut()
            .expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
            .map_linearly(frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
            .expect("failed to map memory for GenericAddressStructure");
        result.flush();
    }

    pub unsafe fn read_u64(&self, offset: usize) -> u64{
        volatile_load((self.address as usize + offset + crate::PHYS_OFFSET) as *const u64)
    }

    pub unsafe fn write_u64(&mut self, offset: usize, value: u64) {
        volatile_store((self.address as usize + offset + crate::PHYS_OFFSET) as *mut u64, value);
    }
}
<|endoftext|>


<commit_before>use std::iter::Iterator;

use num_rational::Ratio;

use crate::buffer::RgbaImage;
use crate::error::ImageResult;

/// An implementation dependent iterator, reading the frames as requested
pub struct Frames<'a> {
    iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>
}

impl<'a> Frames<'a> {
    /// Creates a new `Frames` from an implementation specific iterator.
    pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
        Frames { iterator }
    }

    /// Steps through the iterator from the current frame until the end and pushes each frame into
    /// a `Vec`.
    /// If en error is encountered that error is returned instead.
    ///
    /// Note: This is equivalent to `Frames::collect::<ImageResult<Vec<Frame>>>()`
    pub fn collect_frames(self) -> ImageResult<Vec<Frame>> {
        self.collect()
    }
}

impl<'a> Iterator for Frames<'a> {
    type Item = ImageResult<Frame>;
    fn next(&mut self) -> Option<ImageResult<Frame>> {
        self.iterator.next()
    }
}

/// A single animation frame
#[derive(Clone)]
pub struct Frame {
    /// Delay between the frames in milliseconds
    delay: Delay,
    /// x offset
    left: u32,
    /// y offset
    top: u32,
    buffer: RgbaImage,
}

/// The delay of a frame relative to the previous one.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
pub struct Delay {
    ratio: Ratio<u32>,
}

impl Frame {
    /// Contructs a new frame without any delay.
    pub fn new(buffer: RgbaImage) -> Frame {
        Frame {
            delay: Delay::from_ratio(Ratio::from_integer(0)),
            left: 0,
            top: 0,
            buffer,
        }
    }

    /// Contructs a new frame
    pub fn from_parts(buffer: RgbaImage, left: u32, top: u32, delay: Delay) -> Frame {
        Frame {
            delay,
            left,
            top,
            buffer,
        }
    }

    /// Delay of this frame
    pub fn delay(&self) -> Delay {
        self.delay
    }

    /// Returns the image buffer
    pub fn buffer(&self) -> &RgbaImage {
        &self.buffer
    }

    /// Returns the image buffer
    pub fn into_buffer(self) -> RgbaImage {
        self.buffer
    }

    /// Returns the x offset
    pub fn left(&self) -> u32 {
        self.left
    }

    /// Returns the y offset
    pub fn top(&self) -> u32 {
        self.top
    }
}

impl Delay {
    /// Create a delay from a ratio of milliseconds.
    ///
    /// # Examples
    ///
    /// ```
    /// use image::Delay;
    /// let delay_10ms = Delay::from_num_denom_ms(10, 1);
    /// ```
    pub fn from_num_denom_ms(numerator: u32, denominator: u32) -> Self {
        Delay { ratio: Ratio::new_raw(numerator, denominator) }
    }

    /// The numerator and denominator of the delay in milliseconds.
    pub fn num_denom_ms(self) -> (u32, u32) {
        (*self.ratio.numer(), *self.ratio.denom())
    }

    pub(crate) fn from_ratio(ratio: Ratio<u32>) -> Self {
        Delay { ratio }
    }

    pub(crate) fn into_ratio(self) -> Ratio<u32> {
        self.ratio
    }
}
<commit_msg>Add conversion of Delay into time::Duration<commit_after>use std::iter::Iterator;
use std::time::Duration;

use num_rational::Ratio;

use crate::buffer::RgbaImage;
use crate::error::ImageResult;

/// An implementation dependent iterator, reading the frames as requested
pub struct Frames<'a> {
    iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>
}

impl<'a> Frames<'a> {
    /// Creates a new `Frames` from an implementation specific iterator.
    pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
        Frames { iterator }
    }

    /// Steps through the iterator from the current frame until the end and pushes each frame into
    /// a `Vec`.
    /// If en error is encountered that error is returned instead.
    ///
    /// Note: This is equivalent to `Frames::collect::<ImageResult<Vec<Frame>>>()`
    pub fn collect_frames(self) -> ImageResult<Vec<Frame>> {
        self.collect()
    }
}

impl<'a> Iterator for Frames<'a> {
    type Item = ImageResult<Frame>;
    fn next(&mut self) -> Option<ImageResult<Frame>> {
        self.iterator.next()
    }
}

/// A single animation frame
#[derive(Clone)]
pub struct Frame {
    /// Delay between the frames in milliseconds
    delay: Delay,
    /// x offset
    left: u32,
    /// y offset
    top: u32,
    buffer: RgbaImage,
}

/// The delay of a frame relative to the previous one.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
pub struct Delay {
    ratio: Ratio<u32>,
}

impl Frame {
    /// Contructs a new frame without any delay.
    pub fn new(buffer: RgbaImage) -> Frame {
        Frame {
            delay: Delay::from_ratio(Ratio::from_integer(0)),
            left: 0,
            top: 0,
            buffer,
        }
    }

    /// Contructs a new frame
    pub fn from_parts(buffer: RgbaImage, left: u32, top: u32, delay: Delay) -> Frame {
        Frame {
            delay,
            left,
            top,
            buffer,
        }
    }

    /// Delay of this frame
    pub fn delay(&self) -> Delay {
        self.delay
    }

    /// Returns the image buffer
    pub fn buffer(&self) -> &RgbaImage {
        &self.buffer
    }

    /// Returns the image buffer
    pub fn into_buffer(self) -> RgbaImage {
        self.buffer
    }

    /// Returns the x offset
    pub fn left(&self) -> u32 {
        self.left
    }

    /// Returns the y offset
    pub fn top(&self) -> u32 {
        self.top
    }
}

impl Delay {
    /// Create a delay from a ratio of milliseconds.
    ///
    /// # Examples
    ///
    /// ```
    /// use image::Delay;
    /// let delay_10ms = Delay::from_num_denom_ms(10, 1);
    /// ```
    pub fn from_num_denom_ms(numerator: u32, denominator: u32) -> Self {
        Delay { ratio: Ratio::new_raw(numerator, denominator) }
    }

    /// The numerator and denominator of the delay in milliseconds.
    pub fn num_denom_ms(self) -> (u32, u32) {
        (*self.ratio.numer(), *self.ratio.denom())
    }

    pub(crate) fn from_ratio(ratio: Ratio<u32>) -> Self {
        Delay { ratio }
    }

    pub(crate) fn into_ratio(self) -> Ratio<u32> {
        self.ratio
    }
}

impl From<Delay> for Duration {
    fn from(delay: Delay) -> Self {
        let ratio = delay.into_ratio();
        let ms = ratio.to_integer();
        let rest = ratio.numer() % ratio.denom();
        let nanos = (u64::from(rest) * 1_000_000) / u64::from(*ratio.denom());
        Duration::from_millis(ms.into()) + Duration::from_nanos(nanos)
    }
}

#[cfg(test)]
mod tests {
    use super::{Delay, Duration, Ratio};

    #[test]
    fn simple() {
        let second = Delay::from_num_denom_ms(1000, 1);
        assert_eq!(Duration::from(second), Duration::from_secs(1));
    }

    #[test]
    fn fps_30() {
        let thirtieth = Delay::from_num_denom_ms(1000, 30);
        let duration = Duration::from(thirtieth);
        assert_eq!(duration.as_secs(), 0);
        assert_eq!(duration.subsec_millis(), 33);
        assert_eq!(duration.subsec_nanos(), 33_333_333);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::error;

use hyper::server::Response;
use hyper::status::StatusCode;
use hyper::header::{Server, ContentType};
use serde_json;
use serde::Serialize;

use super::super::{Result, Error, ResultExt, ErrorKind};
use super::super::constants::VERSION;

/// Represents API responses.
pub struct ApiResponse {
    body: Vec<u8>,
    status: StatusCode,
}

/// Represents API Errors.
#[derive(Debug)]
pub enum ApiError {
    NotFound,
    BadRequest,
    MethodNotAllowed,
    PayloadTooLarge,
    BadJson(Box<serde_json::Error>),
    SdkNotFound,
    InternalServerError(Box<Error>),
}

#[derive(Serialize)]
struct ApiErrorDescription {
    #[serde(rename="type")]
    pub ty: String,
    pub message: String,
}

impl ApiResponse {
    /// Creates a new API response.
    pub fn new<S: Serialize>(data: S, status: StatusCode) -> Result<ApiResponse> {
        let mut body : Vec<u8> = vec![];
        serde_json::to_writer(&mut body, &data)
            .chain_err(|| "Failed to serialize response for client")?;
        Ok(ApiResponse {
            body: body,
            status: status,
        })
    }

    /// Creates an API response from a given error.
    pub fn from_error(err: Error) -> Result<ApiResponse> {
        if_chain! {
            if let &ErrorKind::ApiError(_) = err.kind();
            if let Error(ErrorKind::ApiError(api_error), _) = err;
            then {
                return api_error.into_api_response();
            }
        }

        error!("Internal Server Error: {}", &err);
        if let Some(backtrace) = err.backtrace() {
            debug!("  Traceback: {:?}", backtrace);
        }

        ApiResponse::new(ApiErrorDescription {
            ty: "internal_server_error".into(),
            message: format!("The server failed with an internal error: {}",
                &err),
        }, StatusCode::InternalServerError)
    }

    /// Writes the API response into a hyper response.
    pub fn write_to_response(&self, mut resp: Response) -> Result<()> {
        *resp.status_mut() = self.status;
        resp.headers_mut().set(ContentType::json());
        resp.headers_mut().set(Server(format!("sentry-symbolserver/{}", VERSION)));
        resp.send(&self.body[..])?;
        Ok(())
    }
}

impl ApiError {
    /// Returns the HTTP status code for this error.
    pub fn get_status(&self) -> StatusCode {
        match *self {
            ApiError::NotFound => StatusCode::NotFound,
            ApiError::BadRequest => StatusCode::BadRequest,
            ApiError::MethodNotAllowed => StatusCode::MethodNotAllowed,
            ApiError::PayloadTooLarge => StatusCode::PayloadTooLarge,
            ApiError::BadJson(_) => StatusCode::BadRequest,
            ApiError::SdkNotFound => StatusCode::NotFound,
            ApiError::InternalServerError(_) => StatusCode::InternalServerError,
        }
    }

    fn describe(&self) -> ApiErrorDescription {
        match *self {
            ApiError::NotFound => {
                ApiErrorDescription {
                    ty: "not_found".into(),
                    message: "The requested resource was not found".into(),
                }
            }
            ApiError::BadRequest => {
                ApiErrorDescription {
                    ty: "bad_request".into(),
                    message: "The client sent a bad request".into(),
                }
            }
            ApiError::MethodNotAllowed => {
                ApiErrorDescription {
                    ty: "method_not_allowed".into(),
                    message: "This HTTP method is not supported here".into(),
                }
            }
            ApiError::PayloadTooLarge => {
                ApiErrorDescription {
                    ty: "payload_too_large".into(),
                    message: "The request payload is too large".into(),
                }
            }
            ApiError::BadJson(ref json_err) => {
                ApiErrorDescription {
                    ty: "bad_json".into(),
                    message: format!("The client sent bad json: {}", json_err),
                }
            }
            ApiError::SdkNotFound => {
                ApiErrorDescription {
                    ty: "sdk_not_found".into(),
                    message: "The requested SDK was not found".into(),
                }
            }
            ApiError::InternalServerError(ref err) => {
                ApiErrorDescription {
                    ty: "internal_server_error".into(),
                    message: format!(
                        "The server failed with an internal error: {}",
                        err),
                }
            }
        }
    }

    /// Converts the error into a response.
    pub fn into_api_response(self) -> Result<ApiResponse> {
        ApiResponse::new(self.describe(), self.get_status())
    }
}

impl error::Error for ApiError {
    fn description(&self) -> &str {
        "API error"
    }
}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "API error")
    }
}
<commit_msg>Add a newline at end of JSON output<commit_after>use std::fmt;
use std::error;

use hyper::server::Response;
use hyper::status::StatusCode;
use hyper::header::{Server, ContentType};
use serde_json;
use serde::Serialize;

use super::super::{Result, Error, ResultExt, ErrorKind};
use super::super::constants::VERSION;

/// Represents API responses.
pub struct ApiResponse {
    body: Vec<u8>,
    status: StatusCode,
}

/// Represents API Errors.
#[derive(Debug)]
pub enum ApiError {
    NotFound,
    BadRequest,
    MethodNotAllowed,
    PayloadTooLarge,
    BadJson(Box<serde_json::Error>),
    SdkNotFound,
    InternalServerError(Box<Error>),
}

#[derive(Serialize)]
struct ApiErrorDescription {
    #[serde(rename="type")]
    pub ty: String,
    pub message: String,
}

impl ApiResponse {
    /// Creates a new API response.
    pub fn new<S: Serialize>(data: S, status: StatusCode) -> Result<ApiResponse> {
        let mut body : Vec<u8> = vec![];
        serde_json::to_writer(&mut body, &data)
            .chain_err(|| "Failed to serialize response for client")?;
        body.push(b'\n');
        Ok(ApiResponse {
            body: body,
            status: status,
        })
    }

    /// Creates an API response from a given error.
    pub fn from_error(err: Error) -> Result<ApiResponse> {
        if_chain! {
            if let &ErrorKind::ApiError(_) = err.kind();
            if let Error(ErrorKind::ApiError(api_error), _) = err;
            then {
                return api_error.into_api_response();
            }
        }

        error!("Internal Server Error: {}", &err);
        if let Some(backtrace) = err.backtrace() {
            debug!("  Traceback: {:?}", backtrace);
        }

        ApiResponse::new(ApiErrorDescription {
            ty: "internal_server_error".into(),
            message: format!("The server failed with an internal error: {}",
                &err),
        }, StatusCode::InternalServerError)
    }

    /// Writes the API response into a hyper response.
    pub fn write_to_response(&self, mut resp: Response) -> Result<()> {
        *resp.status_mut() = self.status;
        resp.headers_mut().set(ContentType::json());
        resp.headers_mut().set(Server(format!("sentry-symbolserver/{}", VERSION)));
        resp.send(&self.body[..])?;
        Ok(())
    }
}

impl ApiError {
    /// Returns the HTTP status code for this error.
    pub fn get_status(&self) -> StatusCode {
        match *self {
            ApiError::NotFound => StatusCode::NotFound,
            ApiError::BadRequest => StatusCode::BadRequest,
            ApiError::MethodNotAllowed => StatusCode::MethodNotAllowed,
            ApiError::PayloadTooLarge => StatusCode::PayloadTooLarge,
            ApiError::BadJson(_) => StatusCode::BadRequest,
            ApiError::SdkNotFound => StatusCode::NotFound,
            ApiError::InternalServerError(_) => StatusCode::InternalServerError,
        }
    }

    fn describe(&self) -> ApiErrorDescription {
        match *self {
            ApiError::NotFound => {
                ApiErrorDescription {
                    ty: "not_found".into(),
                    message: "The requested resource was not found".into(),
                }
            }
            ApiError::BadRequest => {
                ApiErrorDescription {
                    ty: "bad_request".into(),
                    message: "The client sent a bad request".into(),
                }
            }
            ApiError::MethodNotAllowed => {
                ApiErrorDescription {
                    ty: "method_not_allowed".into(),
                    message: "This HTTP method is not supported here".into(),
                }
            }
            ApiError::PayloadTooLarge => {
                ApiErrorDescription {
                    ty: "payload_too_large".into(),
                    message: "The request payload is too large".into(),
                }
            }
            ApiError::BadJson(ref json_err) => {
                ApiErrorDescription {
                    ty: "bad_json".into(),
                    message: format!("The client sent bad json: {}", json_err),
                }
            }
            ApiError::SdkNotFound => {
                ApiErrorDescription {
                    ty: "sdk_not_found".into(),
                    message: "The requested SDK was not found".into(),
                }
            }
            ApiError::InternalServerError(ref err) => {
                ApiErrorDescription {
                    ty: "internal_server_error".into(),
                    message: format!(
                        "The server failed with an internal error: {}",
                        err),
                }
            }
        }
    }

    /// Converts the error into a response.
    pub fn into_api_response(self) -> Result<ApiResponse> {
        ApiResponse::new(self.describe(), self.get_status())
    }
}

impl error::Error for ApiError {
    fn description(&self) -> &str {
        "API error"
    }
}

impl fmt::Display for ApiError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "API error")
    }
}
<|endoftext|>


<commit_before>extern crate argparse;
extern crate image;
extern crate path_tracer;

use argparse::{ArgumentParser, Store, Collect};
use path_tracer::*;
use std::fs::File;
use std::io::{self, BufReader};
use std::io::prelude::*;

#[derive(Debug)]
enum ImageError {
    IoError(io::Error),
    BadFileError(String)
}
use ImageError::*;

impl From<io::Error> for ImageError {
    fn from(e: io::Error) -> ImageError {
        ImageError::IoError(e)
    }
}
type Result<T> = std::result::Result<T, ImageError>;

struct PartialImage {
    image : Vec<Vec<Vec3d>>,
    samples : i32,
}

impl PartialImage {
    fn empty() -> PartialImage {
        PartialImage { image: Vec::new(), samples: 0 }
    }

    // I'm totally unsure about whether this is taking additional copies.
    fn add(self, other: PartialImage) -> PartialImage {
        let image = if self.samples == 0 { other.image } else {
            // A nicer way to do this would be ideal. This may well be doing lots of boundchecks.
            let mut combined : Vec<Vec<Vec3d>> = self.image;
            for y in 0..combined.len() {
                for x in 0..combined[y].len() {
                    combined[y][x] = combined[y][x] + other.image[y][x];
                }
            }
            combined
        };
        let samples = self.samples + other.samples;
        PartialImage { image: image, samples: samples }
    }

    fn height(&self) -> usize {
        self.image.len()
    }
    fn width(&self) -> usize {
        self.image[0].len()
    }
}

fn load_file(name: &String) -> Result<PartialImage> {
    let mut result : Vec<Vec<Vec3d>> = Vec::new();
    let file = BufReader::new(try!(File::open(&name)));
    println!("Loading '{}'", name);
    let mut line_iter = file.lines();
    let first_line = line_iter.next().unwrap().ok().unwrap();
    let mut first_line_words = first_line.split(' ').map(|x| x.parse::<i32>().unwrap());
    let width = first_line_words.next().unwrap() as usize;
    let height = first_line_words.next().unwrap() as usize;
    let samples = first_line_words.next().unwrap(); // this is terrible
    println!("Found {} samples in {}x{} image", samples, width, height);
    for line in line_iter.filter_map(|x| x.ok()) {
        let mut vecs : Vec<Vec3d> = Vec::new();
        let mut split = line.split(' ').map(|x| x.parse::<f64>().unwrap());
        loop {
            let x = match split.next() {
                None => break,
                Some(x) => x
            };
            let y : f64 = split.next().unwrap();
            let z : f64 = split.next().unwrap();
            vecs.push(Vec3d::new(x, y, z) * samples as f64);
        }
        if vecs.len() != width {
            return Err(BadFileError("Bad width".to_string()));
        }
        result.push(vecs);
    }
    if result.len() != height {
        return Err(BadFileError("Bad height".to_string()));
    }
    println!("Loaded ok");
    Ok(PartialImage { image: result, samples: samples })
}

fn main() {
    let mut to_merge : Vec<String> = Vec::new();
    let mut output_filename = "image.png".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Combine several sample images into one PNG");
        ap.refer(&mut output_filename).add_option(&["-o", "--output"], Store,
                                                  "Filename to output to");
        ap.refer(&mut to_merge).add_argument("files", Collect, "Files to merge")
            .required();
        ap.parse_args_or_exit();
    }
    let accum : PartialImage = to_merge.iter()
        .map(load_file)
        .map(|x| x.unwrap())
        .fold(PartialImage::empty(), |acc, item| { acc.add(item) });

    println!("Merged {} samples", accum.samples);
    println!("Writing output to '{}'", output_filename);
    let height = accum.height();
    let width = accum.width();
    let samples = accum.samples;
    let mut image = image::ImageBuffer::new(width as u32, height as u32);
    for y in 0..height {
        for x in 0..width {
            let sum = accum.image[y][x] / samples as f64;
            image.put_pixel(x as u32, y as u32, image::Rgb([to_int(sum.x), to_int(sum.y), to_int(sum.z)]));
        }
    }
    let mut output_file = File::create(output_filename).unwrap();
    image::ImageRgb8(image).save(&mut output_file, image::PNG).unwrap();
}
<commit_msg>Slight improvement on the iterator front<commit_after>extern crate argparse;
extern crate image;
extern crate path_tracer;

use argparse::{ArgumentParser, Store, Collect};
use path_tracer::*;
use std::fs::File;
use std::io::{self, BufReader};
use std::io::prelude::*;

#[derive(Debug)]
enum ImageError {
    IoError(io::Error),
    BadFileError(String)
}
use ImageError::*;

impl From<io::Error> for ImageError {
    fn from(e: io::Error) -> ImageError {
        ImageError::IoError(e)
    }
}
type Result<T> = std::result::Result<T, ImageError>;

struct PartialImage {
    image : Vec<Vec<Vec3d>>,
    samples : i32,
}

impl PartialImage {
    fn empty() -> PartialImage {
        PartialImage { image: Vec::new(), samples: 0 }
    }

    // I'm totally unsure about whether this is taking additional copies.
    fn add(self, other: PartialImage) -> PartialImage {
        let image = if self.samples == 0 { other.image } else {
            // A nicer way to do this would be ideal. This may well be doing lots of boundchecks.
            let mut combined : Vec<Vec<Vec3d>> = self.image;
            for y in 0..combined.len() {
                for x in 0..combined[y].len() {
                    combined[y][x] = combined[y][x] + other.image[y][x];
                }
            }
            combined
        };
        let samples = self.samples + other.samples;
        PartialImage { image: image, samples: samples }
    }

    fn height(&self) -> usize {
        self.image.len()
    }
    fn width(&self) -> usize {
        self.image[0].len()
    }
}

fn load_file(name: &String) -> Result<PartialImage> {
    let mut result : Vec<Vec<Vec3d>> = Vec::new();
    let file = BufReader::new(try!(File::open(&name)));
    println!("Loading '{}'", name);
    let mut line_iter = file.lines();
    let first_line = try!(line_iter.next().unwrap());
    let first_line : Vec<usize> = first_line.split(' ').filter_map(|x| x.parse().ok()).collect();
    // Rust experimental branch would let us match on the vector.
    if first_line.len() != 3 { return Err(BadFileError("Bad header".to_string())); }
    let width = first_line[0];
    let height = first_line[1];
    let samples = first_line[2] as i32;
    println!("Found {} samples in {}x{} image", samples, width, height);
    for line in line_iter.filter_map(|x| x.ok()) {
        let mut vecs : Vec<Vec3d> = Vec::new();
        let mut split = line.split(' ').filter_map(|x| x.parse::<f64>().ok());
        loop {
            match (split.next(), split.next(), split.next()) {
                (None, _, _) => break,
                (Some(x), Some(y), Some(z)) => {
                    vecs.push(Vec3d::new(x, y, z) * samples as f64);
                },
                (_, _, _) => return Err(BadFileError("Bad line".to_string())),
            }
        }
        if vecs.len() != width {
            return Err(BadFileError("Bad width".to_string()));
        }
        result.push(vecs);
    }
    if result.len() != height {
        return Err(BadFileError("Bad height".to_string()));
    }
    println!("Loaded ok");
    Ok(PartialImage { image: result, samples: samples })
}

fn main() {
    let mut to_merge : Vec<String> = Vec::new();
    let mut output_filename = "image.png".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Combine several sample images into one PNG");
        ap.refer(&mut output_filename).add_option(&["-o", "--output"], Store,
                                                  "Filename to output to");
        ap.refer(&mut to_merge).add_argument("files", Collect, "Files to merge")
            .required();
        ap.parse_args_or_exit();
    }
    let accum : PartialImage = to_merge.iter()
        .map(load_file)
        .map(|x| x.unwrap())
        .fold(PartialImage::empty(), |acc, item| { acc.add(item) });

    println!("Merged {} samples", accum.samples);
    println!("Writing output to '{}'", output_filename);
    let height = accum.height();
    let width = accum.width();
    let samples = accum.samples;
    let mut image = image::ImageBuffer::new(width as u32, height as u32);
    for y in 0..height {
        for x in 0..width {
            let sum = accum.image[y][x] / samples as f64;
            image.put_pixel(x as u32, y as u32, image::Rgb([to_int(sum.x), to_int(sum.y), to_int(sum.z)]));
        }
    }
    let mut output_file = File::create(output_filename).unwrap();
    image::ImageRgb8(image).save(&mut output_file, image::PNG).unwrap();
}
<|endoftext|>


<commit_before>#![crate_id="cargo"]
#![crate_type="rlib"]

#![feature(macro_rules, phase)]

extern crate debug;
extern crate term;
extern crate url;
extern crate serialize;
extern crate semver;
extern crate toml;

#[phase(plugin, link)]
extern crate hammer;

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate hamcrest;

use serialize::{Decoder, Encoder, Decodable, Encodable, json};
use std::io;
use std::io::{stdout, stderr};
use std::io::stdio::{stdout_raw, stderr_raw};
use hammer::{Flags, decode_args, usage};

use core::{Shell, MultiShell, ShellConfig};
use term::color::{BLACK};

pub use util::{CargoError, CliError, CliResult, human};

macro_rules! some(
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => return None
        }
    )
)

// Added so that the try! macro below can refer to cargo::util, while
// other external importers of this macro can use it as well.
//
// "Hygiene strikes again" - @acrichton
mod cargo {
    pub use super::util;
}

#[macro_export]
macro_rules! try (
    ($expr:expr) => ({
        use cargo::util::FromError;
        match $expr.map_err(FromError::from_error) {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

macro_rules! raw_try (
    ($expr:expr) => ({
        match $expr {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

trait RepresentsJSON : Decodable<json::Decoder, json::DecoderError> {}
impl<T: Decodable<json::Decoder, json::DecoderError>> RepresentsJSON for T {}

#[deriving(Decodable)]
pub struct NoFlags;

hammer_config!(NoFlags)

#[deriving(Decodable)]
pub struct GlobalFlags {
    verbose: bool,
    help: bool,
    rest: Vec<String>
}

hammer_config!(GlobalFlags |c| {
    c.short("verbose", 'v').short("help", 'h')
})

pub fn execute_main<'a,
                    T: Flags,
                    U: RepresentsJSON,
                    V: Encodable<json::Encoder<'a>, io::IoError>>(
                        exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            U: RepresentsJSON,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        let json = try!(json_from_stdin::<U>());

        exec(flags, json, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

pub fn execute_main_without_stdin<'a,
                                  T: Flags,
                                  V: Encodable<json::Encoder<'a>, io::IoError>>(
                                      exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        exec(flags, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

fn process<'a,
           T: Flags,
           V: Encodable<json::Encoder<'a>, io::IoError>>(
               callback: |&[String], &mut MultiShell| -> CliResult<Option<V>>) {

    match global_flags() {
        Err(e) => handle_error(e, &mut shell(false)),
        Ok(val) => {
            let mut shell = shell(val.verbose);

            if val.help {
                let (desc, options) = usage::<T>(true);

                desc.map(|d| println!("{}\n", d));

                println!("Options:\n");

                print!("{}", options);

                let (_, options) = usage::<GlobalFlags>(false);
                print!("{}", options);
            } else {
                process_executed(callback(val.rest.as_slice(), &mut shell), &mut shell)
            }
        }
    }
}

pub fn process_executed<'a,
                        T: Encodable<json::Encoder<'a>, io::IoError>>(
                            result: CliResult<Option<T>>,
                            shell: &mut MultiShell)
{
    match result {
        Err(e) => handle_error(e, shell),
        Ok(encodable) => {
            encodable.map(|encodable| {
                let encoded = json::Encoder::str_encode(&encodable);
                println!("{}", encoded);
            });
        }
    }
}

pub fn shell(verbose: bool) -> MultiShell {
    let tty = stderr_raw().isatty();
    let stderr = box stderr() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let err = Shell::create(stderr, config);

    let tty = stdout_raw().isatty();
    let stdout = box stdout() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let out = Shell::create(stdout, config);

    MultiShell::new(out, err, verbose)
}

pub fn handle_error(err: CliError, shell: &mut MultiShell) {
    log!(4, "handle_error; err={}", err);

    let CliError { error, exit_code, unknown, .. } = err;

    if unknown {
        let _ = shell.error("An unknown error occurred");
    } else {
        let _ = shell.error(error.to_str());
    }

    if error.cause().is_some() {
        let _ = shell.concise(|shell| {
            shell.err().say("\nTo learn more, run the command again with --verbose.", BLACK)
        });
    }

    let _ = shell.verbose(|shell| {
        let _ = handle_cause(error, shell);
        Ok(())
      });

    std::os::set_exit_status(exit_code as int);
}

fn handle_cause(err: &CargoError, shell: &mut MultiShell) {
    let _ = shell.err().say("\nCaused by:", BLACK);
    let _ = shell.err().say(format!("  {}", err.description()), BLACK);

    err.cause().map(|e| handle_cause(e, shell));
}

fn args() -> Vec<String> {
    std::os::args()
}

fn flags_from_args<T: Flags>(args: &[String]) -> CliResult<T> {
    decode_args(args).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn global_flags() -> CliResult<GlobalFlags> {
    decode_args(args().tail()).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn json_from_stdin<T: RepresentsJSON>() -> CliResult<T> {
    let mut reader = io::stdin();
    let input = try!(reader.read_to_str().map_err(|_| {
        CliError::new("Standard in did not exist or was not UTF-8", 1)
    }));

    let json = try!(json::from_str(input.as_slice()).map_err(|_| {
        CliError::new("Could not parse standard in as JSON", 1)
    }));
    let mut decoder = json::Decoder::new(json);

    Decodable::decode(&mut decoder).map_err(|_| {
        CliError::new("Could not process standard in as input", 1)
    })
}
<commit_msg>Fixing deprecated JSON call<commit_after>#![crate_id="cargo"]
#![crate_type="rlib"]

#![feature(macro_rules, phase)]

extern crate debug;
extern crate term;
extern crate url;
extern crate serialize;
extern crate semver;
extern crate toml;

#[phase(plugin, link)]
extern crate hammer;

#[phase(plugin, link)]
extern crate log;

#[cfg(test)]
extern crate hamcrest;

use serialize::{Decoder, Encoder, Decodable, Encodable, json};
use std::io;
use std::io::{stdout, stderr};
use std::io::stdio::{stdout_raw, stderr_raw};
use hammer::{Flags, decode_args, usage};

use core::{Shell, MultiShell, ShellConfig};
use term::color::{BLACK};

pub use util::{CargoError, CliError, CliResult, human};

macro_rules! some(
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => return None
        }
    )
)

// Added so that the try! macro below can refer to cargo::util, while
// other external importers of this macro can use it as well.
//
// "Hygiene strikes again" - @acrichton
mod cargo {
    pub use super::util;
}

#[macro_export]
macro_rules! try (
    ($expr:expr) => ({
        use cargo::util::FromError;
        match $expr.map_err(FromError::from_error) {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

macro_rules! raw_try (
    ($expr:expr) => ({
        match $expr {
            Ok(val) => val,
            Err(err) => return Err(err)
        }
    })
)

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

trait RepresentsJSON : Decodable<json::Decoder, json::DecoderError> {}
impl<T: Decodable<json::Decoder, json::DecoderError>> RepresentsJSON for T {}

#[deriving(Decodable)]
pub struct NoFlags;

hammer_config!(NoFlags)

#[deriving(Decodable)]
pub struct GlobalFlags {
    verbose: bool,
    help: bool,
    rest: Vec<String>
}

hammer_config!(GlobalFlags |c| {
    c.short("verbose", 'v').short("help", 'h')
})

pub fn execute_main<'a,
                    T: Flags,
                    U: RepresentsJSON,
                    V: Encodable<json::Encoder<'a>, io::IoError>>(
                        exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            U: RepresentsJSON,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, U, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        let json = try!(json_from_stdin::<U>());

        exec(flags, json, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

pub fn execute_main_without_stdin<'a,
                                  T: Flags,
                                  V: Encodable<json::Encoder<'a>, io::IoError>>(
                                      exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>)
{
    fn call<'a,
            T: Flags,
            V: Encodable<json::Encoder<'a>, io::IoError>>(
                exec: fn(T, &mut MultiShell) -> CliResult<Option<V>>,
                shell: &mut MultiShell,
                args: &[String])
        -> CliResult<Option<V>>
    {
        let flags = try!(flags_from_args::<T>(args));
        exec(flags, shell)
    }

    process::<T, V>(|rest, shell| call(exec, shell, rest));
}

fn process<'a,
           T: Flags,
           V: Encodable<json::Encoder<'a>, io::IoError>>(
               callback: |&[String], &mut MultiShell| -> CliResult<Option<V>>) {

    match global_flags() {
        Err(e) => handle_error(e, &mut shell(false)),
        Ok(val) => {
            let mut shell = shell(val.verbose);

            if val.help {
                let (desc, options) = usage::<T>(true);

                desc.map(|d| println!("{}\n", d));

                println!("Options:\n");

                print!("{}", options);

                let (_, options) = usage::<GlobalFlags>(false);
                print!("{}", options);
            } else {
                process_executed(callback(val.rest.as_slice(), &mut shell), &mut shell)
            }
        }
    }
}

pub fn process_executed<'a,
                        T: Encodable<json::Encoder<'a>, io::IoError>>(
                            result: CliResult<Option<T>>,
                            shell: &mut MultiShell)
{
    match result {
        Err(e) => handle_error(e, shell),
        Ok(encodable) => {
            encodable.map(|encodable| {
                let encoded = json::encode(&encodable);
                println!("{}", encoded);
            });
        }
    }
}

pub fn shell(verbose: bool) -> MultiShell {
    let tty = stderr_raw().isatty();
    let stderr = box stderr() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let err = Shell::create(stderr, config);

    let tty = stdout_raw().isatty();
    let stdout = box stdout() as Box<Writer>;

    let config = ShellConfig { color: true, verbose: verbose, tty: tty };
    let out = Shell::create(stdout, config);

    MultiShell::new(out, err, verbose)
}

pub fn handle_error(err: CliError, shell: &mut MultiShell) {
    log!(4, "handle_error; err={}", err);

    let CliError { error, exit_code, unknown, .. } = err;

    if unknown {
        let _ = shell.error("An unknown error occurred");
    } else {
        let _ = shell.error(error.to_str());
    }

    if error.cause().is_some() {
        let _ = shell.concise(|shell| {
            shell.err().say("\nTo learn more, run the command again with --verbose.", BLACK)
        });
    }

    let _ = shell.verbose(|shell| {
        let _ = handle_cause(error, shell);
        Ok(())
      });

    std::os::set_exit_status(exit_code as int);
}

fn handle_cause(err: &CargoError, shell: &mut MultiShell) {
    let _ = shell.err().say("\nCaused by:", BLACK);
    let _ = shell.err().say(format!("  {}", err.description()), BLACK);

    err.cause().map(|e| handle_cause(e, shell));
}

fn args() -> Vec<String> {
    std::os::args()
}

fn flags_from_args<T: Flags>(args: &[String]) -> CliResult<T> {
    decode_args(args).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn global_flags() -> CliResult<GlobalFlags> {
    decode_args(args().tail()).map_err(|e| {
        CliError::new(e.message, 1)
    })
}

fn json_from_stdin<T: RepresentsJSON>() -> CliResult<T> {
    let mut reader = io::stdin();
    let input = try!(reader.read_to_str().map_err(|_| {
        CliError::new("Standard in did not exist or was not UTF-8", 1)
    }));

    let json = try!(json::from_str(input.as_slice()).map_err(|_| {
        CliError::new("Could not parse standard in as JSON", 1)
    }));
    let mut decoder = json::Decoder::new(json);

    Decodable::decode(&mut decoder).map_err(|_| {
        CliError::new("Could not process standard in as input", 1)
    })
}
<|endoftext|>