<commit_before>extern crate zmq;
extern crate libnm;
extern crate nalgebra as na;

use protobuf::*;
use self::libnm::protocol::messages;
use self::na::*;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};

use context;
use renderers;

const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");

fn unserialize_matrix4(v: &[f32]) -> Matrix4<f32> {
    Matrix4::new(
        v[0],
        v[1],
        v[2],
        v[3],
        v[4],
        v[5],
        v[6],
        v[7],
        v[8],
        v[9],
        v[10],
        v[11],
        v[12],
        v[13],
        v[14],
        v[15]
    )
}

pub struct Graphs {
    pub n: i64
}

pub struct Server<'a> {
    addr: &'a str,
    ctx: context::Context,
    graphs: Arc<RwLock<Graphs>>
}

impl<'a> Server<'a> {

    pub fn new() -> Server<'a> {
        let server = Server{
            addr: option_env!("NMD_ADDR").unwrap_or("*:5555"),
            ctx: context::Context::new(),
            graphs: Arc::new(RwLock::new(Graphs{n: 1}))
        };
        server
    }

    pub fn listen(&mut self) {
        let mut context = zmq::Context::new();
        let mut responder = context.socket(zmq::REP).unwrap();

        let addr = format!("tcp://{}", self.addr);
        responder.bind(&addr).ok().expect("Could not bind to the address.");

        let mut msg = zmq::Message::new().unwrap();

        loop {
            responder.recv(&mut msg, 0).unwrap();
            let requests = parse_from_bytes::<messages::Requests>(&msg).unwrap();
            let mut responses = Vec::new();

            for (i, request) in requests.get_requests().iter().enumerate() {
                let response = self.get_response(request);

                if let Some(mut res) = response {
                    res.set_index(i as i64);
                    responses.push(res);
                }
            }

            let mut res_message = messages::Responses::new();
            res_message.set_responses(RepeatedField::from_vec(responses));
            let bytes = res_message.write_to_bytes().unwrap();
            responder.send(&bytes, 0).unwrap();
        }
    }

    fn get_response(
        &mut self, request: &messages::Request
    ) -> Option<messages::Response> {
        match request.get_request_type() {
            messages::Request_RequestType::GET_VERSION => {
                Server::get_version()
            },
            messages::Request_RequestType::CREATE_RENDERER => {
                self.create_renderer(request.get_create_renderer_request())
            },
            messages::Request_RequestType::DELETE_RENDERER => {
                self.delete_renderer(request.get_delete_renderer_request())
            },
            messages::Request_RequestType::UPDATE_VIEWER_TRANSFORM => {
                self.update_viewer_transform(
                    request.get_update_viewer_transform_request()
                )
            },
            messages::Request_RequestType::CREATE_CAMERA => {
                self.create_camera(request.get_create_camera_request())
            },
            messages::Request_RequestType::DELETE_CAMERA => {
                self.delete_camera(request.get_delete_camera_request())
            },
            messages::Request_RequestType::UPDATE_CAMERA_TRANSFORM => {
                self.update_camera_transform(
                    request.get_update_camera_transform_request()
                )
            },
            messages::Request_RequestType::UDPATE_CAMERA_PROJECTION => {
                self.update_camera_projection(
                    request.get_update_camera_projection_request()
                )
            },
            _ => None
        }
    }

    fn get_version() -> Option<messages::Response> {
        let mut res = messages::GetVersionResponse::new();
        res.set_version(VERSION.unwrap_or("unknown").to_string());

        let mut msg = messages::Response::new();
        msg.set_response_type(messages::Response_ResponseType::GET_VERSION);
        msg.set_get_version_response(res);
        return Some(msg);
    }

    fn create_renderer(
        &mut self, request: &messages::CreateRendererRequest
    ) -> Option<messages::Response> {
        let mut cameras = HashMap::new();
        for camera in request.get_cameras() {
            let camera_name = camera.get_name().to_string();
            cameras.insert(camera_name.clone(), renderers::Camera{
                name: camera_name,
                transform: unserialize_matrix4(camera.get_transform()),
                projection: unserialize_matrix4(camera.get_projection())
            });
        }

        let viewer = renderers::Viewer{
            cameras: cameras,
            transform: unserialize_matrix4(
                request.get_viewer_transform()
            )
        };

        // Initialize the renderer with options.
        let mut renderer_options = HashMap::new();
        for option in request.get_options() {
            renderer_options.insert(option.get_key().to_string(), option.get_value().to_string());
        }

        let renderer: Box<renderers::Renderer> = match request.get_renderer_type() {
            messages::CreateRendererRequest_RendererType::DISPLAY => {
                unimplemented!()
            },
            messages::CreateRendererRequest_RendererType::WEBGL => {
                Box::new(renderers::webgl::WebGLRenderer::new(
                    self.graphs.clone(),
                    viewer,
                    renderer_options
                ))
            }
        };

        // Add the renderer to context.
        let renderer_id = self.ctx.add_renderer(renderer);
        let mut msg = messages::ItemCreatedResponse::new();
        msg.set_item_id(renderer_id);

        let mut res = messages::Response::new();
        res.set_response_type(messages::Response_ResponseType::ITEM_CREATED);
        res.set_item_created_response(msg);
        Some(res)
    }

    fn delete_renderer(
        &mut self, request: &messages::DeleteRendererRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        self.ctx.delete_renderer_with_id(renderer_id);
        None
    }

    fn update_viewer_transform(
        &mut self, request: &messages::UpdateViewerTransformRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let transform = unserialize_matrix4(request.get_transform());
        renderer.viewer().transform = transform;
        renderer.update_viewer_transform(transform);
        None
    }

    fn create_camera(
        &mut self, request: &messages::CreateCameraRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let req_camera = request.get_camera();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = req_camera.get_name();
        let camera = renderers::Camera{
            name: camera_name.to_string(),
            transform: unserialize_matrix4(req_camera.get_transform()),
            projection: unserialize_matrix4(req_camera.get_projection())
        };
        renderer.add_camera(&camera);
        renderer.viewer().cameras.insert(camera_name.to_string(), camera);
        None
    }

    fn delete_camera(
        &mut self, request: &messages::DeleteCameraRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = request.get_camera_name();
        renderer.viewer().cameras.remove(camera_name);
        renderer.delete_camera_with_name(request.get_camera_name());
        None
    }

    fn update_camera_transform(
        &mut self, request: &messages::UpdateCameraTransformRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let mut renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = request.get_camera_name();
        let transform = unserialize_matrix4(request.get_transform());
        renderer.viewer().cameras.get_mut(camera_name).unwrap().transform = transform;
        renderer.update_camera_transform(
            camera_name,
            transform
        );
        None
    }

    fn update_camera_projection(
        &mut self, request: &messages::UpdateCameraProjectionRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = request.get_camera_name();
        let projection = unserialize_matrix4(request.get_transform());
        renderer.viewer().cameras.get_mut(camera_name).unwrap().projection = projection;
        renderer.update_camera_projection(
            camera_name,
            projection
        );
        None
    }
}
<commit_msg>Disable ItemCreatedResponse<commit_after>extern crate zmq;
extern crate libnm;
extern crate nalgebra as na;

use protobuf::*;
use self::libnm::protocol::messages;
use self::na::*;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};

use context;
use renderers;

const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");

fn unserialize_matrix4(v: &[f32]) -> Matrix4<f32> {
    Matrix4::new(
        v[0],
        v[1],
        v[2],
        v[3],
        v[4],
        v[5],
        v[6],
        v[7],
        v[8],
        v[9],
        v[10],
        v[11],
        v[12],
        v[13],
        v[14],
        v[15]
    )
}

pub struct Graphs {
    pub n: i64
}

pub struct Server<'a> {
    addr: &'a str,
    ctx: context::Context,
    graphs: Arc<RwLock<Graphs>>
}

impl<'a> Server<'a> {

