<commit_before>extern crate x11;
extern crate libc;

use std::ptr;
use std::process::Command;
use std::boxed::Box;

use x11::xlib;
use super::WindowManager;
use super::Workspaces;
use super::container;
use super::layout::{self, LayoutDirection, MoveDirection};
use super::super::libx::{self, Context};

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyBind {
    pub key: xlib::KeySym,
    pub mask: u32,
}

impl KeyBind {
    pub fn build(mod_key: u32, tokens: &[&str]) -> KeyBind {
        let mut mask = 0;
        let mut sym = 0;
        for key in tokens {
            match *key {
                "$mod" => mask = mask | mod_key,
                "Shift" => mask = mask | xlib::ShiftMask,
                "Ctrl" => mask = mask | xlib::ControlMask,
                "Mod1" => mask = mask | xlib::Mod1Mask,
                "Mod2" => mask = mask | xlib::Mod2Mask,
                "Mod3" => mask = mask | xlib::Mod3Mask,
                "Mod4" => mask = mask | xlib::Mod4Mask,
                "Mod5" => mask = mask | xlib::Mod5Mask,
                _ => {
                    sym = libx::string_to_keysym(key);
                }
            }
        }

        KeyBind {
            mask: mask,
            key: sym
        }
    }
}

pub trait Handler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context);
}

pub struct ExecHandler {
    pub cmd: Command
}

pub struct LayoutHandler {
    layout_type: layout::Type,
}

pub struct FullscreenHandler;
/// switch to another workspace
pub struct WorkspaceHandler {
    pub key: char,
}

/// move window to target workspace
pub struct WindowToWorkspaceHandler {
    pub key: char,
}

pub struct WindowFocusHandler {
    pub direction: MoveDirection,
}

pub struct WindowCloseHandler;
pub struct SplitHandler;

pub enum Resize {
    Shrink,
    Grow,
}

pub struct WindowResizeHandler {
    pub direction: LayoutDirection,
    pub resize: Resize
}

impl Handler for WindowResizeHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let focused = workspaces.get_focus();
        if focused.is_some() {
            let c = focused.unwrap();
            let parent = c.get_parent();
            if parent.is_some() {
                let p = parent.unwrap();
                let index = p.contain(c.raw_id()).unwrap();
                if p.direction == self.direction {
                    let step:f32 = match self.resize {
                        Resize::Shrink => {
                            -0.05
                        }
                        Resize::Grow => {
                            0.05
                        }
                    };

                    if index > 0 && index < (p.size() - 1) {
                        p.resize_children(index, index-1, step);
                        p.resize_children(index, index+1, step);
                    }
                    else if index > 0 {
                        p.resize_children(index, index-1, step*2.0);
                    }
                    else if index < (p.size() - 1) {
                        p.resize_children(index, index+1, step*2.0);
                    }
                    p.update_layout();
                }

            }
        }
    }
}

impl Handler for SplitHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        workspaces.current().print_tree(0);
        match workspaces.get_focus() {
            Some(c) => {
                c.split();
            }
            None => {}
        }
        println!("after");
        workspaces.current().print_tree(0);
    }
}

impl Handler for WindowCloseHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle window close");
        let (window, _) = libx::get_input_focus(context);
        libx::kill_window(context, window);
        // xlib::XWithdrawWindow(context, window, screen_num);
        // xlib::XDestroyWindow(context, window);
        println!("try kill window {}", window);

    }
}
impl Handler for WindowFocusHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("change focus in current workspace");
        let focused = workspaces.get_focus();
        match focused {
            Some(c) => {
                match c.get_parent() {
                    Some(p) => {
                        let index = p.contain(c.raw_id()).unwrap();
                        let size = p.size();
                        match p.direction {
                            LayoutDirection::Vertical => {
                                let next = match self.direction {
                                    MoveDirection::Up => {
                                        (index-1) % size
                                    }
                                    MoveDirection::Down => {
                                        (index+1) % size
                                    }
                                    _ => { return }
                                };
                                c.unfocus();
                                let next_c = p.get_child(next).unwrap().focus();
                            }
                            LayoutDirection::Horizontal => {
                                let next = match self.direction {
                                    MoveDirection::Left => {
                                        (index-1) % size
                                    }
                                    MoveDirection::Right => {
                                        (index+1) % size
                                    }
                                    _ => { return }
                                };
                                c.unfocus();
                                let next_c = p.get_child(next).unwrap().focus();
                            }
                        }
                    }
                    None => {}
                }
            }
            None => {}
        }
    }
}

impl Handler for WindowToWorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let id = match workspaces.get_focus() {
            Some(container) => {
                container.raw_id()
            }
            None => { return }
        };
        let from = workspaces.current_name();
        let to = self.key;
        workspaces.move_window(id, from, to);
    }
}

impl Handler for FullscreenHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("fullscreen toggle");
        let focused = workspaces.get_focus();
        match focused {
            Some(c) => {
                c.mode_toggle();
            }
            None => {}
        }
    }
}
impl Handler for WorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle workspace form {}", workspaces.current_name());
        if !workspaces.contain(self.key) {
            workspaces.create(self.key);
        }
        workspaces.switch_workspace(self.key, context);
        println!("to {}", workspaces.current_name());
    }
}

impl Handler for ExecHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle exec");
        self.cmd.spawn();
    }
}

impl Handler for LayoutHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle layout");
        let t = self.layout_type.clone();
        let focused = workspaces.get_focus();
        match focused {
            Some(container) => {
                let c = if container.get_parent().is_some() {
                    container.get_parent().unwrap()
                }
                else {
                    container
                };
                c.change_layout(t);
                c.update_layout();
            }
            None => {}
        }
    }
}

impl LayoutHandler {
    pub fn new(layout: layout::Type) -> LayoutHandler{
        LayoutHandler {
            layout_type: layout
        }
    }
}

impl ExecHandler {
    pub fn new(tokens: &[&str]) -> ExecHandler {
        let (name, args) = tokens.split_at(1);
        let mut cmd = Command::new(name[0]);
        cmd.args(args);

        let handler = ExecHandler {
            cmd: cmd,
        };
        handler
    }
}
<commit_msg>refactor code<commit_after>extern crate x11;
extern crate libc;

use std::ptr;
use std::process::Command;
use std::boxed::Box;

use x11::xlib;
use super::WindowManager;
use super::Workspaces;
use super::container;
use super::layout::{self, LayoutDirection, MoveDirection};
use super::super::libx::{self, Context};

#[derive(Hash, Eq, PartialEq, Debug)]
pub struct KeyBind {
    pub key: xlib::KeySym,
    pub mask: u32,
}

impl KeyBind {
    pub fn build(mod_key: u32, tokens: &[&str]) -> KeyBind {
        let mut mask = 0;
        let mut sym = 0;
        for key in tokens {
            match *key {
                "$mod" => mask = mask | mod_key,
                "Shift" => mask = mask | xlib::ShiftMask,
                "Ctrl" => mask = mask | xlib::ControlMask,
                "Mod1" => mask = mask | xlib::Mod1Mask,
                "Mod2" => mask = mask | xlib::Mod2Mask,
                "Mod3" => mask = mask | xlib::Mod3Mask,
                "Mod4" => mask = mask | xlib::Mod4Mask,
                "Mod5" => mask = mask | xlib::Mod5Mask,
                _ => {
                    sym = libx::string_to_keysym(key);
                }
            }
        }

        KeyBind {
            mask: mask,
            key: sym
        }
    }
}

pub trait Handler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context);
}

pub struct ExecHandler {
    pub cmd: Command
}

pub struct LayoutHandler {
    layout_type: layout::Type,
}

pub struct FullscreenHandler;
/// switch to another workspace
pub struct WorkspaceHandler {
    pub key: char,
}

/// move window to target workspace
pub struct WindowToWorkspaceHandler {
    pub key: char,
}

pub struct WindowFocusHandler {
    pub direction: MoveDirection,
}

pub struct WindowCloseHandler;
pub struct SplitHandler;

pub enum Resize {
    Shrink,
    Grow,
}

pub struct WindowResizeHandler {
    pub direction: LayoutDirection,
    pub resize: Resize
}

impl Handler for WindowResizeHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let focused = workspaces.get_focus();
        if focused.is_some() {
            let c = focused.unwrap();
            let parent = c.get_parent();
            if parent.is_some() {
                let p = parent.unwrap();
                let index = p.contain(c.raw_id()).unwrap();
                if p.direction == self.direction {
                    let step:f32 = match self.resize {
                        Resize::Shrink => {
                            -0.05
                        }
                        Resize::Grow => {
                            0.05
                        }
                    };

                    if index > 0 && index < (p.size() - 1) {
                        p.resize_children(index, index-1, step);
                        p.resize_children(index, index+1, step);
                    }
                    else if index > 0 {
                        p.resize_children(index, index-1, step*2.0);
                    }
                    else if index < (p.size() - 1) {
                        p.resize_children(index, index+1, step*2.0);
                    }
                    p.update_layout();
                }

            }
        }
    }
}

impl Handler for SplitHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        workspaces.current().print_tree(0);
        match workspaces.get_focus() {
            Some(c) => {
                c.split();
            }
            None => {}
        }
        println!("after");
        workspaces.current().print_tree(0);
    }
}

impl Handler for WindowCloseHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle window close");
        let (window, _) = libx::get_input_focus(context);
        libx::kill_window(context, window);
        // xlib::XWithdrawWindow(context, window, screen_num);
        // xlib::XDestroyWindow(context, window);
        println!("try kill window {}", window);

    }
}
impl Handler for WindowFocusHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("change focus in current workspace");
        let focused = workspaces.get_focus();
        match focused {
            Some(c) => {
                match c.get_parent() {
                    Some(p) => {
                        let index = p.contain(c.raw_id()).unwrap();
                        let size = p.size();
                        let next = match p.direction {
                            LayoutDirection::Vertical => {
                                match self.direction {
                                    MoveDirection::Up => {
                                        (index-1) % size
                                    }
                                    MoveDirection::Down => {
                                        (index+1) % size
                                    }
                                    _ => { index }
                                }
                            }
                            LayoutDirection::Horizontal => {
                                match self.direction {
                                    MoveDirection::Left => {
                                        (index-1) % size
                                    }
                                    MoveDirection::Right => {
                                        (index+1) % size
                                    }
                                    _ => { index }
                                }
                            }
                        };
                        if next != index {
                            c.unfocus();
                            let next_c = p.get_child(next).unwrap().focus();
                        }
                    }
                    None => {}
                }
            }
            None => {}
        }
    }
}

impl Handler for WindowToWorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        let id = match workspaces.get_focus() {
            Some(container) => {
                container.raw_id()
            }
            None => { return }
        };
        let from = workspaces.current_name();
        let to = self.key;
        workspaces.move_window(id, from, to);
    }
}

impl Handler for FullscreenHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("fullscreen toggle");
        let focused = workspaces.get_focus();
        match focused {
            Some(c) => {
                c.mode_toggle();
            }
            None => {}
        }
    }
}
impl Handler for WorkspaceHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle workspace form {}", workspaces.current_name());
        if !workspaces.contain(self.key) {
            workspaces.create(self.key);
        }
        workspaces.switch_workspace(self.key, context);
        println!("to {}", workspaces.current_name());
    }
}

impl Handler for ExecHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle exec");
        self.cmd.spawn();
    }
}

impl Handler for LayoutHandler {
    fn handle(&mut self, workspaces: &mut Workspaces, context: Context) {
        debug!("handle layout");
        let t = self.layout_type.clone();
        let focused = workspaces.get_focus();
        match focused {
            Some(container) => {
                let c = if container.get_parent().is_some() {
                    container.get_parent().unwrap()
                }
                else {
                    container
                };
                c.change_layout(t);
                c.update_layout();
            }
            None => {}
        }
    }
}

impl LayoutHandler {
    pub fn new(layout: layout::Type) -> LayoutHandler{
        LayoutHandler {
            layout_type: layout
        }
    }
}

impl ExecHandler {
    pub fn new(tokens: &[&str]) -> ExecHandler {
        let (name, args) = tokens.split_at(1);
        let mut cmd = Command::new(name[0]);
        cmd.args(args);

        let handler = ExecHandler {
            cmd: cmd,
        };
        handler
    }
}
<|endoftext|>


<commit_before>//! Details of the `ruma_api` procedural macro.

use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{
    parse::{Parse, ParseStream},
    Field, Token, Type,
};

pub(crate) mod attribute;
pub(crate) mod metadata;
pub(crate) mod request;
pub(crate) mod response;

use self::{metadata::Metadata, request::Request, response::Response};
use crate::util;

/// Removes `serde` attributes from struct fields.
pub fn strip_serde_attrs(field: &Field) -> Field {
    let mut field = field.clone();
    field.attrs.retain(|attr| !attr.path.is_ident("serde"));
    field
}

/// The result of processing the `ruma_api` macro, ready for output back to source code.
pub struct Api {
    /// The `metadata` section of the macro.
    metadata: Metadata,

    /// The `request` section of the macro.
    request: Request,

    /// The `response` section of the macro.
    response: Response,

    /// The `error` section of the macro.
    error_ty: TokenStream,
}

impl Parse for Api {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        let ruma_api = util::import_ruma_api();

        let metadata: Metadata = input.parse()?;
        let request: Request = input.parse()?;
        let response: Response = input.parse()?;
        let error_ty = match input.parse::<ErrorType>() {
            Ok(err) => err.ty.to_token_stream(),
            Err(_) => quote! { #ruma_api::error::Void },
        };

        let newtype_body_field = request.newtype_body_field();
        if metadata.method == "GET" && (request.has_body_fields() || newtype_body_field.is_some()) {
            let mut combined_error: Option<syn::Error> = None;
            let mut add_error = |field| {
                let error = syn::Error::new_spanned(field, "GET endpoints can't have body fields");
                if let Some(combined_error_ref) = &mut combined_error {
                    combined_error_ref.combine(error);
                } else {
                    combined_error = Some(error);
                }
            };

            for field in request.body_fields() {
                add_error(field);
            }

            if let Some(field) = newtype_body_field {
                add_error(field);
            }

            return Err(combined_error.unwrap());
        }

        Ok(Self { metadata, request, response, error_ty })
    }
}