    pub fn new() -> Server<'a> {
        let server = Server{
            addr: option_env!("NMD_ADDR").unwrap_or("*:5555"),
            ctx: context::Context::new(),
            graphs: Arc::new(RwLock::new(Graphs{n: 1}))
        };
        server
    }

    pub fn listen(&mut self) {
        let mut context = zmq::Context::new();
        let mut responder = context.socket(zmq::REP).unwrap();

        let addr = format!("tcp://{}", self.addr);
        responder.bind(&addr).ok().expect("Could not bind to the address.");

        let mut msg = zmq::Message::new().unwrap();

        loop {
            responder.recv(&mut msg, 0).unwrap();
            let requests = parse_from_bytes::<messages::Requests>(&msg).unwrap();
            let mut responses = Vec::new();

            for (i, request) in requests.get_requests().iter().enumerate() {
                let response = self.get_response(request);

                if let Some(mut res) = response {
                    res.set_index(i as i64);
                    responses.push(res);
                }
            }

            let mut res_message = messages::Responses::new();
            res_message.set_responses(RepeatedField::from_vec(responses));
            let bytes = res_message.write_to_bytes().unwrap();
            responder.send(&bytes, 0).unwrap();
        }
    }

    fn get_response(
        &mut self, request: &messages::Request
    ) -> Option<messages::Response> {
        match request.get_request_type() {
            messages::Request_RequestType::GET_VERSION => {
                Server::get_version()
            },
            messages::Request_RequestType::CREATE_RENDERER => {
                self.create_renderer(request.get_create_renderer_request())
            },
            messages::Request_RequestType::DELETE_RENDERER => {
                self.delete_renderer(request.get_delete_renderer_request())
            },
            messages::Request_RequestType::UPDATE_VIEWER_TRANSFORM => {
                self.update_viewer_transform(
                    request.get_update_viewer_transform_request()
                )
            },
            messages::Request_RequestType::CREATE_CAMERA => {
                self.create_camera(request.get_create_camera_request())
            },
            messages::Request_RequestType::DELETE_CAMERA => {
                self.delete_camera(request.get_delete_camera_request())
            },
            messages::Request_RequestType::UPDATE_CAMERA_TRANSFORM => {
                self.update_camera_transform(
                    request.get_update_camera_transform_request()
                )
            },
            messages::Request_RequestType::UDPATE_CAMERA_PROJECTION => {
                self.update_camera_projection(
                    request.get_update_camera_projection_request()
                )
            },
            _ => None
        }
    }

    fn get_version() -> Option<messages::Response> {
        let mut res = messages::GetVersionResponse::new();
        res.set_version(VERSION.unwrap_or("unknown").to_string());

        let mut msg = messages::Response::new();
        msg.set_response_type(messages::Response_ResponseType::GET_VERSION);
        msg.set_get_version_response(res);
        return Some(msg);
    }

    fn create_renderer(
        &mut self, request: &messages::CreateRendererRequest
    ) -> Option<messages::Response> {
        let mut cameras = HashMap::new();
        for camera in request.get_cameras() {
            let camera_name = camera.get_name().to_string();
            cameras.insert(camera_name.clone(), renderers::Camera{
                name: camera_name,
                transform: unserialize_matrix4(camera.get_transform()),
                projection: unserialize_matrix4(camera.get_projection())
            });
        }

        let viewer = renderers::Viewer{
            cameras: cameras,
            transform: unserialize_matrix4(
                request.get_viewer_transform()
            )
        };

        // Initialize the renderer with options.
        let mut renderer_options = HashMap::new();
        for option in request.get_options() {
            renderer_options.insert(option.get_key().to_string(), option.get_value().to_string());
        }

        let renderer: Box<renderers::Renderer> = match request.get_renderer_type() {
            messages::CreateRendererRequest_RendererType::DISPLAY => {
                unimplemented!()
            },
            messages::CreateRendererRequest_RendererType::WEBGL => {
                Box::new(renderers::webgl::WebGLRenderer::new(
                    self.graphs.clone(),
                    viewer,
                    renderer_options
                ))
            }
        };

        // Add the renderer to context.
        // let renderer_id = self.ctx.add_renderer(renderer);
        // let mut msg = messages::ItemCreatedResponse::new();
        // msg.set_item_id(renderer_id);

        let mut res = messages::Response::new();
        res.set_response_type(messages::Response_ResponseType::ITEM_CREATED);
        // res.set_item_created_response(msg);
        Some(res)
    }

    fn delete_renderer(
        &mut self, request: &messages::DeleteRendererRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        self.ctx.delete_renderer_with_id(renderer_id);
        None
    }

    fn update_viewer_transform(
        &mut self, request: &messages::UpdateViewerTransformRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let transform = unserialize_matrix4(request.get_transform());
        renderer.viewer().transform = transform;
        renderer.update_viewer_transform(transform);
        None
    }

    fn create_camera(
        &mut self, request: &messages::CreateCameraRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let req_camera = request.get_camera();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = req_camera.get_name();
        let camera = renderers::Camera{
            name: camera_name.to_string(),
            transform: unserialize_matrix4(req_camera.get_transform()),
            projection: unserialize_matrix4(req_camera.get_projection())
        };
        renderer.add_camera(&camera);
        renderer.viewer().cameras.insert(camera_name.to_string(), camera);
        None
    }

    fn delete_camera(
        &mut self, request: &messages::DeleteCameraRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = request.get_camera_name();
        renderer.viewer().cameras.remove(camera_name);
        renderer.delete_camera_with_name(request.get_camera_name());
        None
    }

    fn update_camera_transform(
        &mut self, request: &messages::UpdateCameraTransformRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let mut renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = request.get_camera_name();
        let transform = unserialize_matrix4(request.get_transform());
        renderer.viewer().cameras.get_mut(camera_name).unwrap().transform = transform;
        renderer.update_camera_transform(
            camera_name,
            transform
        );
        None
    }

    fn update_camera_projection(
        &mut self, request: &messages::UpdateCameraProjectionRequest
    ) -> Option<messages::Response> {
        let renderer_id = request.get_renderer_id();
        let renderer = self.ctx.get_renderer_with_id(renderer_id);
        let camera_name = request.get_camera_name();
        let projection = unserialize_matrix4(request.get_transform());
        renderer.viewer().cameras.get_mut(camera_name).unwrap().projection = projection;
        renderer.update_camera_projection(
            camera_name,
            projection
        );
        None
    }
}
<|endoftext|>


<commit_before>extern crate elektra_sys;

use crate::{KeySetError, ReadableKey, StrKey, StringKey, WriteableKey};
use bitflags::bitflags;
use std::convert::TryInto;
// use std::ffi::CString;

#[derive(Debug)]
pub struct KeySet {
    ptr: std::ptr::NonNull<elektra_sys::KeySet>,
    phantom: std::marker::PhantomData<elektra_sys::KeySet>,
}

pub type Cursor = elektra_sys::cursor_t;

bitflags! {
    // Results in default value with bits: 0
    #[derive(Default)]
    pub struct LookupOption: elektra_sys::option_t {
        const KDB_O_NONE = elektra_sys::KDB_O_NONE as elektra_sys::option_t;
        const KDB_O_DEL = elektra_sys::KDB_O_DEL as elektra_sys::option_t;
        const KDB_O_POP = elektra_sys::KDB_O_POP as elektra_sys::option_t;
        const KDB_O_NODIR = elektra_sys::KDB_O_NODIR as elektra_sys::option_t;
        const KDB_O_DIRONLY = elektra_sys::KDB_O_DIRONLY as elektra_sys::option_t;
        const KDB_O_NOREMOVE = elektra_sys::KDB_O_NOREMOVE as elektra_sys::option_t;
        const KDB_O_REMOVEONLY = elektra_sys::KDB_O_REMOVEONLY as elektra_sys::option_t;
        const KDB_O_INACTIVE = elektra_sys::KDB_O_INACTIVE as elektra_sys::option_t;
        const KDB_O_SYNC = elektra_sys::KDB_O_SYNC as elektra_sys::option_t;
        const KDB_O_SORT = elektra_sys::KDB_O_SORT as elektra_sys::option_t;
        const KDB_O_NORECURSIVE = elektra_sys::KDB_O_NORECURSIVE as elektra_sys::option_t;
        const KDB_O_NOCASE = elektra_sys::KDB_O_NOCASE as elektra_sys::option_t;
        const KDB_O_WITHOWNER = elektra_sys::KDB_O_WITHOWNER as elektra_sys::option_t;
        const KDB_O_NOALL = elektra_sys::KDB_O_NOALL as elektra_sys::option_t;
    }
}

impl Drop for KeySet {
    fn drop(&mut self) {
        println!("Drop {:?}", self);
        unsafe {
            elektra_sys::ksDel(self.as_ptr());
        }
    }
}

// impl Iterator for KeySet {
//     type Item = StrKey<'a>;
//     fn next(&self) -> Option<Self::Item> {
//         let key_ptr = unsafe { elektra_sys::ksNext(self.as_ptr()) };
//         if (key_ptr as *const elektra_sys::Key) == std::ptr::null() {
//             None
//         } else {
//             Some(StrKey::from_ptr(key_ptr as *mut elektra_sys::Key))
//         }
//     }
// }

impl KeySet {
    fn as_ptr(&mut self) -> *mut elektra_sys::KeySet {
        self.ptr.as_ptr()
    }

    fn as_ref(&self) -> &elektra_sys::KeySet {
        unsafe { self.ptr.as_ref() }
    }

    /// Create a new empty KeySet
    pub fn new() -> KeySet {
        let ks_ptr = unsafe { elektra_sys::ksNew(0, elektra_sys::KEY_END) };
        KeySet::from_ptr(ks_ptr)
    }

    /// Create a new KeySet that allocates enough space for the
    /// given capacity of keys
    pub fn with_capacity(capacity: usize) -> Self {
        let ks_ptr = unsafe { elektra_sys::ksNew(capacity, elektra_sys::KEY_END) };
        Self::from_ptr(ks_ptr)
    }

    fn from_ptr(keyset_ptr: *mut elektra_sys::KeySet) -> KeySet {
        KeySet {
            ptr: std::ptr::NonNull::new(keyset_ptr).unwrap(),
            phantom: std::marker::PhantomData,
        }
    }

    /// Append a key to the keyset
    /// May return an InsertionFailure error, if the key was already added
    pub fn append_key<T: WriteableKey>(&mut self, mut key: T) -> Result<(), KeySetError> {
        let ret_val = unsafe { elektra_sys::ksAppendKey(self.as_ptr(), key.as_ptr()) };
        if ret_val == -1 {
            Err(KeySetError::InsertionFailure)
        } else {
            Ok(())
        }
    }

    /// Append a vector of keys to the KeySet.
    /// It will call append_key on every key. If any key returns an error it will be returned,
    /// but only after iterating over all keys.
    pub fn append_all<T: WriteableKey>(&mut self, keys: Vec<T>) -> Result<(), KeySetError> {
        let mut err = None;
        for key in keys {
            if let Err(ks_err) = self.append_key(key) {
                err = Some(ks_err);
            }
        }
        if let Some(error) = err {
            Err(error)
        } else {
            Ok(())
        }
    }

    /// Return a duplicate of a keyset.
    pub fn duplicate(&self) -> Self {
        let ks_ptr = unsafe { elektra_sys::ksDup(self.as_ref()) };
        Self::from_ptr(ks_ptr)
    }

    /// Replace the content of a keyset with another one.
    /// Copies the contents of source into self
    pub fn copy(&mut self, source: &Self) {
        unsafe { elektra_sys::ksCopy(self.as_ptr(), source.as_ref()) };
    }

    /// Return the number of keys that ks contains.
    pub fn get_size(&self) -> usize {
        unsafe { elektra_sys::ksGetSize(self.as_ref()).try_into().unwrap() }
    }

    /// Rewinds the KeySet internal cursor.
    pub fn rewind(&mut self) {
        unsafe {
            elektra_sys::ksRewind(self.as_ptr());
        }
    }

    /// Return the first key in the KeySet
    /// or None if the KeySet is empty.
    pub fn head(&self) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksHead(self.as_ref()) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Return the key pointed at by the internal cursor
    /// or None if the end is reached or after [`rewind`].
    ///
    /// [`rewind`]: #method.rewind
    pub fn current(&self) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksCurrent(self.as_ref()) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Return the last key in the KeySet
    /// or None if the KeySet is empty.
    pub fn tail(&self) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksTail(self.as_ref()) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Get the KeySet internal cursor.
    pub fn get_cursor(&self) -> Cursor {
        unsafe { elektra_sys::ksGetCursor(self.as_ref()) }
    }

    /// Return key at given cursor position or None if the cursor
    /// has a negative position or a position that does not lie within the keyset.
    pub fn at_cursor(&mut self, cursor: Cursor) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksAtCursor(self.as_ptr(), cursor) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Set the KeySet cursor.
    pub fn set_cursor(&mut self, cursor: Cursor) {
        unsafe {
            elektra_sys::ksSetCursor(self.as_ptr(), cursor);
        }
    }

    pub fn lookup<'a>(
        &'a mut self,
        mut key: StringKey,
        options: LookupOption,
    ) -> Option<StrKey<'a>> {
        println!("Got flags {:?}", options.bits() as elektra_sys::option_t);
        let key_ptr = unsafe {
            elektra_sys::ksLookup(
                self.as_ptr(),
                key.as_ptr(),
                options.bits() as elektra_sys::option_t,
            )
        };
        if options.contains(LookupOption::KDB_O_DEL) {
            std::mem::forget(key);
        }

        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            // let dup_ptr = unsafe { elektra_sys::keyDup(key_ptr as *const elektra_sys::Key) };
            Some(StrKey::from_ptr(key_ptr))
        }
    }

    // pub fn lookup_by_name(&mut self, name: &str, options: LookupOption) -> Option<StringKey> {
    //     println!("Got flags {:?}", options.bits() as elektra_sys::option_t);
    //     let cname = CString::new(name).unwrap();
    //     let key_ptr = unsafe {
    //         elektra_sys::ksLookupByName(
    //             self.as_ptr(),
    //             cname.as_ptr(),
    //             options.bits() as elektra_sys::option_t,
    //         )
    //     };
    //     println!("keyptr is {:?}", key_ptr);

    //     if key_ptr as *const elektra_sys::Key == std::ptr::null() {
    //         println!("is null");
    //         None
    //     } else {
    //         if options.contains(LookupOption::KDB_O_DEL) {
    //             println!("contains del");
    //             None
    //         } else {
    //             let dup_ptr = unsafe { elektra_sys::keyDup(key_ptr as *const elektra_sys::Key) };
    //             Some(StringKey::from_ptr(dup_ptr))
    //         }
    //     }
    // }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::KeyBuilder;

    #[test]
    fn can_build_simple_keyset() {
        let mut ks = KeySet::new();
        ks.append_key(
            KeyBuilder::<StringKey>::new("user/sw/org/app/bool")
                .value("true")
                .build(),
        )
        .unwrap();
        // Make sure that the returned key from head can be dropped
        // without deleting the actual key
        {
            let head = ks.head().unwrap();
            assert_eq!(head.get_value(), "true");
        }
        {
            let head = ks.head().unwrap();
            assert_eq!(head.get_value(), "true");
        }
    }

    // #[test]
    // fn can_iterate_simple_keyset() {
    //     let names = ["user/test/key1", "user/test/key2", "user/test/key3"];
    //     let values = ["value1", "value2", "value3"];

    //     let mut ks = KeySet::with_capacity(3);

    //     ks.append_all(vec![
    //         KeyBuilder::<StringKey>::new(names[0])
    //             .value(values[0])
    //             .build(),
    //         KeyBuilder::<StringKey>::new(names[1])
    //             .value(values[1])
    //             .build(),
    //         KeyBuilder::<StringKey>::new(names[2])
    //             .value(values[2])
    //             .build(),
    //     ])
    //     .unwrap();
    //     ks.rewind();

    //     let mut did_iterate = false;
    //     for (i, key) in ks.enumerate() {
    //         did_iterate = true;
    //         assert_eq!(key.get_value(), values[i]);
    //         assert_eq!(key.get_name(), names[i]);
    //     }
    //     assert!(did_iterate);
    // }

    fn setup_keyset() -> KeySet {
        let names = ["system/test/key", "user/test/key"];
        let values = ["value1", "value3"];

        let mut ks = KeySet::with_capacity(3);

        ks.append_all(vec![
            KeyBuilder::<StringKey>::new(names[0])
                .value(values[0])
                .build(),
            KeyBuilder::<StringKey>::new(names[1])
                .value(values[1])
                .build(),
            // KeyBuilder::<StringKey>::new(names[2])
            //     .value(values[2])
            //     .build(),
        ])
        .unwrap();
        ks
    }

    #[test]
    fn can_lookup_key_with_none_option() {
        let mut ks = setup_keyset();
        let lookup_key = StringKey::new("/test/key").unwrap();
        println!("Lookup_key is {:?}", lookup_key);
        let ret_val = ks.lookup(lookup_key, LookupOption::KDB_O_NONE);
        assert_eq!(ret_val.unwrap().get_name(), "user/test/key");
        assert_eq!(ks.get_size(), 2);
        assert_eq!(ks.tail().unwrap().get_name(), "user/test/key");
    }

    #[test]
    fn can_lookup_key_with_del_option() {
        let mut ks = setup_keyset();
        let lookup_key = StringKey::new("/test/key").unwrap();
        let key = ks.lookup(lookup_key, LookupOption::KDB_O_DEL);
        assert_eq!(key.unwrap().get_name(), "user/test/key");
        assert_eq!(ks.get_size(), 2);
        assert_eq!(ks.head().unwrap().get_name(), "system/test/key");
    }

    #[test]
    fn can_lookup_and_duplicate_key() {
        // Make sure that a duplicate of a key that is from a keyset
        // can be used after the KeySet has been freed
        let key;
        {
            let lookup_key = StringKey::new("/test/key").unwrap();
            let mut ks = setup_keyset();
            key = ks
                .lookup(lookup_key, LookupOption::KDB_O_DEL)
                .unwrap()
                .to_owned();
            assert_eq!(ks.get_size(), 2);
            assert_eq!(ks.head().unwrap().get_name(), "system/test/key");
        }
        assert_eq!(key.get_name(), "user/test/key");
    }

}
<commit_msg>Rust: Add a keyset iter over borrowed references<commit_after>extern crate elektra_sys;

use crate::{KeySetError, ReadableKey, StrKey, StringKey, WriteableKey};
use bitflags::bitflags;
use std::convert::TryInto;
// use std::ffi::CString;

#[derive(Debug)]
pub struct KeySet {
    ptr: std::ptr::NonNull<elektra_sys::KeySet>,
    phantom: std::marker::PhantomData<elektra_sys::KeySet>,
}

pub type Cursor = elektra_sys::cursor_t;

bitflags! {
    // Results in default value with bits: 0
    #[derive(Default)]
    pub struct LookupOption: elektra_sys::option_t {
        const KDB_O_NONE = elektra_sys::KDB_O_NONE as elektra_sys::option_t;
        const KDB_O_DEL = elektra_sys::KDB_O_DEL as elektra_sys::option_t;
        const KDB_O_POP = elektra_sys::KDB_O_POP as elektra_sys::option_t;
        const KDB_O_NODIR = elektra_sys::KDB_O_NODIR as elektra_sys::option_t;
        const KDB_O_DIRONLY = elektra_sys::KDB_O_DIRONLY as elektra_sys::option_t;
        const KDB_O_NOREMOVE = elektra_sys::KDB_O_NOREMOVE as elektra_sys::option_t;
        const KDB_O_REMOVEONLY = elektra_sys::KDB_O_REMOVEONLY as elektra_sys::option_t;
        const KDB_O_INACTIVE = elektra_sys::KDB_O_INACTIVE as elektra_sys::option_t;
        const KDB_O_SYNC = elektra_sys::KDB_O_SYNC as elektra_sys::option_t;
        const KDB_O_SORT = elektra_sys::KDB_O_SORT as elektra_sys::option_t;
        const KDB_O_NORECURSIVE = elektra_sys::KDB_O_NORECURSIVE as elektra_sys::option_t;
        const KDB_O_NOCASE = elektra_sys::KDB_O_NOCASE as elektra_sys::option_t;
        const KDB_O_WITHOWNER = elektra_sys::KDB_O_WITHOWNER as elektra_sys::option_t;
        const KDB_O_NOALL = elektra_sys::KDB_O_NOALL as elektra_sys::option_t;
    }
}

impl Drop for KeySet {
    fn drop(&mut self) {
        println!("Drop {:?}", self);
        unsafe {
            elektra_sys::ksDel(self.as_ptr());
        }
    }
}

impl Iterator for KeySet {
    type Item = StringKey;
    fn next(&mut self) -> Option<Self::Item> {
        let key_ptr = unsafe { elektra_sys::ksNext(self.as_ptr()) };
        if (key_ptr as *const elektra_sys::Key) == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr as *mut elektra_sys::Key))
        }
    }
}

impl KeySet {
    fn as_ptr(&mut self) -> *mut elektra_sys::KeySet {
        self.ptr.as_ptr()
    }

    fn as_ref(&self) -> &elektra_sys::KeySet {
        unsafe { self.ptr.as_ref() }
    }

    /// Create a new empty KeySet
    pub fn new() -> KeySet {
        let ks_ptr = unsafe { elektra_sys::ksNew(0, elektra_sys::KEY_END) };
        KeySet::from_ptr(ks_ptr)
    }

    /// Create a new KeySet that allocates enough space for the
    /// given capacity of keys
    pub fn with_capacity(capacity: usize) -> Self {
        let ks_ptr = unsafe { elektra_sys::ksNew(capacity, elektra_sys::KEY_END) };
        Self::from_ptr(ks_ptr)
    }

    fn from_ptr(keyset_ptr: *mut elektra_sys::KeySet) -> KeySet {
        KeySet {
            ptr: std::ptr::NonNull::new(keyset_ptr).unwrap(),
            phantom: std::marker::PhantomData,
        }
    }

    /// Append a key to the keyset
    /// May return an InsertionFailure error, if the key was already added
    pub fn append_key<T: WriteableKey>(&mut self, mut key: T) -> Result<(), KeySetError> {
        let ret_val = unsafe { elektra_sys::ksAppendKey(self.as_ptr(), key.as_ptr()) };
        if ret_val == -1 {
            Err(KeySetError::InsertionFailure)
        } else {
            Ok(())
        }
    }

    /// Append a vector of keys to the KeySet.
    /// It will call append_key on every key. If any key returns an error it will be returned,
    /// but only after iterating over all keys.
    pub fn append_all<T: WriteableKey>(&mut self, keys: Vec<T>) -> Result<(), KeySetError> {
        let mut err = None;
        for key in keys {
            if let Err(ks_err) = self.append_key(key) {
                err = Some(ks_err);
            }
        }
        if let Some(error) = err {
            Err(error)
        } else {
            Ok(())
        }
    }

    /// Return a duplicate of a keyset.
    pub fn duplicate(&self) -> Self {
        let ks_ptr = unsafe { elektra_sys::ksDup(self.as_ref()) };
        Self::from_ptr(ks_ptr)
    }