pub fn expand_all(api: Api) -> syn::Result<TokenStream> {
    // Guarantee `ruma_api` is available and named something we can refer to.
    let ruma_api_import = util::import_ruma_api();

    let description = &api.metadata.description;
    let method = &api.metadata.method;
    // We don't (currently) use this literal as a literal in the generated code. Instead we just
    // put it into doc comments, for which the span information is irrelevant. So we can work
    // with only the literal's value from here on.
    let name = &api.metadata.name.value();
    let path = &api.metadata.path;
    let rate_limited = &api.metadata.rate_limited;
    let authentication = &api.metadata.authentication;

    let request_type = &api.request;
    let response_type = &api.response;

    let incoming_request_type =
        if api.request.contains_lifetimes() { quote!(IncomingRequest) } else { quote!(Request) };

    let extract_request_path = if api.request.has_path_fields() {
        quote! {
            let path_segments: ::std::vec::Vec<&::std::primitive::str> =
                request.uri().path()[1..].split('/').collect();
        }
    } else {
        TokenStream::new()
    };

    let (request_path_string, parse_request_path) =
        util::request_path_string_and_parse(&api.request, &api.metadata, &ruma_api_import);

    let request_query_string = util::build_query_string(&api.request, &ruma_api_import);

    let extract_request_query = util::extract_request_query(&api.request, &ruma_api_import);

    let parse_request_query = if let Some(field) = api.request.query_map_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");

        quote! {
            #field_name: request_query,
        }
    } else {
        api.request.request_init_query_fields()
    };

    let mut header_kvs = api.request.append_header_kvs();
    if authentication == "AccessToken" {
        header_kvs.extend(quote! {
            req_builder = req_builder.header(
                #ruma_api_import::exports::http::header::AUTHORIZATION,
                #ruma_api_import::exports::http::header::HeaderValue::from_str(
                    &::std::format!(
                        "Bearer {}",
                        access_token.ok_or(
                            #ruma_api_import::error::IntoHttpError::NeedsAuthentication
                        )?
                    )
                )?
            );
        });
    }

    let extract_request_headers = if api.request.has_header_fields() {
        quote! {
            let headers = request.headers();
        }
    } else {
        TokenStream::new()
    };

    let extract_request_body =
        if api.request.has_body_fields() || api.request.newtype_body_field().is_some() {
            let body_lifetimes = if api.request.has_body_lifetimes() {
                // duplicate the anonymous lifetime as many times as needed
                let lifetimes =
                    std::iter::repeat(quote! { '_ }).take(api.request.body_lifetime_count());
                quote! { < #( #lifetimes, )* >}
            } else {
                TokenStream::new()
            };
            quote! {
                let request_body: <
                    RequestBody #body_lifetimes
                    as #ruma_api_import::exports::ruma_serde::Outgoing
                >::Incoming =
                    #ruma_api_import::try_deserialize!(
                        request,
                        #ruma_api_import::exports::serde_json::from_slice(request.body().as_slice())
                    );
            }
        } else {
            TokenStream::new()
        };

    let parse_request_headers = if api.request.has_header_fields() {
        api.request.parse_headers_from_request()
    } else {
        TokenStream::new()
    };

    let request_body = util::build_request_body(&api.request, &ruma_api_import);

    let parse_request_body = util::parse_request_body(&api.request);

    let extract_response_headers = if api.response.has_header_fields() {
        quote! {
            let mut headers = response.headers().clone();
        }
    } else {
        TokenStream::new()
    };

    let typed_response_body_decl = if api.response.has_body_fields()
        || api.response.newtype_body_field().is_some()
    {
        quote! {
            let response_body: <
                ResponseBody
                as #ruma_api_import::exports::ruma_serde::Outgoing
            >::Incoming =
                #ruma_api_import::try_deserialize!(
                    response,
                    #ruma_api_import::exports::serde_json::from_slice(response.body().as_slice()),
                );
        }
    } else {
        TokenStream::new()
    };

    let response_init_fields = api.response.init_fields();

    let serialize_response_headers = api.response.apply_header_fields();

    let body = api.response.to_body();

    let metadata_doc = format!("Metadata for the `{}` API endpoint.", name);
    let request_doc =
        format!("Data for a request to the `{}` API endpoint.\n\n{}", name, description.value());
    let response_doc = format!("Data in the response from the `{}` API endpoint.", name);

    let error = &api.error_ty;

    let request_lifetimes = api.request.combine_lifetimes();

    let non_auth_endpoint_impls = if authentication != "None" {
        TokenStream::new()
    } else {
        quote! {
            impl #request_lifetimes #ruma_api_import::OutgoingNonAuthRequest
                for Request #request_lifetimes
            {}

            impl #ruma_api_import::IncomingNonAuthRequest for #incoming_request_type {}
        }
    };

    Ok(quote! {
        #[doc = #request_doc]
        #request_type

        impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Request<Vec<u8>>>
            for #incoming_request_type
        {
            type Error = #ruma_api_import::error::FromHttpRequestError;

            #[allow(unused_variables)]
            fn try_from(
                request: #ruma_api_import::exports::http::Request<Vec<u8>>
            ) -> ::std::result::Result<Self, Self::Error> {
                #extract_request_path
                #extract_request_query
                #extract_request_headers
                #extract_request_body

                Ok(Self {
                    #parse_request_path
                    #parse_request_query
                    #parse_request_headers
                    #parse_request_body
                })
            }
        }

        #[doc = #response_doc]
        #response_type

        impl ::std::convert::TryFrom<Response>
            for #ruma_api_import::exports::http::Response<Vec<u8>>
        {
            type Error = #ruma_api_import::error::IntoHttpError;

            #[allow(unused_variables)]
            fn try_from(response: Response) -> ::std::result::Result<Self, Self::Error> {
                let mut resp_builder = #ruma_api_import::exports::http::Response::builder()
                    .header(
                        #ruma_api_import::exports::http::header::CONTENT_TYPE,
                        "application/json",
                    );

                let mut headers = resp_builder
                    .headers_mut()
                    .expect("`http::ResponseBuilder` is in unusable state");
                #serialize_response_headers

                // This cannot fail because we parse each header value
                // checking for errors as each value is inserted and
                // we only allow keys from the `http::header` module.
                let response = resp_builder.body(#body).unwrap();
                Ok(response)
            }
        }

        impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Response<Vec<u8>>>
            for Response
        {
            type Error = #ruma_api_import::error::FromHttpResponseError<#error>;

            #[allow(unused_variables)]
            fn try_from(
                response: #ruma_api_import::exports::http::Response<Vec<u8>>,
            ) -> ::std::result::Result<Self, Self::Error> {
                if response.status().as_u16() < 400 {
                    #extract_response_headers

                    #typed_response_body_decl

                    Ok(Self {
                        #response_init_fields
                    })
                } else {
                    match <#error as #ruma_api_import::EndpointError>::try_from_response(response) {
                        Ok(err) => Err(#ruma_api_import::error::ServerError::Known(err).into()),
                        Err(response_err) => {
                            Err(#ruma_api_import::error::ServerError::Unknown(response_err).into())
                        }
                    }
                }
            }
        }

        #[doc = #metadata_doc]
        pub const METADATA: #ruma_api_import::Metadata = #ruma_api_import::Metadata {
            description: #description,
            method: #ruma_api_import::exports::http::Method::#method,
            name: #name,
            path: #path,
            rate_limited: #rate_limited,
            authentication: #ruma_api_import::AuthScheme::#authentication,
        };

        impl #request_lifetimes #ruma_api_import::OutgoingRequest
            for Request #request_lifetimes
        {
            type EndpointError = #error;
            type IncomingResponse =
                <Response as #ruma_api_import::exports::ruma_serde::Outgoing>::Incoming;

            #[doc = #metadata_doc]
            const METADATA: #ruma_api_import::Metadata = self::METADATA;

            #[allow(unused_mut, unused_variables)]
            fn try_into_http_request(
                self,
                base_url: &::std::primitive::str,
                access_token: ::std::option::Option<&str>,
            ) -> ::std::result::Result<
                #ruma_api_import::exports::http::Request<Vec<u8>>,
                #ruma_api_import::error::IntoHttpError,
            > {
                let metadata = self::METADATA;

                let mut req_builder = #ruma_api_import::exports::http::Request::builder()
                    .method(#ruma_api_import::exports::http::Method::#method)
                    .uri(::std::format!(
                        "{}{}{}",
                        // FIXME: Once MSRV is >= 1.45.0, switch to
                        // base_url.strip_suffix('/').unwrap_or(base_url),
                        match base_url.as_bytes().last() {
                            Some(b'/') => &base_url[..base_url.len() - 1],
                            _ => base_url,
                        },
                        #request_path_string,
                        #request_query_string,
                    ));

                #header_kvs

                let http_request = req_builder.body(#request_body)?;

                Ok(http_request)
            }
        }

        impl #ruma_api_import::IncomingRequest for #incoming_request_type {
            type EndpointError = #error;
            type OutgoingResponse = Response;

            #[doc = #metadata_doc]
            const METADATA: #ruma_api_import::Metadata = self::METADATA;
        }

        #non_auth_endpoint_impls
    })
}

mod kw {
    syn::custom_keyword!(error);
}

pub struct ErrorType {
    pub error_kw: kw::error,
    pub ty: Type,
}

impl Parse for ErrorType {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        let error_kw = input.parse::<kw::error>()?;
        input.parse::<Token![:]>()?;
        let ty = input.parse()?;

        Ok(Self { error_kw, ty })
    }
}
<commit_msg>Allow empty request / response if all body parameters are optional<commit_after>//! Details of the `ruma_api` procedural macro.

use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{
    parse::{Parse, ParseStream},
    Field, Token, Type,
};

pub(crate) mod attribute;
pub(crate) mod metadata;
pub(crate) mod request;
pub(crate) mod response;

use self::{metadata::Metadata, request::Request, response::Response};
use crate::util;

/// Removes `serde` attributes from struct fields.
pub fn strip_serde_attrs(field: &Field) -> Field {
    let mut field = field.clone();
    field.attrs.retain(|attr| !attr.path.is_ident("serde"));
    field
}

/// The result of processing the `ruma_api` macro, ready for output back to source code.
pub struct Api {
    /// The `metadata` section of the macro.
    metadata: Metadata,

    /// The `request` section of the macro.
    request: Request,

    /// The `response` section of the macro.
    response: Response,

    /// The `error` section of the macro.
    error_ty: TokenStream,
}

impl Parse for Api {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        let ruma_api = util::import_ruma_api();

        let metadata: Metadata = input.parse()?;
        let request: Request = input.parse()?;
        let response: Response = input.parse()?;
        let error_ty = match input.parse::<ErrorType>() {
            Ok(err) => err.ty.to_token_stream(),
            Err(_) => quote! { #ruma_api::error::Void },
        };

        let newtype_body_field = request.newtype_body_field();
        if metadata.method == "GET" && (request.has_body_fields() || newtype_body_field.is_some()) {
            let mut combined_error: Option<syn::Error> = None;
            let mut add_error = |field| {
                let error = syn::Error::new_spanned(field, "GET endpoints can't have body fields");
                if let Some(combined_error_ref) = &mut combined_error {
                    combined_error_ref.combine(error);
                } else {
                    combined_error = Some(error);
                }
            };

            for field in request.body_fields() {
                add_error(field);
            }

            if let Some(field) = newtype_body_field {
                add_error(field);
            }

            return Err(combined_error.unwrap());
        }

        Ok(Self { metadata, request, response, error_ty })
    }
}

pub fn expand_all(api: Api) -> syn::Result<TokenStream> {
    // Guarantee `ruma_api` is available and named something we can refer to.
    let ruma_api_import = util::import_ruma_api();

    let description = &api.metadata.description;
    let method = &api.metadata.method;
    // We don't (currently) use this literal as a literal in the generated code. Instead we just
    // put it into doc comments, for which the span information is irrelevant. So we can work
    // with only the literal's value from here on.
    let name = &api.metadata.name.value();
    let path = &api.metadata.path;
    let rate_limited = &api.metadata.rate_limited;
    let authentication = &api.metadata.authentication;

    let request_type = &api.request;
    let response_type = &api.response;

    let incoming_request_type =
        if api.request.contains_lifetimes() { quote!(IncomingRequest) } else { quote!(Request) };

    let extract_request_path = if api.request.has_path_fields() {
        quote! {
            let path_segments: ::std::vec::Vec<&::std::primitive::str> =
                request.uri().path()[1..].split('/').collect();
        }
    } else {
        TokenStream::new()
    };

    let (request_path_string, parse_request_path) =
        util::request_path_string_and_parse(&api.request, &api.metadata, &ruma_api_import);

    let request_query_string = util::build_query_string(&api.request, &ruma_api_import);

    let extract_request_query = util::extract_request_query(&api.request, &ruma_api_import);

    let parse_request_query = if let Some(field) = api.request.query_map_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");

        quote! {
            #field_name: request_query,
        }
    } else {
        api.request.request_init_query_fields()
    };

    let mut header_kvs = api.request.append_header_kvs();
    if authentication == "AccessToken" {
        header_kvs.extend(quote! {
            req_builder = req_builder.header(
                #ruma_api_import::exports::http::header::AUTHORIZATION,
                #ruma_api_import::exports::http::header::HeaderValue::from_str(
                    &::std::format!(
                        "Bearer {}",
                        access_token.ok_or(
                            #ruma_api_import::error::IntoHttpError::NeedsAuthentication
                        )?
                    )
                )?
            );
        });
    }

    let extract_request_headers = if api.request.has_header_fields() {
        quote! {
            let headers = request.headers();
        }
    } else {
        TokenStream::new()
    };

    let extract_request_body =
        if api.request.has_body_fields() || api.request.newtype_body_field().is_some() {
            let body_lifetimes = if api.request.has_body_lifetimes() {
                // duplicate the anonymous lifetime as many times as needed
                let lifetimes =
                    std::iter::repeat(quote! { '_ }).take(api.request.body_lifetime_count());
                quote! { < #( #lifetimes, )* >}
            } else {
                TokenStream::new()
            };
            quote! {
                let request_body: <
                    RequestBody #body_lifetimes
                    as #ruma_api_import::exports::ruma_serde::Outgoing
                >::Incoming = {
                    // If the request body is completely empty, pretend it is an empty JSON object
                    // instead. This allows requests with only optional body parameters to be
                    // deserialized in that case.
                    let json = match request.body().as_slice() {
                        b"" => b"{}",
                        body => body,
                    };

                    #ruma_api_import::try_deserialize!(
                        request,
                        #ruma_api_import::exports::serde_json::from_slice(json)
                    )
                };
            }
        } else {
            TokenStream::new()
        };

    let parse_request_headers = if api.request.has_header_fields() {
        api.request.parse_headers_from_request()
    } else {
        TokenStream::new()
    };

    let request_body = util::build_request_body(&api.request, &ruma_api_import);

    let parse_request_body = util::parse_request_body(&api.request);

    let extract_response_headers = if api.response.has_header_fields() {
        quote! {
            let mut headers = response.headers().clone();
        }
    } else {
        TokenStream::new()
    };

    let typed_response_body_decl =
        if api.response.has_body_fields() || api.response.newtype_body_field().is_some() {
            quote! {
                let response_body: <
                    ResponseBody
                    as #ruma_api_import::exports::ruma_serde::Outgoing
                >::Incoming = {
                    // If the reponse body is completely empty, pretend it is an empty JSON object
                    // instead. This allows reponses with only optional body parameters to be
                    // deserialized in that case.
                    let json = match response.body().as_slice() {
                        b"" => b"{}",
                        body => body,
                    };

                    #ruma_api_import::try_deserialize!(
                        response,
                        #ruma_api_import::exports::serde_json::from_slice(json),
                    )
                };
            }
        } else {
            TokenStream::new()
        };

    let response_init_fields = api.response.init_fields();

    let serialize_response_headers = api.response.apply_header_fields();

    let body = api.response.to_body();

    let metadata_doc = format!("Metadata for the `{}` API endpoint.", name);
    let request_doc =
        format!("Data for a request to the `{}` API endpoint.\n\n{}", name, description.value());
    let response_doc = format!("Data in the response from the `{}` API endpoint.", name);

    let error = &api.error_ty;

    let request_lifetimes = api.request.combine_lifetimes();

    let non_auth_endpoint_impls = if authentication != "None" {
        TokenStream::new()
    } else {
        quote! {
            impl #request_lifetimes #ruma_api_import::OutgoingNonAuthRequest
                for Request #request_lifetimes
            {}

            impl #ruma_api_import::IncomingNonAuthRequest for #incoming_request_type {}
        }
    };

    Ok(quote! {
        #[doc = #request_doc]
        #request_type

        impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Request<Vec<u8>>>
            for #incoming_request_type
        {
            type Error = #ruma_api_import::error::FromHttpRequestError;

            #[allow(unused_variables)]
            fn try_from(
                request: #ruma_api_import::exports::http::Request<Vec<u8>>
            ) -> ::std::result::Result<Self, Self::Error> {
                #extract_request_path
                #extract_request_query
                #extract_request_headers
                #extract_request_body

                Ok(Self {
                    #parse_request_path
                    #parse_request_query
                    #parse_request_headers
                    #parse_request_body
                })
            }
        }

        #[doc = #response_doc]
        #response_type

        impl ::std::convert::TryFrom<Response>
            for #ruma_api_import::exports::http::Response<Vec<u8>>
        {
            type Error = #ruma_api_import::error::IntoHttpError;

            #[allow(unused_variables)]
            fn try_from(response: Response) -> ::std::result::Result<Self, Self::Error> {
                let mut resp_builder = #ruma_api_import::exports::http::Response::builder()
                    .header(
                        #ruma_api_import::exports::http::header::CONTENT_TYPE,
                        "application/json",
                    );

                let mut headers = resp_builder
                    .headers_mut()
                    .expect("`http::ResponseBuilder` is in unusable state");
                #serialize_response_headers

                // This cannot fail because we parse each header value
                // checking for errors as each value is inserted and
                // we only allow keys from the `http::header` module.
                let response = resp_builder.body(#body).unwrap();
                Ok(response)
            }
        }

        impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Response<Vec<u8>>>
            for Response
        {
            type Error = #ruma_api_import::error::FromHttpResponseError<#error>;

            #[allow(unused_variables)]
            fn try_from(
                response: #ruma_api_import::exports::http::Response<Vec<u8>>,
            ) -> ::std::result::Result<Self, Self::Error> {
                if response.status().as_u16() < 400 {
                    #extract_response_headers

                    #typed_response_body_decl

                    Ok(Self {
                        #response_init_fields
                    })
                } else {
                    match <#error as #ruma_api_import::EndpointError>::try_from_response(response) {
                        Ok(err) => Err(#ruma_api_import::error::ServerError::Known(err).into()),
                        Err(response_err) => {
                            Err(#ruma_api_import::error::ServerError::Unknown(response_err).into())
                        }
                    }
                }
            }
        }

        #[doc = #metadata_doc]
        pub const METADATA: #ruma_api_import::Metadata = #ruma_api_import::Metadata {
            description: #description,
            method: #ruma_api_import::exports::http::Method::#method,
            name: #name,
            path: #path,
            rate_limited: #rate_limited,
            authentication: #ruma_api_import::AuthScheme::#authentication,
        };

        impl #request_lifetimes #ruma_api_import::OutgoingRequest
            for Request #request_lifetimes
        {
            type EndpointError = #error;
            type IncomingResponse =
                <Response as #ruma_api_import::exports::ruma_serde::Outgoing>::Incoming;

            #[doc = #metadata_doc]
            const METADATA: #ruma_api_import::Metadata = self::METADATA;

            #[allow(unused_mut, unused_variables)]
            fn try_into_http_request(
                self,
                base_url: &::std::primitive::str,
                access_token: ::std::option::Option<&str>,
            ) -> ::std::result::Result<
                #ruma_api_import::exports::http::Request<Vec<u8>>,
                #ruma_api_import::error::IntoHttpError,
            > {
                let metadata = self::METADATA;

                let mut req_builder = #ruma_api_import::exports::http::Request::builder()
                    .method(#ruma_api_import::exports::http::Method::#method)
                    .uri(::std::format!(
                        "{}{}{}",
                        // FIXME: Once MSRV is >= 1.45.0, switch to
                        // base_url.strip_suffix('/').unwrap_or(base_url),
                        match base_url.as_bytes().last() {
                            Some(b'/') => &base_url[..base_url.len() - 1],
                            _ => base_url,
                        },
                        #request_path_string,
                        #request_query_string,
                    ));

                #header_kvs

                let http_request = req_builder.body(#request_body)?;

                Ok(http_request)
            }
        }

        impl #ruma_api_import::IncomingRequest for #incoming_request_type {
            type EndpointError = #error;
            type OutgoingResponse = Response;

            #[doc = #metadata_doc]
            const METADATA: #ruma_api_import::Metadata = self::METADATA;
        }

        #non_auth_endpoint_impls
    })
}

mod kw {
    syn::custom_keyword!(error);
}

pub struct ErrorType {
    pub error_kw: kw::error,
    pub ty: Type,
}

impl Parse for ErrorType {
    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
        let error_kw = input.parse::<kw::error>()?;
        input.parse::<Token![:]>()?;
        let ty = input.parse()?;

        Ok(Self { error_kw, ty })
    }
}
<|endoftext|>


<commit_before>extern crate itertools;
use std::collections::HashSet;
use itertools::Itertools;

pub fn count(lines: &[&str]) -> i32 {
    if lines.is_empty() {
        return 0;
    }
    let rectangle_corners = lines.iter().enumerate().fold(HashSet::new(),
                                                          |acc, (outer_idx, val)| {
        val.chars()
            .enumerate()
            .filter(|&(_, ch)| ch == '+')
            .fold(acc, |mut acc, (inner_idx, _)| {
                acc.insert((outer_idx as i32, inner_idx as i32));
                acc
            })
    });

    // get the the list of total points from the diagram, then grab all the
    // right corners and feed it to a function that will calculate the left
    // corner
    let rectangles = (0i32..lines.len() as i32)
        .cartesian_product(0i32..lines[0].len() as i32)
        .filter(|&(x, y)| x != 0 && y != 0)
        .map(|corner| get_list_of_rects_from_right_corner(corner))
        .fold(HashSet::<((i32, i32), (i32, i32))>::new(), |mut acc, val| {
            acc.extend(val.iter());
            acc
        });

    count_rectangles(&rectangle_corners, &rectangles, lines)
}

// gets the list of rectangles, (up_left, right_down) pairs starting from down right corner
fn get_list_of_rects_from_right_corner(point: (i32, i32)) -> HashSet<((i32, i32), (i32, i32))> {
    let mut v = HashSet::new();
    let mut left_corner = (point.0 - 1, point.1 - 1);
    // populates up left and down right pair of corners
    while left_corner.0 >= 0 {
        while left_corner.1 >= 0 {
            v.insert((left_corner, point));
            left_corner = (left_corner.0, left_corner.1 - 1);
        }
        left_corner = (left_corner.0 - 1, point.1 - 1);
    }

    v

}

// this function validates if the rectangle has been formed using valid ASCII
// characters
//   - horizontal: + | -
//   - vertical:   + | |
fn does_rectangle_contains_valid_chars(up_left: (i32, i32),
                                       right_down: (i32, i32),
                                       lines: &[&str])
                                       -> bool {
    lines.iter()
            .skip(up_left.0 as usize)
            .take(1)
            .next()
            .unwrap()[up_left.1 as usize..right_down.1 as usize + 1]
        .chars()
        .all(|y| y == '+' || y == '-') &&
    lines.iter()
            .skip(right_down.0 as usize)
            .take(1)
            .next()
            .unwrap()[up_left.1 as usize..right_down.1 as usize + 1]
        .chars()
        .all(|y| y == '+' || y == '-') &&
    lines.iter()
        .skip(up_left.0 as usize)
        .take(right_down.0 as usize - up_left.0 as usize + 1)
        .map(|str| str.chars().skip(up_left.1 as usize).take(1).next().unwrap())
        .all(|c| c == '+' || c == '|') &&
    lines.iter()
        .skip(up_left.0 as usize)
        .take(right_down.0 as usize - up_left.0 as usize + 1)
        .map(|str| str.chars().skip(right_down.1 as usize).take(1).next().unwrap())
        .all(|c| c == '+' || c == '|')

}

fn count_rectangles(rectangle_points: &HashSet<(i32, i32)>,
                    from: &HashSet<((i32, i32), (i32, i32))>,
                    lines: &[&str])
                    -> i32 {
    let mut count = 0;
    for &(up_left_corner, right_down_corner) in from {
        if rectangle_points.contains(&up_left_corner) &&
           rectangle_points.contains(&right_down_corner) &&
           rectangle_points.contains(&(right_down_corner.0, up_left_corner.1)) &&
           rectangle_points.contains(&(up_left_corner.0, right_down_corner.1)) &&
           does_rectangle_contains_valid_chars(up_left_corner, right_down_corner, lines) {
            count += 1;
        }
    }
    count
}
<commit_msg>Replace the (i32, i32) tuple with a type alias Point<commit_after>extern crate itertools;
use std::collections::HashSet;
use itertools::Itertools;

type Point = (i32, i32);

pub fn count(lines: &[&str]) -> i32 {
    if lines.is_empty() {
        return 0;
    }
    let rectangle_corners = lines.iter().enumerate().fold(HashSet::new(),
                                                          |acc, (outer_idx, val)| {
        val.chars()
            .enumerate()
            .filter(|&(_, ch)| ch == '+')
            .fold(acc, |mut acc, (inner_idx, _)| {
                acc.insert((outer_idx as i32, inner_idx as i32));
                acc
            })
    });

    // get the the list of total points from the diagram, then grab all the
    // right corners and feed it to a function that will calculate the left
    // corner
    let rectangles = (0i32..lines.len() as i32)
        .cartesian_product(0i32..lines[0].len() as i32)
        .filter(|&(x, y)| x != 0 && y != 0)
        .map(|corner| get_list_of_rects_from_right_corner(corner))
        .fold(HashSet::<(Point, Point)>::new(), |mut acc, val| {
            acc.extend(val.iter());
            acc
        });

    count_rectangles(&rectangle_corners, &rectangles, lines)
}

// gets the list of rectangles, (up_left, right_down) pairs starting from down right corner
fn get_list_of_rects_from_right_corner(point: Point) -> HashSet<(Point, Point)> {
    let mut v = HashSet::new();
    let mut left_corner = (point.0 - 1, point.1 - 1);
    // populates up left and down right pair of corners
    while left_corner.0 >= 0 {
        while left_corner.1 >= 0 {
            v.insert((left_corner, point));
            left_corner = (left_corner.0, left_corner.1 - 1);
        }
        left_corner = (left_corner.0 - 1, point.1 - 1);
    }

    v

}

// this function validates if the rectangle has been formed using valid ASCII
// characters
//   - horizontal: + | -
//   - vertical:   + | |
fn does_rectangle_contains_valid_chars(up_left: Point, right_down: Point, lines: &[&str]) -> bool {
    lines.iter()
            .skip(up_left.0 as usize)
            .take(1)
            .next()
            .unwrap()[up_left.1 as usize..right_down.1 as usize + 1]
        .chars()
        .all(|y| y == '+' || y == '-') &&
    lines.iter()
            .skip(right_down.0 as usize)
            .take(1)
            .next()
            .unwrap()[up_left.1 as usize..right_down.1 as usize + 1]
        .chars()
        .all(|y| y == '+' || y == '-') &&
    lines.iter()
        .skip(up_left.0 as usize)
        .take(right_down.0 as usize - up_left.0 as usize + 1)
        .map(|str| str.chars().skip(up_left.1 as usize).take(1).next().unwrap())
        .all(|c| c == '+' || c == '|') &&
    lines.iter()
        .skip(up_left.0 as usize)
        .take(right_down.0 as usize - up_left.0 as usize + 1)
        .map(|str| str.chars().skip(right_down.1 as usize).take(1).next().unwrap())
        .all(|c| c == '+' || c == '|')

}

fn count_rectangles(rectangle_points: &HashSet<Point>,
                    from: &HashSet<(Point, Point)>,
                    lines: &[&str])
                    -> i32 {
    let mut count = 0;
    for &(up_left_corner, right_down_corner) in from {
        if rectangle_points.contains(&up_left_corner) &&
           rectangle_points.contains(&right_down_corner) &&
           rectangle_points.contains(&(right_down_corner.0, up_left_corner.1)) &&
           rectangle_points.contains(&(up_left_corner.0, right_down_corner.1)) &&
           does_rectangle_contains_valid_chars(up_left_corner, right_down_corner, lines) {
            count += 1;
        }
    }
    count
}
<|endoftext|>


<commit_before>use super::{ Renderer, Renderable }; //, Physical, Syncable, Identifyable };
use std::rc::{ Rc, Weak };
use std::fmt;
use std::cell::RefCell;

//use cgmath::Matrix;

pub struct State {
    pub renderers: Vec<Box<Renderer>>,
    pub renderables: Vec<Box<Renderable>>,
    pub blob: u64,
}
impl State {}

pub struct Graph {
    root: Rc<RefCell<Node>>
}

pub struct Node { // le cliche classname
    id: u32,
    parent: Option<Weak<RefCell<Node>>>,
    children: Vec<Rc<RefCell<Node>>>,
    // TODO: figure out type signatures
 //   local_mat: Matrix<f32>,
 //  global_mat: Matrix<f32>,
}

impl Drop for Node {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let p = match self.parent {
            Some(_) => "*",
            None => "*root"
        };
        write!(f, "{} ->(id: {})", p, self.id);
        Ok(())
    }
}

impl Node {

    pub fn create(id: u32, parent: Option<Rc<RefCell<Node>>>) -> Rc<RefCell<Node>> {
        let prt = match parent {
            Some(ref p) => {
                Some(Rc::downgrade(p))
            },
            None => None
        };

        let node = Rc::new(
            RefCell::new(
                Node::new(id, prt)
            )
        );

        match parent {
            Some(ref p) => {
                p.borrow_mut().add_child(node.clone());
            },
            None => {}
        };

        node
    }

    pub fn find_root(node: Rc<RefCell<Node>>) -> Rc<RefCell<Node>> {
        match node.borrow().parent() {
            Some(p) => Node::find_root(p.clone()),
            None => return node.clone()
        }
    }

    fn new(id: u32, parent: Option<Weak<RefCell<Node>>>) -> Self {
        Node {
            id: id,
            parent: match parent {
                Some(p) => Some(p),
                None => None
            },
            children: Vec::new(),
            // local_mat: Matrix<f32>::one(),
            // global_mat: Matrix<f32>::one()
        }
    }

    /// Recursively find if this node is a child of another
    pub fn is_child_of(this: Rc<RefCell<Node>>, parent: Rc<RefCell<Node>>) -> bool {
        match this.borrow().parent() {
            Some(p) => {
                if p.borrow().id == parent.borrow().id {
                    true
                } else {
                    Node::is_child_of(p, parent)
                }
            },
            None => false
        }
    }