    /// Replace the content of a keyset with another one.
    /// Copies the contents of source into self
    pub fn copy(&mut self, source: &Self) {
        unsafe { elektra_sys::ksCopy(self.as_ptr(), source.as_ref()) };
    }

    /// Return the number of keys that ks contains.
    pub fn get_size(&self) -> usize {
        unsafe { elektra_sys::ksGetSize(self.as_ref()).try_into().unwrap() }
    }

    /// Rewinds the KeySet internal cursor.
    pub fn rewind(&mut self) {
        unsafe {
            elektra_sys::ksRewind(self.as_ptr());
        }
    }

    /// Return the first key in the KeySet
    /// or None if the KeySet is empty.
    pub fn head(&self) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksHead(self.as_ref()) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Return the key pointed at by the internal cursor
    /// or None if the end is reached or after [`rewind`].
    ///
    /// [`rewind`]: #method.rewind
    pub fn current(&self) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksCurrent(self.as_ref()) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Return the last key in the KeySet
    /// or None if the KeySet is empty.
    pub fn tail(&self) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksTail(self.as_ref()) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Get the KeySet internal cursor.
    pub fn get_cursor(&self) -> Cursor {
        unsafe { elektra_sys::ksGetCursor(self.as_ref()) }
    }

    /// Return key at given cursor position or None if the cursor
    /// has a negative position or a position that does not lie within the keyset.
    pub fn at_cursor(&mut self, cursor: Cursor) -> Option<StringKey> {
        let key_ptr = unsafe { elektra_sys::ksAtCursor(self.as_ptr(), cursor) };
        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            Some(StringKey::from_ptr(key_ptr))
        }
    }

    /// Set the KeySet cursor.
    pub fn set_cursor(&mut self, cursor: Cursor) {
        unsafe {
            elektra_sys::ksSetCursor(self.as_ptr(), cursor);
        }
    }

    pub fn lookup<'a>(
        &'a mut self,
        mut key: StringKey,
        options: LookupOption,
    ) -> Option<StrKey<'a>> {
        println!("Got flags {:?}", options.bits() as elektra_sys::option_t);
        let key_ptr = unsafe {
            elektra_sys::ksLookup(
                self.as_ptr(),
                key.as_ptr(),
                options.bits() as elektra_sys::option_t,
            )
        };
        if options.contains(LookupOption::KDB_O_DEL) {
            std::mem::forget(key);
        }

        if key_ptr as *const elektra_sys::Key == std::ptr::null() {
            None
        } else {
            // let dup_ptr = unsafe { elektra_sys::keyDup(key_ptr as *const elektra_sys::Key) };
            Some(StrKey::from_ptr(key_ptr))
        }
    }

    // pub fn lookup_by_name(&mut self, name: &str, options: LookupOption) -> Option<StringKey> {
    //     println!("Got flags {:?}", options.bits() as elektra_sys::option_t);
    //     let cname = CString::new(name).unwrap();
    //     let key_ptr = unsafe {
    //         elektra_sys::ksLookupByName(
    //             self.as_ptr(),
    //             cname.as_ptr(),
    //             options.bits() as elektra_sys::option_t,
    //         )
    //     };
    //     println!("keyptr is {:?}", key_ptr);

    //     if key_ptr as *const elektra_sys::Key == std::ptr::null() {
    //         println!("is null");
    //         None
    //     } else {
    //         if options.contains(LookupOption::KDB_O_DEL) {
    //             println!("contains del");
    //             None
    //         } else {
    //             let dup_ptr = unsafe { elektra_sys::keyDup(key_ptr as *const elektra_sys::Key) };
    //             Some(StringKey::from_ptr(dup_ptr))
    //         }
    //     }
    // }

    pub fn iter<'a>(&'a mut self) -> StrKeyIter<'a> {
        StrKeyIter {
            cursor: None,
            keyset: self,
        }
    }
}

pub struct StrKeyIter<'a> {
    cursor: Option<Cursor>,
    keyset: &'a mut KeySet,
}

impl<'a> Iterator for StrKeyIter<'a> {
    type Item = StrKey<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.cursor {
            None => {
                let key_ptr = unsafe { elektra_sys::ksNext(self.keyset.as_ptr()) };
                if (key_ptr as *const elektra_sys::Key) == std::ptr::null() {
                    None
                } else {
                    self.cursor = Some(self.keyset.get_cursor());
                    Some(StrKey::from_ptr(key_ptr))
                }
            }
            Some(cursor) => {
                self.cursor = Some(cursor + 1);
                self.keyset.set_cursor(self.cursor.unwrap());
                let key_ptr = unsafe { elektra_sys::ksCurrent(self.keyset.as_ptr()) };

                if (key_ptr as *const elektra_sys::Key) == std::ptr::null() {
                    self.cursor = None;
                    None
                } else {
                    Some(StrKey::from_ptr(key_ptr))
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::KeyBuilder;

    #[test]
    fn can_build_simple_keyset() {
        let mut ks = KeySet::new();
        ks.append_key(
            KeyBuilder::<StringKey>::new("user/sw/org/app/bool")
                .value("true")
                .build(),
        )
        .unwrap();
        // Make sure that the returned key from head can be dropped
        // without deleting the actual key
        {
            let head = ks.head().unwrap();
            assert_eq!(head.get_value(), "true");
        }
        {
            let head = ks.head().unwrap();
            assert_eq!(head.get_value(), "true");
        }
    }

    #[test]
    fn can_iterate_simple_keyset_immutably() {
        let names = ["user/test/key1", "user/test/key2", "user/test/key3"];
        let values = ["value1", "value2", "value3"];

        let mut ks = KeySet::with_capacity(3);

        ks.append_all(vec![
            KeyBuilder::<StringKey>::new(names[0])
                .value(values[0])
                .build(),
            KeyBuilder::<StringKey>::new(names[1])
                .value(values[1])
                .build(),
            KeyBuilder::<StringKey>::new(names[2])
                .value(values[2])
                .build(),
        ])
        .unwrap();
        ks.rewind();

        let mut did_iterate = false;
        for (i, key) in ks.iter().enumerate() {
            did_iterate = true;
            assert_eq!(key.get_value(), values[i]);
            assert_eq!(key.get_name(), names[i]);
        }
        assert!(did_iterate);

        // Make sure that calling a method that takes &mut self
        // does not produce a compile error here
        ks.set_cursor(0);
    }

    #[test]
    fn can_iterate_simple_keyset() {
        let names = ["user/test/key1", "user/test/key2", "user/test/key3"];
        let values = ["value1", "value2", "value3"];

        let mut ks = KeySet::with_capacity(3);

        ks.append_all(vec![
            KeyBuilder::<StringKey>::new(names[0])
                .value(values[0])
                .build(),
            KeyBuilder::<StringKey>::new(names[1])
                .value(values[1])
                .build(),
            KeyBuilder::<StringKey>::new(names[2])
                .value(values[2])
                .build(),
        ])
        .unwrap();
        ks.rewind();

        let mut did_iterate = false;
        for (i, key) in ks.enumerate() {
            did_iterate = true;
            assert_eq!(key.get_value(), values[i]);
            assert_eq!(key.get_name(), names[i]);
        }
        assert!(did_iterate);
    }

    fn setup_keyset() -> KeySet {
        let names = ["system/test/key", "user/test/key"];
        let values = ["value1", "value3"];

        let mut ks = KeySet::with_capacity(3);

        ks.append_all(vec![
            KeyBuilder::<StringKey>::new(names[0])
                .value(values[0])
                .build(),
            KeyBuilder::<StringKey>::new(names[1])
                .value(values[1])
                .build(),
            // KeyBuilder::<StringKey>::new(names[2])
            //     .value(values[2])
            //     .build(),
        ])
        .unwrap();
        ks
    }

    #[test]
    fn can_lookup_key_with_none_option() {
        let mut ks = setup_keyset();
        let lookup_key = StringKey::new("/test/key").unwrap();
        println!("Lookup_key is {:?}", lookup_key);
        let ret_val = ks.lookup(lookup_key, LookupOption::KDB_O_NONE);
        assert_eq!(ret_val.unwrap().get_name(), "user/test/key");
        assert_eq!(ks.get_size(), 2);
        assert_eq!(ks.tail().unwrap().get_name(), "user/test/key");
    }

    #[test]
    fn can_lookup_key_with_del_option() {
        let mut ks = setup_keyset();
        let lookup_key = StringKey::new("/test/key").unwrap();
        let key = ks.lookup(lookup_key, LookupOption::KDB_O_DEL);
        assert_eq!(key.unwrap().get_name(), "user/test/key");
        assert_eq!(ks.get_size(), 2);
        assert_eq!(ks.head().unwrap().get_name(), "system/test/key");
    }

    #[test]
    fn can_lookup_and_duplicate_key() {
        // Make sure that a duplicate of a key that is from a keyset
        // can be used after the KeySet has been freed
        let key;
        {
            let lookup_key = StringKey::new("/test/key").unwrap();
            let mut ks = setup_keyset();
            key = ks
                .lookup(lookup_key, LookupOption::KDB_O_DEL)
                .unwrap()
                .to_owned();
            assert_eq!(ks.get_size(), 2);
            assert_eq!(ks.head().unwrap().get_name(), "system/test/key");
        }
        assert_eq!(key.get_name(), "user/test/key");
    }

}
<|endoftext|>


<commit_before>//! Socks5 protocol definition ([RFC1928](https://tools.ietf.org/rfc/rfc1928.txt))

use std::io;
use std::str;
use std::mem;
use std::rc::Rc;
use std::net::{self, SocketAddr};

use futures::{Poll, Future, Async};
use tokio_core::net::{TcpStream, TcpStreamNew};
use tokio_core::reactor::Handle;

use buffer::{BufRange, SharedBuf};

const VERSION: u8 = 0x05;
const AUTH_METHOD_NONE: u8 = 0x00;
const CMD_TCP_CONNECT: u8 = 0x01;

pub const ADDR_TYPE_IPV4: u8 = 0x01;
pub const ADDR_TYPE_IPV6: u8 = 0x04;
pub const ADDR_TYPE_DOMAIN_NAME: u8 = 0x03;

const REPLY_SUCCEEDED: u8 = 0x00;
const REPLY_GENERAL_FAILURE: u8 = 0x01;
const REPLY_CONNECTION_REFUSED: u8 = 0x05;

// +----+-----+-------+------+----------+----------+
// |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
// +----+-----+-------+------+----------+----------+
// | 1  |  1  | X'00' |  1   | Variable |    2     |
// +----+-----+-------+------+----------+----------+

const MAX_REQ_LEN: usize = 1 + 1 + 1 + 1 + 1 + 255 + 2;

pub struct ReqAddr {
    len: usize,
    bytes: [u8; MAX_REQ_LEN],
}

impl ReqAddr {
    pub fn new(bytes: &[u8]) -> ReqAddr {
        let len = bytes.len();
        assert!(len < MAX_REQ_LEN);

        let mut buf = [0u8; MAX_REQ_LEN];
        buf[..len].copy_from_slice(bytes);
        ReqAddr {
            len: len,
            bytes: buf,
        }
    }

    pub fn get(&self) -> io::Result<String> {
        let atyp = self.bytes[0];
        let buf = &self.bytes[1..self.len];

        match atyp {
            ADDR_TYPE_IPV4 => {
                let addr = net::Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]);
                let port = ((buf[4] as u16) << 8) | (buf[5] as u16);
                let addr = net::SocketAddrV4::new(addr, port);
                Ok(format!("{}", SocketAddr::V4(addr)))
            }
            ADDR_TYPE_IPV6 => {
                let a = ((buf[0] as u16) << 8) | (buf[1] as u16);
                let b = ((buf[2] as u16) << 8) | (buf[3] as u16);
                let c = ((buf[4] as u16) << 8) | (buf[5] as u16);
                let d = ((buf[6] as u16) << 8) | (buf[7] as u16);
                let e = ((buf[8] as u16) << 8) | (buf[9] as u16);
                let f = ((buf[10] as u16) << 8) | (buf[11] as u16);
                let g = ((buf[12] as u16) << 8) | (buf[13] as u16);
                let h = ((buf[14] as u16) << 8) | (buf[15] as u16);
                let addr = net::Ipv6Addr::new(a, b, c, d, e, f, g, h);
                let port = ((buf[16] as u16) << 8) | (buf[17] as u16);
                let addr = net::SocketAddrV6::new(addr, port, 0, 0);
                Ok(format!("{}", SocketAddr::V6(addr)))
            }
            ADDR_TYPE_DOMAIN_NAME => {
                let len = buf[0] as usize;
                let domain = str::from_utf8(&buf[1..len + 1]).map_err(|e| {
                    other(&format!("domain not valid utf-8, {}", e))
                })?;
                let pos = buf.len() - 2;
                let port = ((buf[pos] as u16) << 8) | (buf[pos + 1] as u16);
                Ok(format!("{}:{}", domain, port))
            }
            _ => unreachable!(),
        }
    }
}

// BND.ADDR use IP V4 or V6, 16 is ipv6 bytes
pub const REPLY_LEN: usize = 1 + 1 + 1 + 1 + 16 + 2;

pub struct Reply {
    len: usize,
    buffer: [u8; REPLY_LEN],
}

impl Reply {
    pub fn new(addr: SocketAddr) -> Reply {
        let mut buf = [0u8; REPLY_LEN];

        // VER - protocol version
        buf[0] = VERSION;

        // RSV - reserved
        buf[2] = 0;

        let pos = match addr {
            SocketAddr::V4(ref a) => {
                buf[3] = ADDR_TYPE_IPV4;
                buf[4..8].copy_from_slice(&a.ip().octets()[..]);
                8
            }
            SocketAddr::V6(ref a) => {
                buf[3] = ADDR_TYPE_IPV6;
                let mut pos = 4;
                for &segment in a.ip().segments().iter() {
                    buf[pos] = (segment >> 8) as u8;
                    buf[pos + 1] = segment as u8;
                    pos += 2;
                }
                pos
            }
        };
        buf[pos] = (addr.port() >> 8) as u8;
        buf[pos + 1] = addr.port() as u8;

        Reply {
            len: pos + 2,
            buffer: buf,
        }
    }