    pub fn reparent(child: Rc<RefCell<Node>>, target: Rc<RefCell<Node>>) -> Result<(), String> {
        if child.borrow().id == target.borrow().id {
            return Err("Cannot make node a child of itself.".to_string());
        }
        if  !Node::is_child_of(target.clone(), child.clone()) { // check for cycles
            match child.borrow().parent() {
                Some(old_parent) => {
                    old_parent.borrow_mut().remove_child(child.clone());
                },
                None => {}
            }
            child.borrow_mut().parent = Some(Rc::downgrade(&target.clone()));
            target.borrow_mut().add_child(child.clone());
            Ok(())
        } else {
            Err("Node cycle detected. Child is a parent of reparent target.".to_string()) // format for better debug msg
        }
    }

    pub fn remove_child(&mut self, child: Rc<RefCell<Node>>) {
        let mut idx: Option<usize> = None;
        for i in 0usize..self.children.len() {
            let child_id = self.children[i].borrow().id;
            if child_id == child.borrow().id {
                idx = Some(i);
                break;
            }
        }
        match idx {
           Some(i) => {
               self.children.remove(i);
           },
           _ => {}
        };
    }

    pub fn find_child(&self, id: u32) -> Option<Rc<RefCell<Node>>> {
        let option: Option<&Rc<RefCell<Node>>> =
            self.children.iter().find(|x| x.borrow().id == id);
        match option {
            Some(obj_ref) => Some(obj_ref.clone()),
            None => None
        }
    }

    pub fn children(&mut self) -> &mut Vec<Rc<RefCell<Node>>> {
        &mut self.children
    }

    fn add_child(&mut self, child: Rc<RefCell<Node>>) {
        if self.id != child.borrow().id {
            self.children.push(child);
        }
    }

    pub fn parent(&self) -> Option<Rc<RefCell<Node>>> {
        match self.parent {
            Some(ref p) => Some(p.upgrade().unwrap()),
            None => None
        }
    }

    pub fn debug_draw(&self, lvl: u32) {
        if lvl == 0 {
            println!("-- Hierarchy Dump --");
        }
        let c = if self.children.len() > 0 {
            "..."
        } else {
            ".leaf*"
        };
        println!(
            "{}{}{}",
            (0..lvl).map(|_| "....").collect::<String>(),
            self,
            c
        );
        for child in &self.children {
            child.borrow().debug_draw(lvl+1);
        }
    }

}

#[test]
fn traverse_nodes() {
    let root_ptr = Node::create(0, None);
    let child_ptr = Node::create(42, Some(root_ptr.clone()));

    let parent: Rc<RefCell<Node>> = child_ptr.borrow().parent().unwrap();
    parent.borrow_mut().add_child(child_ptr);

    let found_child = parent.borrow().find_child(42).unwrap();
    assert!(found_child.borrow().id == 42);
}

#[test]
fn find_root() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let found_root = Node::find_root(child.clone());
    assert!(root.borrow().id == found_root.borrow().id);
}

#[test]
fn is_child_of() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    assert!(Node::is_child_of(child.clone(), root.clone()));
    let r = Node::create(42, None);
    assert!( ! Node::is_child_of(child.clone(), r.clone()) );
}

#[test]
fn reparent() {
    let root = Node::create(0, None);

    let child = Node::create(2, Some(root.clone()));
    let original_child = root.borrow().find_child(2);
    assert!(original_child.is_some());

    let root2 = Node::create(1, None);
    Node::reparent(child.clone(), root2.clone());

    let found_root = Node::find_root(child);
    assert!(root2.borrow().id == found_root.borrow().id);

    let stale_child = root.borrow().find_child(2);
    assert!(stale_child.is_none());

    let actual_child = root2.borrow().find_child(2);
    assert!(actual_child.is_some());
}
#[test]
fn is_child_of_reparent() {
    let root = Node::create(0, None);
    let im = Node::create(1, Some(root.clone()));
    let child = Node::create(2, Some(im.clone()));
    assert!( Node::is_child_of(child.clone(), im.clone()) );
    assert!( Node::is_child_of(child.clone(), root.clone()) );

    let root2 = Node::create(3, None);
    let result = Node::reparent(im.clone(), root2.clone());

    assert!( result.is_ok() );
    assert!( Node::is_child_of(child.clone(), root2.clone()) );
}

#[test]
fn fails_to_reparent_to_self() {
    let root = Node::create(0, None);
    let result = Node::reparent(root.clone(), root.clone());
    assert!( result.is_err() );
}