    fn get(&self, rtype: u8, out: &mut [u8]) -> usize {
        assert!(out.len() >= self.len);
        out[..self.len].copy_from_slice(&self.buffer[..self.len]);
        // REP
        out[1] = rtype;

        self.len
    }
}

pub struct Handshake {
    handle: Handle,
    client: Rc<TcpStream>,
    reply: Rc<Reply>,
    remote_addr: SocketAddr,

    buf: SharedBuf,
    state: HandshakeState,

    connect: Option<TcpStreamNew>,
    remote: io::Result<TcpStream>,
    reqaddr: Option<ReqAddr>,
}

impl Handshake {
    pub fn new(
        handle: Handle,
        reply: Rc<Reply>,
        client: Rc<TcpStream>,
        remote: SocketAddr,
    ) -> Handshake {
        Handshake {
            handle: handle,
            client: client,
            reply: reply,
            remote_addr: remote,

            buf: SharedBuf::new(MAX_REQ_LEN),
            state: HandshakeState::AuthVersion(BufRange { start: 0, end: 1 }),

            connect: None,
            remote: Err(not_connected()),
            reqaddr: None,
        }
    }
}

#[derive(Copy, Clone, Debug)]
enum HandshakeState {
    AuthVersion(BufRange),
    AuthNmethod(BufRange),
    AuthMethods(BufRange),
    AuthEnd(BufRange),

    ReqVersion(BufRange),
    ReqHeader(BufRange),
    ReqData(BufRange),

    ConnectServer,

    ReqEnd(BufRange),

    Done,

    Over,
}

impl Future for Handshake {
    type Item = TcpStream;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<TcpStream, io::Error> {
        loop {
            match self.state {
                HandshakeState::AuthVersion(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    if buf[0] != VERSION {
                        return Err(other("only support socks version 5"));
                    }
                    self.state = HandshakeState::AuthNmethod(BufRange {
                        start: range.end,
                        end: range.end + 1,
                    });
                }
                HandshakeState::AuthNmethod(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    self.state = HandshakeState::AuthMethods(BufRange {
                        start: range.end,
                        end: range.end + buf[0] as usize,
                    });
                }
                HandshakeState::AuthMethods(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    {
                        let buf = self.buf.get_ref_range(range);
                        if !buf.contains(&AUTH_METHOD_NONE) {
                            return Err(other("no supported method given"));
                        }
                    }

                    let range = BufRange { start: 0, end: 2 };
                    let buf = self.buf.get_mut_range(range);
                    buf[0] = VERSION;
                    buf[1] = AUTH_METHOD_NONE;
                    self.state = HandshakeState::AuthEnd(range)
                }
                HandshakeState::AuthEnd(range) => {
                    try_ready!(self.buf.write_exact(&mut (&*self.client), range));
                    self.state = HandshakeState::ReqVersion(BufRange { start: 0, end: 1 })
                }
                HandshakeState::ReqVersion(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    if buf[0] != VERSION {
                        return Err(other("only support socks version 5"));
                    }
                    self.state = HandshakeState::ReqHeader(BufRange {
                        start: range.end,
                        // CMD +  RSV  + ATYP + 1
                        end: range.end + 4,
                    });
                }
                HandshakeState::ReqHeader(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    if buf[0] != CMD_TCP_CONNECT {
                        return Err(other("only support tcp connect command"));
                    }
                    let need = match buf[2] {
                        // 4 bytes ipv4 and 2 bytes port, and already read more 1 bytes
                        ADDR_TYPE_IPV4 => 4 + 2 - 1,
                        // 16 bytes ipv6 and 2 bytes port
                        ADDR_TYPE_IPV6 => 16 + 2 - 1,
                        ADDR_TYPE_DOMAIN_NAME => (buf[3] as usize) + 2,
                        n => {
                            return Err(other(&format!("unknown ATYP received: {}", n)));
                        }
                    };
                    self.state = HandshakeState::ReqData(BufRange {
                        start: range.end,
                        end: range.end + need,
                    });
                }
                HandshakeState::ReqData(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    // get addr info
                    let range = BufRange {
                        // VER - CMD -  RSV
                        start: 1 + 1 + 1,
                        end: range.end,
                    };

                    let reqaddr = ReqAddr::new(self.buf.get_ref_range(range));
                    let addr = reqaddr.get()?;
                    info!("request {}", addr);

                    self.reqaddr = Some(reqaddr);
                    self.connect = Some(TcpStream::connect(&self.remote_addr, &self.handle));
                    self.state = HandshakeState::ConnectServer;
                }
                HandshakeState::ConnectServer => {
                    // now, connect remote server
                    let rtype = match self.connect {
                        Some(ref mut s) => {
                            match s.poll() {
                                Ok(Async::Ready(conn)) => {
                                    self.remote = Ok(conn);
                                    REPLY_SUCCEEDED
                                }
                                Ok(Async::NotReady) => return Ok(Async::NotReady),
                                Err(e) => {
                                    let kind = e.kind();
                                    self.remote = Err(e);
                                    if kind == io::ErrorKind::ConnectionRefused {
                                        REPLY_CONNECTION_REFUSED
                                    } else {
                                        REPLY_GENERAL_FAILURE
                                    }
                                }
                            }
                        }
                        None => panic!("connect server on illegal state"),
                    };

                    let reply_len = self.reply.get(rtype, self.buf.get_mut());
                    self.state = HandshakeState::ReqEnd(BufRange {
                        start: 0,
                        end: reply_len,
                    })
                }
                HandshakeState::ReqEnd(range) => {
                    try_ready!(self.buf.write_exact(&mut (&*self.client), range));
                    self.state = HandshakeState::Done;
                }
                HandshakeState::Done => {
                    self.state = HandshakeState::Over;
                    let remote = mem::replace(&mut self.remote, Err(not_connected()));
                    match remote {
                        Ok(conn) => return Ok(Async::Ready(conn)),
                        Err(e) => {
                            return Err(other(
                                &format!("connect remote {}, {}", self.remote_addr, e),
                            ))
                        }
                    }
                }
                HandshakeState::Over => panic!("poll a done future"),
            };
        }
    }
}

fn other(desc: &str) -> io::Error {
    io::Error::new(io::ErrorKind::Other, desc)
}

fn not_connected() -> io::Error {
    io::Error::new(io::ErrorKind::NotConnected, "not connected")
}
<commit_msg>handshake return remote conn and req addr<commit_after>//! Socks5 protocol definition ([RFC1928](https://tools.ietf.org/rfc/rfc1928.txt))

use std::io;
use std::str;
use std::mem;
use std::rc::Rc;
use std::net::{self, SocketAddr};

use futures::{Poll, Future, Async};
use tokio_core::net::{TcpStream, TcpStreamNew};
use tokio_core::reactor::Handle;

use buffer::{BufRange, SharedBuf};

const VERSION: u8 = 0x05;
const AUTH_METHOD_NONE: u8 = 0x00;
const CMD_TCP_CONNECT: u8 = 0x01;

pub const ADDR_TYPE_IPV4: u8 = 0x01;
pub const ADDR_TYPE_IPV6: u8 = 0x04;
pub const ADDR_TYPE_DOMAIN_NAME: u8 = 0x03;

const REPLY_SUCCEEDED: u8 = 0x00;
const REPLY_GENERAL_FAILURE: u8 = 0x01;
const REPLY_CONNECTION_REFUSED: u8 = 0x05;

// +----+-----+-------+------+----------+----------+
// |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
// +----+-----+-------+------+----------+----------+
// | 1  |  1  | X'00' |  1   | Variable |    2     |
// +----+-----+-------+------+----------+----------+

const MAX_REQ_LEN: usize = 1 + 1 + 1 + 1 + 1 + 255 + 2;

pub struct ReqAddr {
    len: usize,
    bytes: [u8; MAX_REQ_LEN],
}

impl ReqAddr {
    pub fn new(bytes: &[u8]) -> ReqAddr {
        let len = bytes.len();
        assert!(len < MAX_REQ_LEN);

        let mut buf = [0u8; MAX_REQ_LEN];
        buf[..len].copy_from_slice(bytes);
        ReqAddr {
            len: len,
            bytes: buf,
        }
    }

    pub fn get(&self) -> io::Result<String> {
        let atyp = self.bytes[0];
        let buf = &self.bytes[1..self.len];

        match atyp {
            ADDR_TYPE_IPV4 => {
                let addr = net::Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]);
                let port = ((buf[4] as u16) << 8) | (buf[5] as u16);
                let addr = net::SocketAddrV4::new(addr, port);
                Ok(format!("{}", SocketAddr::V4(addr)))
            }
            ADDR_TYPE_IPV6 => {
                let a = ((buf[0] as u16) << 8) | (buf[1] as u16);
                let b = ((buf[2] as u16) << 8) | (buf[3] as u16);
                let c = ((buf[4] as u16) << 8) | (buf[5] as u16);
                let d = ((buf[6] as u16) << 8) | (buf[7] as u16);
                let e = ((buf[8] as u16) << 8) | (buf[9] as u16);
                let f = ((buf[10] as u16) << 8) | (buf[11] as u16);
                let g = ((buf[12] as u16) << 8) | (buf[13] as u16);
                let h = ((buf[14] as u16) << 8) | (buf[15] as u16);
                let addr = net::Ipv6Addr::new(a, b, c, d, e, f, g, h);
                let port = ((buf[16] as u16) << 8) | (buf[17] as u16);
                let addr = net::SocketAddrV6::new(addr, port, 0, 0);
                Ok(format!("{}", SocketAddr::V6(addr)))
            }
            ADDR_TYPE_DOMAIN_NAME => {
                let len = buf[0] as usize;
                let domain = str::from_utf8(&buf[1..len + 1]).map_err(|e| {
                    other(&format!("domain not valid utf-8, {}", e))
                })?;
                let pos = buf.len() - 2;
                let port = ((buf[pos] as u16) << 8) | (buf[pos + 1] as u16);
                Ok(format!("{}:{}", domain, port))
            }
            _ => unreachable!(),
        }
    }
}

// BND.ADDR use IP V4 or V6, 16 is ipv6 bytes
pub const REPLY_LEN: usize = 1 + 1 + 1 + 1 + 16 + 2;

pub struct Reply {
    len: usize,
    buffer: [u8; REPLY_LEN],
}

impl Reply {
    pub fn new(addr: SocketAddr) -> Reply {
        let mut buf = [0u8; REPLY_LEN];

        // VER - protocol version
        buf[0] = VERSION;

        // RSV - reserved
        buf[2] = 0;

        let pos = match addr {
            SocketAddr::V4(ref a) => {
                buf[3] = ADDR_TYPE_IPV4;
                buf[4..8].copy_from_slice(&a.ip().octets()[..]);
                8
            }
            SocketAddr::V6(ref a) => {
                buf[3] = ADDR_TYPE_IPV6;
                let mut pos = 4;
                for &segment in a.ip().segments().iter() {
                    buf[pos] = (segment >> 8) as u8;
                    buf[pos + 1] = segment as u8;
                    pos += 2;
                }
                pos
            }
        };
        buf[pos] = (addr.port() >> 8) as u8;
        buf[pos + 1] = addr.port() as u8;

        Reply {
            len: pos + 2,
            buffer: buf,
        }
    }

    fn get(&self, rtype: u8, out: &mut [u8]) -> usize {
        assert!(out.len() >= self.len);
        out[..self.len].copy_from_slice(&self.buffer[..self.len]);
        // REP
        out[1] = rtype;

        self.len
    }
}

pub struct Handshake {
    handle: Handle,
    client: Rc<TcpStream>,
    reply: Rc<Reply>,
    remote_addr: SocketAddr,

    buf: SharedBuf,
    state: HandshakeState,

    connect: Option<TcpStreamNew>,
    remote: io::Result<TcpStream>,
    reqaddr: Option<ReqAddr>,
}

impl Handshake {
    pub fn new(
        handle: Handle,
        reply: Rc<Reply>,
        client: Rc<TcpStream>,
        remote: SocketAddr,
    ) -> Handshake {
        Handshake {
            handle: handle,
            client: client,
            reply: reply,
            remote_addr: remote,

            buf: SharedBuf::new(MAX_REQ_LEN),
            state: HandshakeState::AuthVersion(BufRange { start: 0, end: 1 }),

            connect: None,
            remote: Err(not_connected()),
            reqaddr: None,
        }
    }
}

#[derive(Copy, Clone, Debug)]
enum HandshakeState {
    AuthVersion(BufRange),
    AuthNmethod(BufRange),
    AuthMethods(BufRange),
    AuthEnd(BufRange),

    ReqVersion(BufRange),
    ReqHeader(BufRange),
    ReqData(BufRange),

    ConnectServer,

    ReqEnd(BufRange),

    Done,

    Over,
}

impl Future for Handshake {
    type Item = (TcpStream, ReqAddr);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(TcpStream, ReqAddr), io::Error> {
        loop {
            match self.state {
                HandshakeState::AuthVersion(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    if buf[0] != VERSION {
                        return Err(other("only support socks version 5"));
                    }
                    self.state = HandshakeState::AuthNmethod(BufRange {
                        start: range.end,
                        end: range.end + 1,
                    });
                }
                HandshakeState::AuthNmethod(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    self.state = HandshakeState::AuthMethods(BufRange {
                        start: range.end,
                        end: range.end + buf[0] as usize,
                    });
                }
                HandshakeState::AuthMethods(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    {
                        let buf = self.buf.get_ref_range(range);
                        if !buf.contains(&AUTH_METHOD_NONE) {
                            return Err(other("no supported auth method given"));
                        }
                    }

                    let range = BufRange { start: 0, end: 2 };
                    let buf = self.buf.get_mut_range(range);
                    buf[0] = VERSION;
                    buf[1] = AUTH_METHOD_NONE;
                    self.state = HandshakeState::AuthEnd(range)
                }
                HandshakeState::AuthEnd(range) => {
                    try_ready!(self.buf.write_exact(&mut (&*self.client), range));
                    self.state = HandshakeState::ReqVersion(BufRange { start: 0, end: 1 })
                }
                HandshakeState::ReqVersion(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    if buf[0] != VERSION {
                        return Err(other("only support socks version 5"));
                    }
                    self.state = HandshakeState::ReqHeader(BufRange {
                        start: range.end,
                        // CMD +  RSV  + ATYP + 1
                        end: range.end + 4,
                    });
                }
                HandshakeState::ReqHeader(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    let buf = self.buf.get_ref_range(range);
                    if buf[0] != CMD_TCP_CONNECT {
                        return Err(other("only support tcp connect command"));
                    }
                    let need = match buf[2] {
                        // 4 bytes ipv4 and 2 bytes port, and already read more 1 bytes
                        ADDR_TYPE_IPV4 => 4 + 2 - 1,
                        // 16 bytes ipv6 and 2 bytes port
                        ADDR_TYPE_IPV6 => 16 + 2 - 1,
                        ADDR_TYPE_DOMAIN_NAME => (buf[3] as usize) + 2,
                        n => {
                            return Err(other(&format!("unknown ATYP received: {}", n)));
                        }
                    };
                    self.state = HandshakeState::ReqData(BufRange {
                        start: range.end,
                        end: range.end + need,
                    });
                }
                HandshakeState::ReqData(range) => {
                    let range = try_ready!(self.buf.read_exact(&mut (&*self.client), range));
                    // get addr info
                    let range = BufRange {
                        // VER - CMD -  RSV
                        start: 1 + 1 + 1,
                        end: range.end,
                    };

                    let reqaddr = ReqAddr::new(self.buf.get_ref_range(range));
                    let addr = reqaddr.get()?;
                    info!("request {}", addr);

                    self.reqaddr = Some(reqaddr);
                    self.connect = Some(TcpStream::connect(&self.remote_addr, &self.handle));
                    self.state = HandshakeState::ConnectServer;
                }
                HandshakeState::ConnectServer => {
                    // now, connect remote server
                    let rtype = match self.connect {
                        Some(ref mut s) => {
                            match s.poll() {
                                Ok(Async::Ready(conn)) => {
                                    self.remote = Ok(conn);
                                    REPLY_SUCCEEDED
                                }
                                Ok(Async::NotReady) => return Ok(Async::NotReady),
                                Err(e) => {
                                    let kind = e.kind();
                                    self.remote = Err(e);
                                    if kind == io::ErrorKind::ConnectionRefused {
                                        REPLY_CONNECTION_REFUSED
                                    } else {
                                        REPLY_GENERAL_FAILURE
                                    }
                                }
                            }
                        }
                        None => panic!("connect server on illegal state"),
                    };

                    let reply_len = self.reply.get(rtype, self.buf.get_mut());
                    self.state = HandshakeState::ReqEnd(BufRange {
                        start: 0,
                        end: reply_len,
                    })
                }
                HandshakeState::ReqEnd(range) => {
                    try_ready!(self.buf.write_exact(&mut (&*self.client), range));
                    self.state = HandshakeState::Done;
                }
                HandshakeState::Done => {
                    self.state = HandshakeState::Over;
                    let remote = mem::replace(&mut self.remote, Err(not_connected()));
                    let reqaddr = mem::replace(&mut self.reqaddr, None);
                    match remote {
                        Ok(conn) => return Ok(Async::Ready((conn, reqaddr.unwrap()))),
                        Err(e) => {
                            return Err(other(
                                &format!("connect remote {}, {}", self.remote_addr, e),
                            ))
                        }
                    }
                }
                HandshakeState::Over => panic!("poll a done future"),
            };
        }
    }
}