#[test]
fn fails_to_reparent_causing_a_cycle() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let sibling = Node::create(2, Some(root.clone()));

    let result = Node::reparent(root.clone(), sibling.clone());
    assert!( result.is_err() );
}
<commit_msg>adding siblings() method<commit_after>use super::{ Renderer, Renderable }; //, Physical, Syncable, Identifyable };
use std::rc::{ Rc, Weak };
use std::fmt;
use std::cell::RefCell;

//use cgmath::Matrix;

pub struct State {
    pub renderers: Vec<Box<Renderer>>,
    pub renderables: Vec<Box<Renderable>>,
    pub blob: u64,
}
impl State {}

pub struct Graph {
    root: Rc<RefCell<Node>>
}

pub struct Node { // le cliche classname
    id: u32,
    parent: Option<Weak<RefCell<Node>>>,
    children: Vec<Rc<RefCell<Node>>>,
    // TODO: figure out type signatures
 //   local_mat: Matrix<f32>,
 //  global_mat: Matrix<f32>,
}

impl Drop for Node {
    fn drop(&mut self) {
        println!("Dropping {}", self.id);
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let p = match self.parent {
            Some(_) => "*",
            None => "*root"
        };
        write!(f, "{} ->(id: {})", p, self.id);
        Ok(())
    }
}

impl Node {

    pub fn create(id: u32, parent: Option<Rc<RefCell<Node>>>) -> Rc<RefCell<Node>> {
        let prt = match parent {
            Some(ref p) => {
                Some(Rc::downgrade(p))
            },
            None => None
        };

        let node = Rc::new(
            RefCell::new(
                Node::new(id, prt)
            )
        );

        match parent {
            Some(ref p) => {
                p.borrow_mut().add_child(node.clone());
            },
            None => {}
        };

        node
    }

    pub fn find_root(node: Rc<RefCell<Node>>) -> Rc<RefCell<Node>> {
        match node.borrow().parent() {
            Some(p) => Node::find_root(p.clone()),
            None => return node.clone()
        }
    }

    fn new(id: u32, parent: Option<Weak<RefCell<Node>>>) -> Self {
        Node {
            id: id,
            parent: match parent {
                Some(p) => Some(p),
                None => None
            },
            children: Vec::new(),
            // local_mat: Matrix<f32>::one(),
            // global_mat: Matrix<f32>::one()
        }
    }

    /// Recursively find if this node is a child of another
    pub fn is_child_of(this: Rc<RefCell<Node>>, parent: Rc<RefCell<Node>>) -> bool {
        match this.borrow().parent() {
            Some(p) => {
                if p.borrow().id == parent.borrow().id {
                    true
                } else {
                    Node::is_child_of(p, parent)
                }
            },
            None => false
        }
    }

    pub fn reparent(child: Rc<RefCell<Node>>, target: Rc<RefCell<Node>>) -> Result<(), String> {
        if child.borrow().id == target.borrow().id {
            return Err("Cannot make node a child of itself.".to_string());
        }
        if  !Node::is_child_of(target.clone(), child.clone()) { // check for cycles
            match child.borrow().parent() {
                Some(old_parent) => {
                    old_parent.borrow_mut().remove_child(child.clone());
                },
                None => {}
            }
            child.borrow_mut().parent = Some(Rc::downgrade(&target.clone()));
            target.borrow_mut().add_child(child.clone());
            Ok(())
        } else {
            Err("Node cycle detected. Child is a parent of reparent target.".to_string()) // format for better debug msg
        }
    }

    pub fn remove_child(&mut self, child: Rc<RefCell<Node>>) {
        let mut idx: Option<usize> = None;
        for i in 0usize..self.children.len() {
            let child_id = self.children[i].borrow().id;
            if child_id == child.borrow().id {
                idx = Some(i);
                break;
            }
        }
        match idx {
           Some(i) => {
               self.children.remove(i);
           },
           _ => {}
        };
    }

    pub fn find_child(&self, id: u32) -> Option<Rc<RefCell<Node>>> {
        let option: Option<&Rc<RefCell<Node>>> =
            self.children.iter().find(|x| x.borrow().id == id);
        match option {
            Some(obj_ref) => Some(obj_ref.clone()),
            None => None
        }
    }

    pub fn siblings(&self) -> Option<&Vec<Rc<RefCell<Node>>>> {
        match self.parent() {
            Some(p) => {
                Some(&p.borrow().children)
            },
            None => None
        }
    }

    pub fn children(&mut self) -> &mut Vec<Rc<RefCell<Node>>> {
        &mut self.children
    }

    fn add_child(&mut self, child: Rc<RefCell<Node>>) {
        if self.id != child.borrow().id {
            self.children.push(child);
        }
    }

    pub fn parent(&self) -> Option<Rc<RefCell<Node>>> {
        match self.parent {
            Some(ref p) => Some(p.upgrade().unwrap()),
            None => None
        }
    }

    pub fn debug_draw(&self, lvl: u32) {
        if lvl == 0 {
            println!("-- Hierarchy Dump --");
        }
        let c = if self.children.len() > 0 {
            "..."
        } else {
            ".leaf*"
        };
        println!(
            "{}{}{}",
            (0..lvl).map(|_| "....").collect::<String>(),
            self,
            c
        );
        for child in &self.children {
            child.borrow().debug_draw(lvl+1);
        }
    }

}

#[test]
fn traverse_nodes() {
    let root_ptr = Node::create(0, None);
    let child_ptr = Node::create(42, Some(root_ptr.clone()));

    let parent: Rc<RefCell<Node>> = child_ptr.borrow().parent().unwrap();
    parent.borrow_mut().add_child(child_ptr);

    let found_child = parent.borrow().find_child(42).unwrap();
    assert!(found_child.borrow().id == 42);
}

#[test]
fn find_root() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let found_root = Node::find_root(child.clone());
    assert!(root.borrow().id == found_root.borrow().id);
}

#[test]
fn is_child_of() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    assert!(Node::is_child_of(child.clone(), root.clone()));
    let r = Node::create(42, None);
    assert!( ! Node::is_child_of(child.clone(), r.clone()) );
}

#[test]
fn reparent() {
    let root = Node::create(0, None);

    let child = Node::create(2, Some(root.clone()));
    let original_child = root.borrow().find_child(2);
    assert!(original_child.is_some());

    let root2 = Node::create(1, None);
    Node::reparent(child.clone(), root2.clone());

    let found_root = Node::find_root(child);
    assert!(root2.borrow().id == found_root.borrow().id);

    let stale_child = root.borrow().find_child(2);
    assert!(stale_child.is_none());

    let actual_child = root2.borrow().find_child(2);
    assert!(actual_child.is_some());
}
#[test]
fn is_child_of_reparent() {
    let root = Node::create(0, None);
    let im = Node::create(1, Some(root.clone()));
    let child = Node::create(2, Some(im.clone()));
    assert!( Node::is_child_of(child.clone(), im.clone()) );
    assert!( Node::is_child_of(child.clone(), root.clone()) );

    let root2 = Node::create(3, None);
    let result = Node::reparent(im.clone(), root2.clone());

    assert!( result.is_ok() );
    assert!( Node::is_child_of(child.clone(), root2.clone()) );
}

#[test]
fn fails_to_reparent_to_self() {
    let root = Node::create(0, None);
    let result = Node::reparent(root.clone(), root.clone());
    assert!( result.is_err() );
}

#[test]
fn fails_to_reparent_causing_a_cycle() {
    let root = Node::create(0, None);
    let child = Node::create(1, Some(root.clone()));
    let sibling = Node::create(2, Some(root.clone()));

    let result = Node::reparent(root.clone(), sibling.clone());
    assert!( result.is_err() );
}
<|endoftext|>


<commit_before>//  notty is a new kind of terminal emulator.
//  Copyright (C) 2015 without boats
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
use std::io;
use std::ffi::CString;
use std::ops::Deref;
use std::ptr;
use std::sync::Arc;

extern crate libc;
extern crate notty;

use notty::terminal::Tty;

#[cfg(target_os="linux")]
const TIOCSWINSZ: libc::c_ulong = 0x5414;
#[cfg(target_os="macos")]
const TIOCSWINSZ: libc::c_ulong = 2148037735;

#[link(name="util")]
extern {
    fn forkpty(amaster: *mut libc::c_int,
               name: *mut libc::c_char,
               termp: *const libc::c_void,
               winsize: *const Winsize) -> libc::pid_t;
}

#[repr(C)]
struct Winsize {
    ws_row: libc::c_ushort,
    ws_col: libc::c_ushort,
    ws_xpixel: libc::c_ushort,
    ws_ypixel: libc::c_ushort,
}

pub fn pty(name: &str, width: u16, height: u16) -> (Reader, Writer) {
    let mut amaster = 0;
    let winsize = Winsize {
        ws_row: height as libc::c_ushort,
        ws_col: width as libc::c_ushort,
        ws_xpixel: 0,
        ws_ypixel: 0
    };
    match unsafe { forkpty(&mut amaster as *mut _,
                           ptr::null_mut(),
                           ptr::null(),
                           &winsize as *const _) } {
        0           => {
            let name = CString::new(name).unwrap();
            unsafe { libc::execvp(name.as_ptr(), ptr::null()); }
            unreachable!();
        }
        n if n > 0  => {
            let handle = Arc::new(Handle(amaster));
            (Reader(handle.clone()), Writer(handle.clone()))
        }
        _           => panic!("Fork failed.")
    }
}

pub struct Reader(Arc<Handle>);

impl Deref for Reader {
    type Target = Handle;
    fn deref(&self) -> &Handle {
        &*self.0
    }
}

impl io::Read for Reader {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match unsafe {libc::read(**self.0, buf.as_mut_ptr() as *mut _, buf.len() as libc::size_t)}
        {
            n if n >= 0 => Ok(n as usize),
            _           => Err(io::Error::last_os_error()),
        }
    }
}

pub struct Writer(Arc<Handle>);