fn other(desc: &str) -> io::Error {
    io::Error::new(io::ErrorKind::Other, desc)
}

fn not_connected() -> io::Error {
    io::Error::new(io::ErrorKind::NotConnected, "not connected")
}
<|endoftext|>


<commit_before>use std::cell::RefCell;

use crate::shell::CONSOLE;
use crate::{prelude::*, utils::SelectionMode as SelMode};

use super::behaviors::{MouseBehavior, SelectionBehavior};

/// The `ComboBoxState` is used to manipulate the position of the thumb of the slider widget.
#[derive(Default, AsAny)]
pub struct ComboBoxState {
    builder: RefCell<Vec<WidgetBuildContext>>,
    selected_item_builder: WidgetBuildContext,
}

impl State for ComboBoxState {
    // fn init(&mut self, _: Registry)
}

widget!(
    /// The `ComboBox` represents an selection widget with a drop-down list.
    ///
    /// **CSS element:** `ComboBox`
    ComboBox<ComboBoxState>: MouseHandler, ChangedHandler {
        /// Sets or shares the background property.
        background: Brush,

        /// Sets or shares the border radius property.
        border_radius: f64,

        /// Sets or shares the border thickness property.
        border_width: Thickness,

        /// Sets or shares the border brush property.
        border_brush: Brush,

        /// Sets or shares the foreground property.
        foreground: Brush,

        /// Sets or share the font size property.
        font_size: f64,

        /// Sets or shares the font property.
        font: String,

        /// Sets or shared the count.
        count: usize,

        /// Sets or shares the css selector property.
        selector: Selector,

        /// Sets or shares the selected index.
        selected_index: u32,

        /// Sets or shares selected entity.
        selected_entity: u32,

        /// Sets or shares the padding property.
        padding: Thickness,

        /// Sets or shares the pressed property.
        pressed: bool,

        /// Sets or shares the flag if the drop down is open.
        selected: bool
    }
);

impl ComboBox {
    pub fn from_items_builder<F: Fn(&mut BuildContext, usize) -> Entity + 'static>(
        builder: F,
    ) -> Self {
        let mut combo_box = ComboBox::create();
        combo_box
            .state_mut()
            .builder
            .borrow_mut()
            .push(Some(Box::new(builder)));
        combo_box
    }

    pub fn selected_item_builder<F: Fn(&mut BuildContext, usize) -> Entity + 'static>(mut self, builder: F) -> Self {
        self.state_mut().selected_item_builder = Some(Box::new(builder));
        self
    }
}

impl Template for ComboBox {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        let container = Container::create()
            .background(id)
            .border_radius(id)
            .border_width(id)
            .border_brush(id)
            .padding(id)
            .build(ctx);

        let mut list_view = ListView::create().count(id).selection_mode(SelMode::Single);

        // Workaround to move builder out of state
        if let Some(builder) = self.state().builder.borrow_mut().pop() {
            if let Some(builder) = builder {
                list_view = list_view.items_builder(builder);
            }
        }

        let list_view = list_view.build(ctx);

        let popup = Popup::create()
            .height(200.0)
            .open(("selected", id))
            .child(list_view)
            .target(container.0)
            .build(ctx);

        let result = ctx.append_child_to_overlay(popup);

        if let Err(e) = result {
            CONSOLE.log(format!("{:?}", e));
        }
        self.name("ComboBox")
            .selector("combo_box")
            .height(32.0)
            .min_width(80.0)
            .selected(false)
            .child(
                MouseBehavior::create()
                    .pressed(id)
                    .enabled(id)
                    .selector(id)
                    .child(
                        SelectionBehavior::create()
                            .selected(id)
                            .enabled(id)
                            .selector(id)
                            .parent(id.0)
                            .child(container)
                            .build(ctx),
                    )
                    .build(ctx),
            )
    }
}
<commit_msg>Docu update.<commit_after>use std::cell::RefCell;

use crate::shell::CONSOLE;
use crate::{prelude::*, utils::SelectionMode as SelMode};

use super::behaviors::{MouseBehavior, SelectionBehavior};

/// The `ComboBoxState` is used to manipulate the position of the thumb of the slider widget.
#[derive(Default, AsAny)]
pub struct ComboBoxState {
    builder: RefCell<Vec<WidgetBuildContext>>,
    selected_item_builder: WidgetBuildContext,
}

impl State for ComboBoxState {
    // fn init(&mut self, _: Registry)
}

widget!(
    /// The `ComboBox` represents an selection widget with a drop-down list.
    ///
    /// **CSS element:** `ComboBox`
    ComboBox<ComboBoxState>: MouseHandler, ChangedHandler {
        /// Sets or shares the background property.
        background: Brush,

        /// Sets or shares the border radius property.
        border_radius: f64,

        /// Sets or shares the border thickness property.
        border_width: Thickness,

        /// Sets or shares the border brush property.
        border_brush: Brush,

        /// Sets or shares the foreground property.
        foreground: Brush,

        /// Sets or share the font size property.
        font_size: f64,

        /// Sets or shares the font property.
        font: String,

        /// Sets or shared the count.
        count: usize,

        /// Sets or shares the css selector property.
        selector: Selector,

        /// Sets or shares the selected index.
        selected_index: u32,

        /// Sets or shares selected entity.
        selected_entity: u32,

        /// Sets or shares the padding property.
        padding: Thickness,

        /// Sets or shares the pressed property.
        pressed: bool,

        /// Sets or shares the flag if the drop down is open.
        selected: bool
    }
);

impl ComboBox {
    /// Creates a ComboBox and add the builder for the list items inside of the ComboBox.
    pub fn from_items_builder<F: Fn(&mut BuildContext, usize) -> Entity + 'static>(
        builder: F,
    ) -> Self {
        let mut combo_box = ComboBox::create();
        combo_box
            .state_mut()
            .builder
            .borrow_mut()
            .push(Some(Box::new(builder)));
        combo_box
    }

    /// Define the builder function for the selected item inside of the header of the ComboBox.
    pub fn selected_item_builder<F: Fn(&mut BuildContext, usize) -> Entity + 'static>(mut self, builder: F) -> Self {
        self.state_mut().selected_item_builder = Some(Box::new(builder));
        self
    }
}

impl Template for ComboBox {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        let container = Container::create()
            .background(id)
            .border_radius(id)
            .border_width(id)
            .border_brush(id)
            .padding(id)
            .build(ctx);

        let mut list_view = ListView::create().count(id).selection_mode(SelMode::Single);

        // Workaround to move builder out of state
        if let Some(builder) = self.state().builder.borrow_mut().pop() {
            if let Some(builder) = builder {
                list_view = list_view.items_builder(builder);
            }
        }

        let list_view = list_view.build(ctx);

        let popup = Popup::create()
            .height(200.0)
            .open(("selected", id))
            .child(list_view)
            .target(container.0)
            .build(ctx);

        let result = ctx.append_child_to_overlay(popup);

        if let Err(e) = result {
            CONSOLE.log(format!("{:?}", e));
        }
        self.name("ComboBox")
            .selector("combo_box")
            .height(32.0)
            .min_width(80.0)
            .selected(false)
            .child(
                MouseBehavior::create()
                    .pressed(id)
                    .enabled(id)
                    .selector(id)
                    .child(
                        SelectionBehavior::create()
                            .selected(id)
                            .enabled(id)
                            .selector(id)
                            .parent(id.0)
                            .child(container)
                            .build(ctx),
                    )
                    .build(ctx),
            )
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::collections::HashMap;

use uuid::Uuid;

use graphics::{ self, Graphics, ImageSize };
use graphics::math::{ Scalar, Matrix2d, Vec2d, Vec3d };

/// A sprite is a texture with some properties.
pub struct Sprite<I: ImageSize> {
    id: Uuid,

    visible: bool,

    anchor: Vec2d,

    position: Vec2d,
    rotation: Scalar,
    scale: Vec2d,
    color: Vec3d,

    flip_x: bool,
    flip_y: bool,

    opacity: f32,

    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,

    texture: Rc<I>,
}

impl<I: ImageSize> Sprite<I> {
    /// Crate sprite from a texture
    pub fn from_texture(texture: Rc<I>) -> Sprite<I> {
        Sprite {
            id: Uuid::new_v4(),

            visible: true,

            anchor: [0.5, 0.5],

            position: [0.0, 0.0],
            rotation: 0.0,
            scale: [1.0, 1.0],
            color: [0.0,1.0,0.0],

            flip_x: false,
            flip_y: false,

            opacity: 1.0,

            texture: texture,

            children: Vec::new(),
            children_index: HashMap::new(),
        }
    }

    /// Get the sprite's id
    #[inline(always)]
    pub fn id(&self) -> Uuid {
        self.id.clone()
    }

    /// Whether or not the sprite is visible
    pub fn visible(&self) -> bool {
        self.visible
    }

    /// Set the sprite's visibility
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
    }

    /// Get the sprite's anchor point
    ///
    /// The value is normalized. Default value is [0.5, 0.5] (the center of texture)
    #[inline(always)]
    pub fn anchor(&self) -> (Scalar, Scalar) {
        (self.anchor[0], self.anchor[1])
    }

    /// Set the sprite's anchor point
    #[inline(always)]
    pub fn set_anchor(&mut self, x: Scalar, y: Scalar) {
        self.anchor = [x, y];
    }

    /// Get the sprite's position
    #[inline(always)]
    pub fn position(&self) -> (Scalar, Scalar) {
        (self.position[0], self.position[1])
    }

    /// Set the sprite's position
    #[inline(always)]
    pub fn set_position(&mut self, x: Scalar, y: Scalar) {
        self.position = [x, y];
    }

    /// Set the sprite's draw color (tint)
    #[inline(always)]
    pub fn set_color(&mut self, r: f64, g: f64, b: f64) {
        self.color = [r, g, b];
    }

    /// get the sprite's color.s
    #[inline(always)]
    pub fn color(&self) -> (f64, f64, f64) {
        (self.color[0], self.color[1], self.color[2])
    }