impl Deref for Writer {
    type Target = Handle;
    fn deref(&self) -> &Handle {
        &*self.0
    }
}

impl io::Write for Writer {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match unsafe {libc::write(**self.0, buf.as_ptr() as *const _, buf.len() as libc::size_t)}
        {
            n if n >= 0 => Ok(n as usize),
            _           => Err(io::Error::last_os_error()),
        }
    }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

impl Tty for Writer {
    fn set_winsize(&mut self, width: u16, height: u16) -> io::Result<()> {
        (**self).set_winsize(width, height)
    }
}

pub struct Handle(libc::c_int);

impl Handle {
    pub fn set_winsize(&self, width: u16, height: u16) -> io::Result<()> {
        let winsize = Winsize {
            ws_row: height as libc::c_ushort,
            ws_col: width as libc::c_ushort,
            ws_xpixel: 0,
            ws_ypixel: 0
        };
        match unsafe { libc::ioctl(**self, TIOCSWINSZ, &winsize as *const _) } {
            -1  => Err(io::Error::last_os_error()),
            _   => Ok(()),
        }
    }
}

impl Deref for Handle {
    type Target = libc::c_int;
    fn deref(&self) -> &libc::c_int { &self.0 }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { libc::close(self.0); }
    }
}
<commit_msg>Minor/nitpicky style changes to tty module.<commit_after>//  notty is a new kind of terminal emulator.
//  Copyright (C) 2015 without boats
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
use std::io;
use std::ffi::CString;
use std::ops::Deref;
use std::ptr;
use std::sync::Arc;

extern crate libc;
extern crate notty;

use notty::terminal::Tty;

#[cfg(target_os="linux")]
const TIOCSWINSZ: libc::c_ulong = 0x5414;
#[cfg(target_os="macos")]
const TIOCSWINSZ: libc::c_ulong = 2148037735;

#[link(name="util")]
extern {
    fn forkpty(amaster: *mut libc::c_int,
               name: *mut libc::c_char,
               termp: *const libc::c_void,
               winsize: *const Winsize) -> libc::pid_t;
}

#[repr(C)]
struct Winsize {
    ws_row: libc::c_ushort,
    ws_col: libc::c_ushort,
    ws_xpixel: libc::c_ushort,
    ws_ypixel: libc::c_ushort,
}

pub fn pty(name: &str, width: u16, height: u16) -> (Reader, Writer) {
    let mut amaster = 0;
    let winsize = Winsize {
        ws_row: height as libc::c_ushort,
        ws_col: width as libc::c_ushort,
        ws_xpixel: 0,
        ws_ypixel: 0
    };
    match unsafe {
        forkpty(&mut amaster as *mut _,
                ptr::null_mut(),
                ptr::null(),
                &winsize as *const _)
    } {
        0           => {
            let name = CString::new(name).unwrap();
            unsafe {
                libc::execvp(name.as_ptr(),
                             ptr::null());
            }
            unreachable!();
        }
        n if n > 0  => {
            let handle = Arc::new(Handle(amaster));
            (Reader(handle.clone()), Writer(handle.clone()))
        }
        _           => panic!("Fork failed.")
    }
}

pub struct Reader(Arc<Handle>);

impl Deref for Reader {
    type Target = Handle;
    fn deref(&self) -> &Handle {
        &*self.0
    }
}

impl io::Read for Reader {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match unsafe {
            libc::read(**self.0,
                       buf.as_mut_ptr() as *mut _,
                       buf.len() as libc::size_t)
        } {
            n if n >= 0 => Ok(n as usize),
            _           => Err(io::Error::last_os_error()),
        }
    }
}

pub struct Writer(Arc<Handle>);

impl Deref for Writer {
    type Target = Handle;
    fn deref(&self) -> &Handle {
        &*self.0
    }
}

impl io::Write for Writer {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match unsafe {
            libc::write(**self.0,
                        buf.as_ptr() as *const _,
                        buf.len() as libc::size_t)
        } {
            n if n >= 0 => Ok(n as usize),
            _           => Err(io::Error::last_os_error()),
        }
    }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

impl Tty for Writer {
    fn set_winsize(&mut self, width: u16, height: u16) -> io::Result<()> {
        (**self).set_winsize(width, height)
    }
}

pub struct Handle(libc::c_int);

impl Handle {
    pub fn set_winsize(&self, width: u16, height: u16) -> io::Result<()> {
        let winsize = Winsize {
            ws_row: height as libc::c_ushort,
            ws_col: width as libc::c_ushort,
            ws_xpixel: 0,
            ws_ypixel: 0
        };
        match unsafe {
            libc::ioctl(**self,
                        TIOCSWINSZ,
                        &winsize as *const _)
        } {
            -1  => Err(io::Error::last_os_error()),
            _   => Ok(()),
        }
    }
}

impl Deref for Handle {
    type Target = libc::c_int;
    fn deref(&self) -> &libc::c_int { &self.0 }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.0);
        }
    }
}
<|endoftext|>


<commit_before>// run-pass
// Test use of stabilized const fns in std formerly using individual feature gates.

use std::cell::Cell;

const CELL: Cell<i32> = Cell::new(42);

fn main() {
    let v = CELL.get();
    CELL.set(v+1);

    assert_eq!(CELL.get(), v);
}
<commit_msg>remove const-fn-feature-flags test<commit_after><|endoftext|>


<commit_before>use std::io::Read;
use std::collections::HashMap;

use iron::prelude::*;
use iron::status;
use rustc_serialize::json::{self, Json};

use document::Document;
use super::persistent;
use super::utils::{json_response, index_not_found_response};
use super::super::Globals;

pub fn view_post_bulk(req: &mut Request) -> IronResult<Response> {
    let ref glob = get_globals!(req);

    // Lock index array
    let mut indices = glob.indices.write().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let mut items = Vec::new();

    // Iterate
    let mut payload_lines = payload.split('\n');
    loop {
        let action_line = payload_lines.next();

        // Check if end of input
        if action_line == None || action_line == Some("") {
            break;
        }

        // Parse action line
        let action_json = parse_json!(&action_line.unwrap());

        // Check action
        // Action should be an object with only one key, the key name indicates the action and
        // the value is the parameters for that action
        let action_name = action_json.as_object().unwrap().keys().nth(0).unwrap();
        let action_params = action_json.as_object()
                                       .unwrap()
                                       .get(action_name)
                                       .unwrap()
                                       .as_object()
                                       .unwrap();

        let doc_id = action_params.get("_id").unwrap().as_string().unwrap();
        let doc_type = action_params.get("_type").unwrap().as_string().unwrap();
        let doc_index = action_params.get("_index").unwrap().as_string().unwrap();

        match action_name.as_ref() {
            "index" => {
                let doc_line = payload_lines.next();
                let doc_json = parse_json!(&doc_line.unwrap());;

                // Find index
                let mut index = match indices.get_mut(doc_index) {
                    Some(index) => index,
                    None => {
                        return Ok(index_not_found_response());
                    }
                };

                let doc = {
                    // Find mapping
                    let mapping = match index.get_mapping_by_name(doc_type) {
                        Some(mapping) => mapping,
                        None => {
                            return Ok(json_response(status::NotFound, "{\"message\": \"Mapping not found\"}"));
                        }
                    };

                    // Create document
                    if let Some(data) = json_from_request_body!(req) {
                        Document::from_json(doc_id.to_string(), data, mapping)
                    } else {
                        return Ok(json_response(status::NotFound, "{\"message\": \"No data\"}"));
                    }
                };

                index.insert_or_update_document(doc);

                // Insert into "items" array
                let mut item = HashMap::new();
                // TODO: "create" may not always be right
                item.insert("create", action_params.clone());
                items.push(item);
            }
            _ => {
                warn!("Unrecognised action! {}", action_name);
            }
        }
    }

    return Ok(json_response(status::Ok,
                            format!("{{\"took\": {}, \"items\": {}}}",
                                    items.len(),
                                    json::encode(&items).unwrap())));
}
<commit_msg>Fixed bulk API<commit_after>use std::io::Read;
use std::collections::HashMap;

use iron::prelude::*;
use iron::status;
use rustc_serialize::json::{self, Json};

use document::Document;
use super::persistent;
use super::utils::{json_response, index_not_found_response};
use super::super::Globals;

pub fn view_post_bulk(req: &mut Request) -> IronResult<Response> {
    let ref glob = get_globals!(req);

    // Lock index array
    let mut indices = glob.indices.write().unwrap();

    // Load data from body
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();

    let mut items = Vec::new();

    // Iterate
    let mut payload_lines = payload.split('\n');
    loop {
        let action_line = payload_lines.next();

        // Check if end of input
        if action_line == None || action_line == Some("") {
            break;
        }

        // Parse action line
        let action_json = parse_json!(&action_line.unwrap());

        // Check action
        // Action should be an object with only one key, the key name indicates the action and
        // the value is the parameters for that action
        let action_name = action_json.as_object().unwrap().keys().nth(0).unwrap();
        let action_params = action_json.as_object()
                                       .unwrap()
                                       .get(action_name)
                                       .unwrap()
                                       .as_object()
                                       .unwrap();

        let doc_id = action_params.get("_id").unwrap().as_string().unwrap();
        let doc_type = action_params.get("_type").unwrap().as_string().unwrap();
        let doc_index = action_params.get("_index").unwrap().as_string().unwrap();

        match action_name.as_ref() {
            "index" => {
                let doc_line = payload_lines.next();
                let doc_json = parse_json!(&doc_line.unwrap());;

                // Find index
                let mut index = match indices.get_mut(doc_index) {
                    Some(index) => index,
                    None => {
                        return Ok(index_not_found_response());
                    }
                };

                let doc = {
                    // Find mapping
                    let mapping = match index.get_mapping_by_name(doc_type) {
                        Some(mapping) => mapping,
                        None => {
                            return Ok(json_response(status::NotFound, "{\"message\": \"Mapping not found\"}"));
                        }
                    };

                    // Create document
                    Document::from_json(doc_id.to_string(), doc_json, mapping)
                };

                index.insert_or_update_document(doc);

                // Insert into "items" array
                let mut item = HashMap::new();
                // TODO: "create" may not always be right
                item.insert("create", action_params.clone());
                items.push(item);
            }
            _ => {
                warn!("Unrecognised action! {}", action_name);
            }
        }
    }

    return Ok(json_response(status::Ok,
                            format!("{{\"took\": {}, \"items\": {}}}",
                                    items.len(),
                                    json::encode(&items).unwrap())));
}
<|endoftext|>


<commit_before>use nom::{be_i8, be_i16, be_i32, be_i64, be_u8, be_u16, be_u32, be_u64, float, double};
use std::collections::HashMap;

pub type UOctet    = u8;
pub type UShort    = u16;
pub type ULong     = u32;
pub type ULongLong = u64;
pub type Timestamp = u64;

named!(pub short_string<&str>,
    do_parse!(
        length: be_u8             >>
        string: take_str!(length) >>
        (string)
    )
);

named!(pub long_string<&str>,
    do_parse!(
        length: be_u32            >>
        string: take_str!(length) >>
        (string)
    )
);
//a long string is a BE u32 followed by data. Maybe handle this in the state machine?

// Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits, or
// underlines, to a maximum length of 128 characters.
// The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD
// signal a connection exception with reply code 503 (syntax error).

#[derive(Clone,Debug,PartialEq)]
pub enum Value {
  Boolean(bool),
  ShortShortInt(i8),
  ShortShortUInt(u8),
  ShortInt(i16),
  ShortUInt(u16),
  LongInt(i32),
  LongUInt(u32),
  LongLongInt(i64),
  LongLongUInt(u64),
  Float(f32),
  Double(f64),
  Decimal(f32),
  ShortString(String),
  LongString(String),
  Array(Vec<Value>),
  Timestamp(u64),
  Table(HashMap<String,Value>),
  None
}

named!(pub value<Value>,
  switch!(map!(be_u8, |u| u as char),
    't' => call!(parse_boolean)          |
    //FIXME: the spec says b for i8, B for u8, but U for i16, u for u16, I for i32, i for u32, etc
    // is that right?
    'b' => call!(parse_short_short_int)  |
    'B' => call!(parse_short_short_uint) |
    'U' => call!(parse_short_int)        |
    'u' => call!(parse_short_uint)       |
    'I' => call!(parse_long_int)         |
    'i' => call!(parse_long_uint)        |
    'L' => call!(parse_long_long_int)    |
    'l' => call!(parse_long_long_uint)   |
    'f' => call!(parse_float)            |
    'd' => call!(parse_double)           |
    'D' => call!(parse_decimal)          |
    's' => call!(parse_short_string)     |
    'S' => call!(parse_long_string)      |
    'A' => call!(parse_array)            |
    'T' => call!(parse_timestamp)        |
    'F' => call!(parse_table)            |
    'V' => value!(Value::None)
  )
);
named!(pub field_name_value<(String, Value)>,
  tuple!(map!(short_string, |s:&str| s.to_string()), value)
);

named!(parse_boolean<Value>,
  map!(be_u8, |u| Value::Boolean(u != 0))
);

named!(parse_short_short_int<Value>,
  map!(be_i8, |i| Value::ShortShortInt(i))
);
named!(parse_short_short_uint<Value>,
  map!(be_u8, |i| Value::ShortShortUInt(i))
);
named!(parse_short_int<Value>,
  map!(be_i16, |i| Value::ShortInt(i))
);
named!(parse_short_uint<Value>,
  map!(be_u16, |i| Value::ShortUInt(i))
);
named!(parse_long_int<Value>,
  map!(be_i32, |i| Value::LongInt(i))
);
named!(parse_long_uint<Value>,
  map!(be_u32, |i| Value::LongUInt(i))
);
named!(parse_long_long_int<Value>,
  map!(be_i64, |i| Value::LongLongInt(i))
);
named!(parse_long_long_uint<Value>,
  map!(be_u64, |i| Value::LongLongUInt(i))
);
named!(parse_float<Value>,
  map!(float, |i| Value::Float(i))
);
named!(parse_double<Value>,
  map!(double, |i| Value::Double(i))
);
named!(parse_decimal<Value>,
  map!(float, |i| Value::Decimal(i))
);
named!(parse_short_string<Value>,
  map!(short_string, |s:&str| Value::ShortString(s.to_string()))
);

named!(parse_long_string<Value>,
  map!(long_string, |s:&str| Value::LongString(s.to_string()))
);

named!(parse_array<Value>,
  do_parse!(
    quantity: be_u32 >>
    //FIXME: the spec specifies a long int there, but a long uint for the table?
    vec: map!(count!(value, quantity as usize), |v| Value::Array(v)) >>
    (vec)
  )
);
named!(parse_timestamp<Value>,
  map!(be_u64, |i| Value::Timestamp(i))
);
named!(parse_table<Value>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(count!(field_name_value, quantity as usize), |v:Vec<(String,Value)>| {
      Value::Table(v.iter().cloned().collect())
    }) >>
    (h)
  )
);

named!(pub field_table<HashMap<String,Value>>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(count!(field_name_value, quantity as usize), |v:Vec<(String,Value)>| {
      v.iter().cloned().collect()
    }) >>
    (h)
  )
);
<commit_msg>the number prefixing a table is the byte size, not the number of elements<commit_after>use nom::{be_i8, be_i16, be_i32, be_i64, be_u8, be_u16, be_u32, be_u64, float, double};
use std::collections::HashMap;

pub type UOctet    = u8;
pub type UShort    = u16;
pub type ULong     = u32;
pub type ULongLong = u64;
pub type Timestamp = u64;

named!(pub short_string<&str>,
    do_parse!(
        length: be_u8             >>
        string: take_str!(length) >>
        (string)
    )
);

named!(pub long_string<&str>,
    do_parse!(
        length: be_u32            >>
        string: take_str!(length) >>
        (string)
    )
);
//a long string is a BE u32 followed by data. Maybe handle this in the state machine?

// Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits, or
// underlines, to a maximum length of 128 characters.
// The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD
// signal a connection exception with reply code 503 (syntax error).

#[derive(Clone,Debug,PartialEq)]
pub enum Value {
  Boolean(bool),
  ShortShortInt(i8),
  ShortShortUInt(u8),
  ShortInt(i16),
  ShortUInt(u16),
  LongInt(i32),
  LongUInt(u32),
  LongLongInt(i64),
  LongLongUInt(u64),
  Float(f32),
  Double(f64),
  Decimal(f32),
  ShortString(String),
  LongString(String),
  Array(Vec<Value>),
  Timestamp(u64),
  Table(HashMap<String,Value>),
  None
}

named!(pub value<Value>,
  switch!(map!(be_u8, |u| u as char),
    't' => call!(parse_boolean)          |
    //FIXME: the spec says b for i8, B for u8, but U for i16, u for u16, I for i32, i for u32, etc
    // is that right?
    'b' => call!(parse_short_short_int)  |
    'B' => call!(parse_short_short_uint) |
    'U' => call!(parse_short_int)        |
    'u' => call!(parse_short_uint)       |
    'I' => call!(parse_long_int)         |
    'i' => call!(parse_long_uint)        |
    'L' => call!(parse_long_long_int)    |
    'l' => call!(parse_long_long_uint)   |
    'f' => call!(parse_float)            |
    'd' => call!(parse_double)           |
    'D' => call!(parse_decimal)          |
    's' => call!(parse_short_string)     |
    'S' => call!(parse_long_string)      |
    'A' => call!(parse_array)            |
    'T' => call!(parse_timestamp)        |
    'F' => call!(parse_table)            |
    'V' => value!(Value::None)
  )
);
named!(pub field_name_value<(String, Value)>,
  tuple!(map!(short_string, |s:&str| s.to_string()), value)
);

named!(parse_boolean<Value>,
  map!(be_u8, |u| Value::Boolean(u != 0))
);

named!(parse_short_short_int<Value>,
  map!(be_i8, |i| Value::ShortShortInt(i))
);
named!(parse_short_short_uint<Value>,
  map!(be_u8, |i| Value::ShortShortUInt(i))
);
named!(parse_short_int<Value>,
  map!(be_i16, |i| Value::ShortInt(i))
);
named!(parse_short_uint<Value>,
  map!(be_u16, |i| Value::ShortUInt(i))
);
named!(parse_long_int<Value>,
  map!(be_i32, |i| Value::LongInt(i))
);
named!(parse_long_uint<Value>,
  map!(be_u32, |i| Value::LongUInt(i))
);
named!(parse_long_long_int<Value>,
  map!(be_i64, |i| Value::LongLongInt(i))
);
named!(parse_long_long_uint<Value>,
  map!(be_u64, |i| Value::LongLongUInt(i))
);
named!(parse_float<Value>,
  map!(float, |i| Value::Float(i))
);
named!(parse_double<Value>,
  map!(double, |i| Value::Double(i))
);
named!(parse_decimal<Value>,
  map!(float, |i| Value::Decimal(i))
);
named!(parse_short_string<Value>,
  map!(short_string, |s:&str| Value::ShortString(s.to_string()))
);

named!(parse_long_string<Value>,
  map!(long_string, |s:&str| Value::LongString(s.to_string()))
);

named!(parse_array<Value>,
  do_parse!(
    quantity: be_u32 >>
    //FIXME: the spec specifies a long int there, but a long uint for the table?
    vec: map!(count!(value, quantity as usize), |v| Value::Array(v)) >>
    (vec)
  )
);
named!(parse_timestamp<Value>,
  map!(be_u64, |i| Value::Timestamp(i))
);
named!(parse_table<Value>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(flat_map!(take!(quantity as usize), many0!(field_name_value)), |v:Vec<(String,Value)>| {
      Value::Table(v.iter().cloned().collect())
    }) >>
    (h)
  )
);

named!(pub field_table<HashMap<String,Value>>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(flat_map!(take!(quantity as usize), many0!(complete!(field_name_value))), |v:Vec<(String,Value)>| {
      v.iter().cloned().collect()
    }) >>
    (h)
  )
);
<|endoftext|>