    /// Get the sprite's rotation (in degree)
    #[inline(always)]
    pub fn rotation(&self) -> Scalar {
        self.rotation
    }

    /// Set the sprite's rotation (in degree)
    #[inline(always)]
    pub fn set_rotation(&mut self, deg: Scalar) {
        self.rotation = deg;
    }

    /// Get the sprite's scale
    #[inline(always)]
    pub fn scale(&self) -> (Scalar, Scalar) {
        (self.scale[0], self.scale[1])
    }

    /// Set the sprite's scale
    #[inline(always)]
    pub fn set_scale(&mut self, sx: Scalar, sy: Scalar) {
        self.scale = [sx, sy];
    }

    /// Whether or not the sprite is flipped horizontally.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.x *= -1;
    #[inline(always)]
    pub fn flip_x(&self) -> bool {
        self.flip_x
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_x(&mut self, flip_x: bool) {
        self.flip_x = flip_x;
    }

    /// Whether or not the sprite is flipped vertically.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.y *= -1;
    #[inline(always)]
    pub fn flip_y(&self) -> bool {
        self.flip_y
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_y(&mut self, flip_y: bool) {
        self.flip_y = flip_y;
    }

    /// Get the sprite's opacity
    #[inline(always)]
    pub fn opacity(&self) -> f32 {
        self.opacity
    }

    /// Set the sprite's opacity
    #[inline(always)]
    pub fn set_opacity(&mut self, opacity: f32) {
        self.opacity = opacity;
    }

    /// Get the sprite's texture
    #[inline(always)]
    pub fn texture(&self) -> &Rc<I> {
        &self.texture
    }

    /// Set the sprite's texture
    #[inline(always)]
    pub fn set_texture(&mut self, texture: Rc<I>) {
        self.texture = texture;
    }

    /// Add a sprite as the child of this sprite, return the added sprite's id.
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    /// Remove the child by `id` from this sprite's children or grandchild
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Get the sprite's children
    #[inline(always)]
    pub fn children(&self) -> &Vec<Sprite<I>> {
        &self.children
    }

    /// Draw this sprite and its children
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        use graphics::*;

        if !self.visible {
            return;
        }

        let (w, h) = self.texture.get_size();
        let w = w as f64;
        let h = h as f64;
        let anchor = [self.anchor[0] * w, self.anchor[1] * h];

        let transformed = t.trans(self.position[0], self.position[1])
                           .rot_deg(self.rotation)
                           .scale(self.scale[0], self.scale[1]);

        let mut model = transformed;

        if self.flip_x {
            model = model.trans(w - 2.0 * anchor[0], 0.0).flip_h();
        }

        if self.flip_y {
            model = model.trans(0.0, h - 2.0 * anchor[1]).flip_v();
        }

        let draw_state = default_draw_state();

        // for debug: bounding_box
        //model.rgb(1.0, 0.0, 0.0).draw(b);

        graphics::Image::new()
            .color([self.color[0] as f32, self.color[1] as f32, self.color[2] as f32, self.opacity])
            .rect([-anchor[0], -anchor[1], w, h])
            .draw(&*self.texture, draw_state, model, b);

        // for debug: anchor point
        //c.trans(self.position[0], self.position[1]).rect(-5.0, -5.0, 10.0, 10.0).rgb(0.0, 0.0, 1.0).draw(b);

        for child in self.children.iter() {
            child.draw(transformed, b);
        }
    }

    /// Get the sprite's bounding box
    pub fn bounding_box(&self) -> graphics::types::Rectangle {
        let (w, h) = self.texture.get_size();
        let w = w as f64 * self.scale[0];
        let h = h as f64 * self.scale[1];

        [
            self.position[0] - self.anchor[0] * w,
            self.position[1] - self.anchor[1] * h,
            w,
            h
        ]
    }
}
<commit_msg>Removing hardcoded color testing<commit_after>use std::rc::Rc;
use std::collections::HashMap;

use uuid::Uuid;

use graphics::{ self, Graphics, ImageSize };
use graphics::math::{ Scalar, Matrix2d, Vec2d, Vec3d };

/// A sprite is a texture with some properties.
pub struct Sprite<I: ImageSize> {
    id: Uuid,

    visible: bool,

    anchor: Vec2d,

    position: Vec2d,
    rotation: Scalar,
    scale: Vec2d,
    color: Vec3d,

    flip_x: bool,
    flip_y: bool,

    opacity: f32,

    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,

    texture: Rc<I>,
}

impl<I: ImageSize> Sprite<I> {
    /// Crate sprite from a texture
    pub fn from_texture(texture: Rc<I>) -> Sprite<I> {
        Sprite {
            id: Uuid::new_v4(),

            visible: true,

            anchor: [0.5, 0.5],

            position: [0.0, 0.0],
            rotation: 0.0,
            scale: [1.0, 1.0],
            color: [1.0,1.0,1.0],

            flip_x: false,
            flip_y: false,

            opacity: 1.0,

            texture: texture,

            children: Vec::new(),
            children_index: HashMap::new(),
        }
    }

    /// Get the sprite's id
    #[inline(always)]
    pub fn id(&self) -> Uuid {
        self.id.clone()
    }

    /// Whether or not the sprite is visible
    pub fn visible(&self) -> bool {
        self.visible
    }

    /// Set the sprite's visibility
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
    }

    /// Get the sprite's anchor point
    ///
    /// The value is normalized. Default value is [0.5, 0.5] (the center of texture)
    #[inline(always)]
    pub fn anchor(&self) -> (Scalar, Scalar) {
        (self.anchor[0], self.anchor[1])
    }

    /// Set the sprite's anchor point
    #[inline(always)]
    pub fn set_anchor(&mut self, x: Scalar, y: Scalar) {
        self.anchor = [x, y];
    }

    /// Get the sprite's position
    #[inline(always)]
    pub fn position(&self) -> (Scalar, Scalar) {
        (self.position[0], self.position[1])
    }

    /// Set the sprite's position
    #[inline(always)]
    pub fn set_position(&mut self, x: Scalar, y: Scalar) {
        self.position = [x, y];
    }

    /// Set the sprite's draw color (tint)
    #[inline(always)]
    pub fn set_color(&mut self, r: f64, g: f64, b: f64) {
        self.color = [r, g, b];
    }

    /// get the sprite's color.s
    #[inline(always)]
    pub fn color(&self) -> (f64, f64, f64) {
        (self.color[0], self.color[1], self.color[2])
    }

    /// Get the sprite's rotation (in degree)
    #[inline(always)]
    pub fn rotation(&self) -> Scalar {
        self.rotation
    }

    /// Set the sprite's rotation (in degree)
    #[inline(always)]
    pub fn set_rotation(&mut self, deg: Scalar) {
        self.rotation = deg;
    }

    /// Get the sprite's scale
    #[inline(always)]
    pub fn scale(&self) -> (Scalar, Scalar) {
        (self.scale[0], self.scale[1])
    }

    /// Set the sprite's scale
    #[inline(always)]
    pub fn set_scale(&mut self, sx: Scalar, sy: Scalar) {
        self.scale = [sx, sy];
    }

    /// Whether or not the sprite is flipped horizontally.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.x *= -1;
    #[inline(always)]
    pub fn flip_x(&self) -> bool {
        self.flip_x
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_x(&mut self, flip_x: bool) {
        self.flip_x = flip_x;
    }

    /// Whether or not the sprite is flipped vertically.
    ///
    /// It only flips the texture of the sprite,
    /// and not the texture of the sprite’s children.
    ///
    /// Also, flipping the texture doesn’t alter the `anchor`.
    ///
    /// If you want to flip the `anchor` too,
    /// and/or to flip the children too use: sprite.scale.y *= -1;
    #[inline(always)]
    pub fn flip_y(&self) -> bool {
        self.flip_y
    }

    /// Flip the sprite
    #[inline(always)]
    pub fn set_flip_y(&mut self, flip_y: bool) {
        self.flip_y = flip_y;
    }

    /// Get the sprite's opacity
    #[inline(always)]
    pub fn opacity(&self) -> f32 {
        self.opacity
    }

    /// Set the sprite's opacity
    #[inline(always)]
    pub fn set_opacity(&mut self, opacity: f32) {
        self.opacity = opacity;
    }

    /// Get the sprite's texture
    #[inline(always)]
    pub fn texture(&self) -> &Rc<I> {
        &self.texture
    }

    /// Set the sprite's texture
    #[inline(always)]
    pub fn set_texture(&mut self, texture: Rc<I>) {
        self.texture = texture;
    }

    /// Add a sprite as the child of this sprite, return the added sprite's id.
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    /// Remove the child by `id` from this sprite's children or grandchild
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Get the sprite's children
    #[inline(always)]
    pub fn children(&self) -> &Vec<Sprite<I>> {
        &self.children
    }

    /// Draw this sprite and its children
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        use graphics::*;

        if !self.visible {
            return;
        }

        let (w, h) = self.texture.get_size();
        let w = w as f64;
        let h = h as f64;
        let anchor = [self.anchor[0] * w, self.anchor[1] * h];

        let transformed = t.trans(self.position[0], self.position[1])
                           .rot_deg(self.rotation)
                           .scale(self.scale[0], self.scale[1]);

        let mut model = transformed;

        if self.flip_x {
            model = model.trans(w - 2.0 * anchor[0], 0.0).flip_h();
        }

        if self.flip_y {
            model = model.trans(0.0, h - 2.0 * anchor[1]).flip_v();
        }

        let draw_state = default_draw_state();

        // for debug: bounding_box
        //model.rgb(1.0, 0.0, 0.0).draw(b);

        graphics::Image::new()
            .color([self.color[0] as f32, self.color[1] as f32, self.color[2] as f32, self.opacity])
            .rect([-anchor[0], -anchor[1], w, h])
            .draw(&*self.texture, draw_state, model, b);

        // for debug: anchor point
        //c.trans(self.position[0], self.position[1]).rect(-5.0, -5.0, 10.0, 10.0).rgb(0.0, 0.0, 1.0).draw(b);

        for child in self.children.iter() {
            child.draw(transformed, b);
        }
    }

    /// Get the sprite's bounding box
    pub fn bounding_box(&self) -> graphics::types::Rectangle {
        let (w, h) = self.texture.get_size();
        let w = w as f64 * self.scale[0];
        let h = h as f64 * self.scale[1];

        [
            self.position[0] - self.anchor[0] * w,
            self.position[1] - self.anchor[1] * h,
            w,
            h
        ]
    }
}
<|endoftext|>