<commit_before>extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::*;

#[proc_macro_derive(ColladaElement, attributes(name, attribute, child))]
pub fn derive(input: TokenStream) -> TokenStream {
    // Parse the string representation.
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();

    // Build the impl.
    match generate_impl(ast) {
        Ok(gen) => {
            let result = gen.parse().unwrap();
            result
        }
        Err(error) => { panic!("{}", error) }
    }
}

fn process_derive_input(input: DeriveInput) -> Result<ElementConfiguration, String> {
    let struct_ident = input.ident;

    // Process the top-level attributes on the type to find the `#[name = "foo"]` attribute.
    // -------------------------------------------------------------------------------------
    let element_name = {
        let mut element_name = None;

        for attribute in ast.attrs {
            match attribute.value {
                MetaItem::NameValue(attr_name, Lit::Str(value, _)) => {
                    if attr_name == "name" {
                        element_name = Some(value);
                    }
                }

                _ => {}
            }
        }

        element_name.ok_or(r#"Type must have `#[name = "..."]` attribute when using `#[derive(ColladaElement)]`"#)?
    };

    // Process the body of the type and gather information about attributes and children.
    // ----------------------------------------------------------------------------------
    let mut children = Vec::new();
    let mut attributes = Vec::new();

    let fields = match input.body {
        Body::Enum(_) => { return Err("`#[derive(ColladaElement)]` does not support enum types")?; }

        Body::Struct(VariantData::Struct(fields)) => { fields }

        Body::Struct(VariantData::Tuple(_)) => { return Err("`#[derive(ColladaElement)]` does not support tuple structs")?; }

        Body::Struct(VariantData::Unit) => { Vec::new() }
    };

    for field in fields {
        // We only support struct-structs, so all fields will have an ident.
        let member_name = field.ident.unwrap();

        // Determine the data type and occurrences for the member.
        let path = match field.ty {
            Ty::Path(None, path) => { path }
            _ => { return Err("`#[derive(ColladaElement)]` doesn't support this member type")?; }
        };

        // Determine the number of occurrences based on the declared type:
        //
        // - `Option<T>` is optional with inner type `T`.
        // - `Vec<T>` is repeating with inner type `T`.
        // - Everything else is required with inner type as declared.
        let segment = path.segments[0].clone();

        // We only support angle bracket parameters (because we're only looking for `Option<T>`
        // and `Vec<T>`), so extract the parameter data and throw away all others.
        let parameter_data = match segment.parameters {
            PathParameters::AngleBracketed(param) => { param }
            _ => { return Err("Round brace function parameters are not supported")?; }
        };

        // Depending on the number of parameters (0 or 1) we determine the occurrences and the
        // type of the actual data.
        let (occurrences, inner_type) = if parameter_data.types.len() == 0 {
            // No type parameters, so we're not looking at `Option<T>` or `Vec<T>`. That means the
            // child is required and that the field's type is the type of the child data.
            (ChildOccurrences::Required, field.ty)
        } else {
            // There's 1 type parameter, so determine if we're looking at an `Option<T>`, which
            // means optional occurrences of a `T`, or a `Vec<T>`, which means optional many
            // occurrences of `T`.
            let inner_type = parameter_data.types[0].clone();
            match segment.ident.as_ref() {
                "Option" => { (ChildOccurrences::Optional, inner_type) }
                "Vec" => { (ChildOccurrences::OptionalMany, inner_type) }
                _ => { return Err("Unexpected child type with parameters, only `Vec<T>` and `Option<T>` are allowed to have type parameters")?; }
            }
        };

        // Determine whether we're looking at a child or an attribute based on whether the member
        // has a `#[child]` or an `#[attribute]` attribute.
        unimplemented!();
    }

    Ok(ElementConfiguration {
        struct_ident: struct_ident,
        element_name: element_name,
        attributes: attributes,
        children: children,
    })
}

struct ElementConfiguration {
    struct_ident: Ident,
    element_name: String,
    attributes: Vec<Attribute>,
    children: Vec<Child>,
}

enum AttributeOccurrences {
    RequiredOptional,
}

struct Attribute {
    member_name: Ident,
    attrib_name: String,
    occurrences: AttributeOccurrences,
    ty: DataType,
}

enum DataType {
    String,
    ColladaElement(Ident),
}

struct Child {
    member_name: Ident,
    element_name: String,
    occurrences: ChildOccurrences,
    ty: DataType,
}

enum ChildOccurrences {
    Optional,
    Required,
    OptionalMany,
    RequiredMany,
}

fn generate_impl(derive_input: DeriveInput) -> Result<quote::Tokens, String> {
    let ElementConfiguration { struct_ident, element_name, children, attributes } = process_derive_input(derive_input)?;

    // Generate declarations for the member variables of the struct.
    // -------------------------------------------------------------
    let member_decls = {
        match ast.body {
            Body::Enum(_) => { panic!("`#[derive(ColladaElement)]` does not yet support enum types"); }

            Body::Struct(VariantData::Unit) => { quote! {} }

            Body::Struct(VariantData::Tuple(_)) => { panic!("`#[derive(ColladaElement)]` does not yet support tuple structs"); }

            Body::Struct(VariantData::Struct(ref fields)) => {
                let decls = fields
                    .iter()
                    .map(|field| {
                        let ident = field.ident.as_ref().unwrap();
                        quote! { let mut #ident = None; }
                    });

                quote! {
                    #( #decls )*
                }
            }
        }
    };

    // Generate code for parsing attributes.
    // -------------------------------------
    let attributes_impl = {
        // TODO: Actualy look at the members and find out what attributes we should be looking for.
        // For now we'll return a default impl that assumes there should be no attributes.
        quote! {
            ::utils::verify_attributes(reader, #element_name, attributes)?;
        }
    };

    // Generate code for parsing children.
    // -----------------------------------
    let children_impl = {
        match ast.body {
            Body::Enum(_) => { panic!("`#[derive(ColladaElement)]` does not yet support enum types"); }

            Body::Struct(VariantData::Unit) => { quote! {} }

            Body::Struct(VariantData::Tuple(_)) => { panic!("`#[derive(ColladaElement)]` does not yet support tuple structs"); }

            Body::Struct(VariantData::Struct(ref fields)) => {
                let decls = fields.iter()
                    .filter_map(|field| {
                        // Determine whether the element is a child or attribute based on the
                        // attributes for the field. Here we only care about children.
                        for attribute in &field.attrs {
                            // Determine the name of the child element based on the attributes on
                            // the element.
                            let child_element_name = match attribute.value {
                                // Children declared as `#[child]`.
                                MetaItem::Word(ref ident) => {
                                    if ident == "child" {
                                        field.ident.clone().unwrap().to_string()
                                    } else {
                                        continue;
                                    }
                                }

                                // Children declared as `#[child(element = "foo")]`
                                MetaItem::List(..) => {
                                    unimplemented!()
                                }

                                MetaItem::NameValue(..) => { continue; }
                            };

                            let field_ident = field.ident.clone().unwrap();

                            let occurrences = {
                                // TODO: Determine child occurrences based on type:
                                //
                                // - `Option<T>` is optional.
                                // - `Vec<T>` is many.
                                // - `Vec<T>` with `#[required]` attribute is required many.
                                // - All others are required.
                                quote! { Optional }
                            };

                            let child_action = {
                                // TODO: Determine child action based on type. Specific types (e.g.
                                // `String`) get special handling, but anything that implements
                                // `ColladaElement` will use that impl.
                                quote! {
                                    utils::verify_attributes(reader, #child_element_name, attributes)?;
                                    #field_ident = utils::optional_text_contents(reader, #child_element_name).map(Into::into)?;
                                    Ok(())
                                }
                            };

                            return Some(quote! {
                                ChildConfiguration {
                                    name: #child_element_name,
                                    occurrences: #occurrences,

                                    action: &mut |reader, attributes| {
                                        #child_action
                                    },
                                }
                            });
                        }

                        None
                    },
                );

                quote! {
                    ElementConfiguration {
                        name: #element_name,
                        children: &mut [
                            #(
                                #decls
                            ),*
                        ],
                    }.parse_children(reader)?;
                }
            }
        }
    };

    // Generate code to construct final result.
    // ----------------------------------------
    let result_decl = {
        match ast.body {
            Body::Enum(_) => { panic!("`#[derive(ColladaElement)]` does not yet support enum types"); }

            Body::Struct(VariantData::Unit) => { quote! {} }

            Body::Struct(VariantData::Tuple(_)) => { panic!("`#[derive(ColladaElement)]` does not yet support tuple structs"); }

            Body::Struct(VariantData::Struct(ref fields)) => {
                let decls = fields
                    .iter()
                    .map(|field| {
                        let ident = field.ident.as_ref().unwrap();
                        quote! { #ident: #ident }
                    });

                quote! {
                    Ok(#type_name {
                        #( #decls ),*
                    })
                }
            }
        }
    };

    // Put all the pieces together.
    // ----------------------------
    Ok(quote! {
        impl ColladaElement for #type_name {
            fn parse_element<R: Read>(reader: &mut EventReader<R>, attributes: Vec<OwnedAttribute>) -> Result<Self> {
                // use utils;
                // use utils::{ElementConfiguration, ChildConfiguration};

                #member_decls

                #attributes_impl

                #children_impl

                #result_decl
            }

            fn name() -> &'static str {
                #element_name
            }
        }
    })
}
<commit_msg>More progress on parse-collada-derive<commit_after>extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use quote::{Tokens, ToTokens};
use syn::*;

#[proc_macro_derive(ColladaElement, attributes(name, attribute, child))]
pub fn derive(input: TokenStream) -> TokenStream {
    // Parse the string representation.
    let ast = syn::parse_derive_input(&input.to_string()).unwrap();

    // Build the impl.
    match generate_impl(ast) {
        Ok(gen) => {
            let result = gen.parse().unwrap();
            result
        }
        Err(error) => { panic!("{}", error) }
    }
}

fn process_derive_input(input: DeriveInput) -> Result<ElementConfiguration, String> {
    let struct_ident = input.ident;

    // Process the top-level attributes on the type to find the `#[name = "foo"]` attribute.
    // -------------------------------------------------------------------------------------
    let element_name = {
        let mut element_name = None;

        for attribute in input.attrs {
            match attribute.value {
                MetaItem::NameValue(attr_name, Lit::Str(value, _)) => {
                    if attr_name == "name" {
                        element_name = Some(value);
                    }
                }

                _ => {}
            }
        }

        element_name.ok_or(r#"Type must have `#[name = "..."]` attribute when using `#[derive(ColladaElement)]`"#)?
    };

    // Process the body of the type and gather information about attributes and children.
    // ----------------------------------------------------------------------------------
    let mut children = Vec::new();
    let mut attributes = Vec::new();

    let fields = match input.body {
        Body::Enum(_) => { return Err("`#[derive(ColladaElement)]` does not support enum types")?; }

        Body::Struct(VariantData::Struct(fields)) => { fields }

        Body::Struct(VariantData::Tuple(_)) => { return Err("`#[derive(ColladaElement)]` does not support tuple structs")?; }

        Body::Struct(VariantData::Unit) => { Vec::new() }
    };

    for field in fields {
        // We only support struct-structs, so all fields will have an ident.
        let member_name = field.ident.unwrap();

        // Determine the data type and occurrences for the member.
        let path = match field.ty {
            Ty::Path(None, path) => { path }
            _ => { return Err("`#[derive(ColladaElement)]` doesn't support this member type")?; }
        };

        // Determine the number of occurrences based on the declared type:
        //
        // - `Option<T>` is optional with inner type `T`.
        // - `Vec<T>` is repeating with inner type `T`.
        // - Everything else is required with inner type as declared.
        let segment = path.segments[0].clone();

        // We only support angle bracket parameters (because we're only looking for `Option<T>`
        // and `Vec<T>`), so extract the parameter data and throw away all others.
        let parameter_data = match segment.parameters {
            PathParameters::AngleBracketed(param) => { param }
            _ => { return Err("Round brace function parameters are not supported")?; }
        };

        // Depending on the number of parameters (0 or 1) we determine the occurrences and the
        // type of the actual data.
        let (occurrences, inner_type) = if parameter_data.types.len() == 0 {
            // No type parameters, so we're not looking at `Option<T>` or `Vec<T>`. That means the
            // child is required and that the field's type is the type of the child data.
            (ChildOccurrences::Required, field.ty)
        } else {
            // There's 1 type parameter, so determine if we're looking at an `Option<T>`, which
            // means optional occurrences of a `T`, or a `Vec<T>`, which means optional many
            // occurrences of `T`.
            let inner_type = parameter_data.types[0].clone();
            match segment.ident.as_ref() {
                "Option" => { (ChildOccurrences::Optional, inner_type) }
                "Vec" => { (ChildOccurrences::OptionalMany, inner_type) }
                _ => { return Err("Unexpected child type with parameters, only `Vec<T>` and `Option<T>` are allowed to have type parameters")?; }
            }
        };

        // Determine whether we're looking at a child or an attribute based on whether the member
        // has a `#[child]` or an `#[attribute]` attribute.
        unimplemented!();
    }

    Ok(ElementConfiguration {
        struct_ident: struct_ident,
        element_name: element_name,
        attributes: attributes,
        children: children,
    })
}

struct ElementConfiguration {
    struct_ident: Ident,
    element_name: String,
    attributes: Vec<Attribute>,
    children: Vec<Child>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum AttributeOccurrences {
    Optional,
    Required,
}

struct Attribute {
    member_name: Ident,
    attrib_name: String,
    occurrences: AttributeOccurrences,
    ty: DataType,
}

enum DataType {
    String,
    ColladaElement(Ident),
}

struct Child {
    member_name: Ident,
    element_name: String,
    occurrences: ChildOccurrences,
    ty: DataType,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ChildOccurrences {
    Optional,
    Required,
    OptionalMany,
    RequiredMany,
}

impl ToTokens for ChildOccurrences {
    fn to_tokens(&self, tokens: &mut Tokens) {
        match *self {
            ChildOccurrences::Optional => { tokens.append("Optional"); }

            ChildOccurrences::Required => { tokens.append("Required"); }

            ChildOccurrences::OptionalMany => { tokens.append("OptionalMany"); }

            ChildOccurrences::RequiredMany => { tokens.append("RequiredMany"); }
        }
    }
}

fn generate_impl(derive_input: DeriveInput) -> Result<quote::Tokens, String> {
    let ElementConfiguration { struct_ident, element_name, attributes, children } = process_derive_input(derive_input)?;

    // Generate declarations for the member variables of the struct.
    // -------------------------------------------------------------
    let member_decls = {
        let attribs = attributes.iter()
            .map(|attrib| {
                let ident = attrib.member_name;
                quote! { let mut #ident = None; }
            });
        let childs = children.iter()
            .map(|child| {
                let ident = child.member_name;
                quote! { let mut #ident = None; }
            });

        quote! {
            #( #attribs )*
            #( #childs )*
        }
    };

    // Generate code for parsing attributes.
    // -------------------------------------
    let attributes_impl = {
        let matches = attributes.iter()
            .map(|attrib| {
                let &Attribute { ref member_name, ref attrib_name, .. } = attrib;
                quote! {
                    #attrib_name => { #member_name = Some(attribute.value.parse()?); }
                }
            });

        let attrib_names = attributes.iter()
            .map(|attrib| { &*attrib.attrib_name });

        let required_attribs = attributes.iter()
            .filter(|attrib| { attrib.occurrences == AttributeOccurrences::Required })
            .map(|attrib| {
                let &Attribute { ref member_name, ref attrib_name, .. } = attrib;
                quote! {
                    let #member_name = #member_name.ok_or(Error {
                        position: reader.position(),
                        kind: ErrorKind::MissingAttribute {
                            element: #element_name,
                            attribute: #attrib_name,
                        },
                    })?;
                }
            });

        quote! {
            for attribute in attributes {
                match &*attribute.name.local_name {
                    #( #matches )*

                    attrib_name @ _ => {
                        return Err(Error {
                            position: reader.position(),
                            kind: ErrorKind::UnexpectedAttribute {
                                element: #element_name,
                                attribute: attrib_name.into(),
                                expected: vec![ #( #attrib_names ),* ],
                            },
                        })
                    }
                }
            }

            #( #required_attribs )*
        }
    };

    // Generate code for parsing children.
    // -----------------------------------
    let children_impl = {
        let decls = children.iter()
            .map(|child| {
                let &Child { ref member_name, ref element_name, occurrences, ref ty } = child;

                let handle_result = match occurrences {
                    ChildOccurrences::Optional | ChildOccurrences::Required => {
                        quote! { #member_name = Some(result); }
                    }

                    ChildOccurrences::OptionalMany | ChildOccurrences::RequiredMany => {
                        quote! { #member_name.push(result); }
                    }
                };

                quote! {
                    ChildConfiguration {
                        name: #element_name,
                        occurrences: #occurrences,

                        action: &mut |reader, attributes| {
                            let result = #ty::parse_element()?;

                            #handle_result

                            Ok(())
                        },
                    }
                }
            });

        quote! {
            ElementConfiguration {
                name: #element_name,
                children: &mut [
                    #( #decls ),*
                ],
            }.parse_children(reader)?;
        }
    };

    // Generate code to construct final result.
    // ----------------------------------------
    let result_decl = {
        match ast.body {
            Body::Enum(_) => { panic!("`#[derive(ColladaElement)]` does not yet support enum types"); }

            Body::Struct(VariantData::Unit) => { quote! {} }

            Body::Struct(VariantData::Tuple(_)) => { panic!("`#[derive(ColladaElement)]` does not yet support tuple structs"); }

            Body::Struct(VariantData::Struct(ref fields)) => {
                let decls = fields
                    .iter()
                    .map(|field| {
                        let ident = field.ident.as_ref().unwrap();
                        quote! { #ident: #ident }
                    });

                quote! {
                    Ok(#type_name {
                        #( #decls ),*
                    })
                }
            }
        }
    };

    // Put all the pieces together.
    // ----------------------------
    Ok(quote! {
        impl ColladaElement for #type_name {
            fn parse_element<R: Read>(reader: &mut EventReader<R>, attributes: Vec<OwnedAttribute>) -> Result<Self> {
                // use utils;
                // use utils::{ElementConfiguration, ChildConfiguration};

                #member_decls

                #attributes_impl

                #children_impl

                #result_decl
            }

            fn name() -> &'static str {
                #element_name
            }
        }
    })
}
<|endoftext|>


<commit_before>extern crate fbx_direct;
extern crate env_logger;

use std::fs::File;
use std::io::BufReader;

use fbx_direct::reader::{EventReader, FbxEvent};

fn main() {
    env_logger::init().unwrap();

    let file = BufReader::new(File::open("sample.fbx").unwrap());

    let parser = EventReader::new(file);
    for e in parser {
        match e {
            Err(e) => {
                println!("Error: {:?}", e);
                break;
            },
            _ => {
                println!("{:?}", e);
            }
        }
    }
}
<commit_msg>Now `example/simple.rs` prints events with indent<commit_after>extern crate fbx_direct;
extern crate env_logger;

use std::fs::File;
use std::io::BufReader;

use fbx_direct::reader::{EventReader, FbxEvent};

fn indent(size: usize) -> String {
    const INDENT: &'static str = "    ";
    (0..size).map(|_| INDENT)
        .fold(String::with_capacity(size * INDENT.len()), |r, s| r + s)
}

fn main() {
    env_logger::init().unwrap();

    let file = BufReader::new(File::open("sample.fbx").unwrap());

    let parser = EventReader::new(file);
    let mut depth = 0;
    for e in parser {
        match e {
            Err(e) => {
                println!("Error: {:?}", e);
                break;
            },
            Ok(ref e@FbxEvent::StartNode { .. }) => {
                println!("{}{:?}", indent(depth), e);
                depth += 1;
            },
            Ok(ref e@FbxEvent::EndNode) => {
                depth -= 1;
                println!("{}{:?}", indent(depth), e);
            },
            _ => {
                println!("{}{:?}", indent(depth), e);
            }
        }
    }
}
<|endoftext|>


<commit_before>/// Async server-side trees

use std::{ops, fmt, mem};
use dbus::tree::{Factory, Tree, MethodType, DataType, MTFn, Method, MethodInfo, MethodErr};
use dbus::{Member, Message, Connection};
use std::marker::PhantomData;
use std::cell::RefCell;
use futures::{IntoFuture, Future, Poll, Stream, Async};
use std::rc::Rc;
use std::ffi::CString;

pub trait ADataType: fmt::Debug + Sized + Default {
    type ObjectPath: fmt::Debug;
    type Property: fmt::Debug;
    type Interface: fmt::Debug + Default;
    type Method: fmt::Debug + Default;
    type Signal: fmt::Debug;
}

#[derive(Debug, Default)]
/// A Tree that allows both synchronous and asynchronous methods.
pub struct ATree<D: ADataType>(RefCell<Option<AMethodResult>>, PhantomData<*const D>);

impl<D: ADataType> ATree<D> {
    pub fn new() -> Self { Default::default() }
    fn push(&self, a: AMethodResult) {
        let mut z = self.0.borrow_mut();
        assert!(z.is_none(), "Same message handled twice");
        *z = Some(a);
    }
}

impl<D: ADataType> DataType for ATree<D> {
    type Tree = ATree<D>;
    type ObjectPath = D::ObjectPath;
    type Property = D::Property;
    type Interface = D::Interface;
    type Method = D::Method;
    type Signal = D::Signal;
}

impl ADataType for () {
    type ObjectPath = ();
    type Property = ();
    type Interface = ();
    type Method = ();
    type Signal = ();
}

/// A Tree factory that allows both synchronous and asynchronous methods.
pub struct AFactory<M: MethodType<D>, D: DataType = ()>(Factory<M, D>);

impl AFactory<MTFn<()>, ()> {
    pub fn new_afn<D: ADataType>() -> AFactory<MTFn<ATree<D>>, ATree<D>> { AFactory(Factory::new_fn()) }
}

impl<M: MethodType<D>, D: DataType> ops::Deref for AFactory<M, D> {
    type Target = Factory<M, D>;
    fn deref(&self) -> &Self::Target { &self.0 }
}

impl<D: ADataType> AFactory<MTFn<ATree<D>>, ATree<D>> {
    /// Creates an async method, for methods whose result cannot be returned immediately.
    ///
    /// The method handler supplied to amethod returns a future, which resolves into the method result.
    /// See the tokio_server example for some hints on how to use it.
    pub fn amethod<H, R, T>(&self, t: T, data: D::Method, handler: H) -> Method<MTFn<ATree<D>>, ATree<D>>
    where H: 'static + Fn(&MethodInfo<MTFn<ATree<D>>, ATree<D>>) -> R, T: Into<Member<'static>>,
        R: 'static + IntoFuture<Item=Vec<Message>, Error=MethodErr> {
        self.0.method(t, data, move |minfo| {
            let r = handler(minfo);
            minfo.tree.get_data().push(AMethodResult::new(r));
            Ok(Vec::new())
        })
    }
}

/// A Future method result
///
/// When method results cannot be returned right away, the AMethodResult holds it temporarily
struct AMethodResult(Box<Future<Item=Vec<Message>, Error=MethodErr>>, Option<Message>);

impl fmt::Debug for AMethodResult {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "AMethodResult({:?})", self.1) }
}

impl AMethodResult {
    fn new<F: 'static + IntoFuture<Item=Vec<Message>, Error=MethodErr>>(f: F) -> Self {
        AMethodResult(Box::new(f.into_future()), None)
    }
}

impl Future for AMethodResult {
    type Item = Vec<Message>;
    type Error = MethodErr;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug)]
/// Creates a filter for incoming messages, that handles messages in the tree.
///
/// See the tokio_server example for some hints on how to use it.
pub struct ATreeServer<'a, D: ADataType + 'a, S> {
   conn: Rc<Connection>,
   tree: &'a Tree<MTFn<ATree<D>>, ATree<D>>,
   stream: S,
   pendingresults: Vec<AMethodResult>,
}

impl<'a, D: ADataType, S: Stream<Item=Message, Error=()>> ATreeServer<'a, D, S> {
    pub fn new(c: Rc<Connection>, t: &'a Tree<MTFn<ATree<D>>, ATree<D>>, stream: S) -> Self {
        ATreeServer { conn: c, tree: t, stream: stream, pendingresults: vec![] }
    }

    fn spawn_method_results(&mut self, msg: Message) {
        let v = self.tree.get_data().0.borrow_mut().take();
        if let Some(mut r) = v {
            if r.1.is_none() { r.1 = Some(msg); };
            // println!("Pushing {:?}", r);
            self.pendingresults.push(r);
        }
    }

    fn check_pending_results(&mut self) {
        let v = mem::replace(&mut self.pendingresults, vec!());
        self.pendingresults = v.into_iter().filter_map(|mut mr| {
            let z = mr.poll();
            // println!("Polling {:?} returned {:?}", mr, z);
            match z {
                Ok(Async::NotReady) => Some(mr),
                Ok(Async::Ready(t)) => { for msg in t { self.conn.send(msg).expect("D-Bus send error"); }; None },
                Err(e) => {
                    let m = mr.1.take().unwrap();
                    let msg = m.error(&e.errorname(), &CString::new(e.description()).unwrap());
                    self.conn.send(msg).expect("D-Bus send error");
                    None
                }
            }
        }).collect();
    }
}

impl<'a, D: ADataType, S: Stream<Item=Message, Error=()>> Stream for ATreeServer<'a, D, S> {
    type Item = Message;
    type Error = ();
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            self.check_pending_results();
            let z = self.stream.poll();
            if let Ok(Async::Ready(Some(m))) = z {
                // println!("treeserver {:?}", m);
                let hh = self.tree.handle(&m);
                // println!("hh: {:?}", hh);
                if let Some(v) = hh {
                    self.spawn_method_results(m);
                    for msg in v { self.conn.send(msg)?; }
                    // We consumed the message. Poll again
                } else { return Ok(Async::Ready(Some(m))) }
            } else { return z }
        }
    }
}

<commit_msg>Use std::ops::Deref for Connection and Tree in ATreeServer<commit_after>/// Async server-side trees

use std::{ops, fmt, mem};
use dbus::tree::{Factory, Tree, MethodType, DataType, MTFn, Method, MethodInfo, MethodErr};
use dbus::{Member, Message, Connection};
use std::marker::PhantomData;
use std::cell::RefCell;
use futures::{IntoFuture, Future, Poll, Stream, Async};
use std::ffi::CString;

pub trait ADataType: fmt::Debug + Sized + Default {
    type ObjectPath: fmt::Debug;
    type Property: fmt::Debug;
    type Interface: fmt::Debug + Default;
    type Method: fmt::Debug + Default;
    type Signal: fmt::Debug;
}

#[derive(Debug, Default)]
/// A Tree that allows both synchronous and asynchronous methods.
pub struct ATree<D: ADataType>(RefCell<Option<AMethodResult>>, PhantomData<*const D>);

impl<D: ADataType> ATree<D> {
    pub fn new() -> Self { Default::default() }
    fn push(&self, a: AMethodResult) {
        let mut z = self.0.borrow_mut();
        assert!(z.is_none(), "Same message handled twice");
        *z = Some(a);
    }
}

impl<D: ADataType> DataType for ATree<D> {
    type Tree = ATree<D>;
    type ObjectPath = D::ObjectPath;
    type Property = D::Property;
    type Interface = D::Interface;
    type Method = D::Method;
    type Signal = D::Signal;
}

impl ADataType for () {
    type ObjectPath = ();
    type Property = ();
    type Interface = ();
    type Method = ();
    type Signal = ();
}

/// A Tree factory that allows both synchronous and asynchronous methods.
pub struct AFactory<M: MethodType<D>, D: DataType = ()>(Factory<M, D>);

impl AFactory<MTFn<()>, ()> {
    pub fn new_afn<D: ADataType>() -> AFactory<MTFn<ATree<D>>, ATree<D>> { AFactory(Factory::new_fn()) }
}

impl<M: MethodType<D>, D: DataType> ops::Deref for AFactory<M, D> {
    type Target = Factory<M, D>;
    fn deref(&self) -> &Self::Target { &self.0 }
}

impl<D: ADataType> AFactory<MTFn<ATree<D>>, ATree<D>> {
    /// Creates an async method, for methods whose result cannot be returned immediately.
    ///
    /// The method handler supplied to amethod returns a future, which resolves into the method result.
    /// See the tokio_server example for some hints on how to use it.
    pub fn amethod<H, R, T>(&self, t: T, data: D::Method, handler: H) -> Method<MTFn<ATree<D>>, ATree<D>>
    where H: 'static + Fn(&MethodInfo<MTFn<ATree<D>>, ATree<D>>) -> R, T: Into<Member<'static>>,
        R: 'static + IntoFuture<Item=Vec<Message>, Error=MethodErr> {
        self.0.method(t, data, move |minfo| {
            let r = handler(minfo);
            minfo.tree.get_data().push(AMethodResult::new(r));
            Ok(Vec::new())
        })
    }
}

/// A Future method result
///
/// When method results cannot be returned right away, the AMethodResult holds it temporarily
struct AMethodResult(Box<Future<Item=Vec<Message>, Error=MethodErr>>, Option<Message>);

impl fmt::Debug for AMethodResult {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "AMethodResult({:?})", self.1) }
}

impl AMethodResult {
    fn new<F: 'static + IntoFuture<Item=Vec<Message>, Error=MethodErr>>(f: F) -> Self {
        AMethodResult(Box::new(f.into_future()), None)
    }
}

impl Future for AMethodResult {
    type Item = Vec<Message>;
    type Error = MethodErr;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug)]
/// Creates a filter for incoming messages, that handles messages in the tree.
///
/// See the tokio_server example for some hints on how to use it.
pub struct ATreeServer<C,T,D,S>
where C: ops::Deref<Target=Connection>,
      T: ops::Deref<Target=Tree<MTFn<ATree<D>>, ATree<D>>>,
      D: ADataType {
   conn: C,
   tree: T,
   stream: S,
   pendingresults: Vec<AMethodResult>,
}

impl<C,T,D,S> ATreeServer<C,T,D,S>
where C: ops::Deref<Target=Connection>,
      T: ops::Deref<Target=Tree<MTFn<ATree<D>>, ATree<D>>>,
      S: Stream<Item=Message, Error=()>,
      D: ADataType {
    pub fn new(c: C, t: T, stream: S) -> Self {
        ATreeServer { conn: c, tree: t, stream: stream, pendingresults: vec![] }
    }

    fn spawn_method_results(&mut self, msg: Message) {
        let v = self.tree.get_data().0.borrow_mut().take();
        if let Some(mut r) = v {
            if r.1.is_none() { r.1 = Some(msg); };
            // println!("Pushing {:?}", r);
            self.pendingresults.push(r);
        }
    }

    fn check_pending_results(&mut self) {
        let v = mem::replace(&mut self.pendingresults, vec!());
        self.pendingresults = v.into_iter().filter_map(|mut mr| {
            let z = mr.poll();
            // println!("Polling {:?} returned {:?}", mr, z);
            match z {
                Ok(Async::NotReady) => Some(mr),
                Ok(Async::Ready(t)) => { for msg in t { self.conn.send(msg).expect("D-Bus send error"); }; None },
                Err(e) => {
                    let m = mr.1.take().unwrap();
                    let msg = m.error(&e.errorname(), &CString::new(e.description()).unwrap());
                    self.conn.send(msg).expect("D-Bus send error");
                    None
                }
            }
        }).collect();
    }
}

impl<C,T,D,S> Stream for ATreeServer<C,T,D,S>
where C: ops::Deref<Target=Connection>,
      T: ops::Deref<Target=Tree<MTFn<ATree<D>>, ATree<D>>>,
      S: Stream<Item=Message, Error=()>,
      D: ADataType {
    type Item = Message;
    type Error = ();
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            self.check_pending_results();
            let z = self.stream.poll();
            if let Ok(Async::Ready(Some(m))) = z {
                // println!("treeserver {:?}", m);
                let hh = self.tree.handle(&m);
                // println!("hh: {:?}", hh);
                if let Some(v) = hh {
                    self.spawn_method_results(m);
                    for msg in v { self.conn.send(msg)?; }
                    // We consumed the message. Poll again
                } else { return Ok(Async::Ready(Some(m))) }
            } else { return z }
        }
    }
}

<|endoftext|>


<commit_before>#![cfg(target_os = "android")]

use crate::api::egl::{Context as EglContext, NativeDisplay, SurfaceType as EglSurfaceType};
use crate::CreationError::{self, OsError};
use crate::{Api, ContextError, GlAttributes, PixelFormat, PixelFormatRequirements, Rect};

use crate::platform::android::EventLoopExtAndroid;
use glutin_egl_sys as ffi;
use parking_lot::Mutex;
use winit;
use winit::dpi;
use winit::event_loop::EventLoopWindowTarget;
use winit::window::WindowBuilder;

use std::sync::Arc;

#[derive(Debug)]
struct AndroidContext {
    egl_context: EglContext,
    stopped: Option<Mutex<bool>>,
}

#[derive(Debug)]
pub struct Context(Arc<AndroidContext>);

#[derive(Debug)]
struct AndroidSyncEventHandler(Arc<AndroidContext>);

impl android_glue::SyncEventHandler for AndroidSyncEventHandler {
    fn handle(&mut self, event: &android_glue::Event) {
        match *event {
            // 'on_surface_destroyed' Android event can arrive with some delay
            // because multithreading communication. Because of
            // that, swap_buffers can be called before processing
            // 'on_surface_destroyed' event, with the native window
            // surface already destroyed. EGL generates a BAD_SURFACE error in
            // this situation. Set stop to true to prevent
            // swap_buffer call race conditions.
            android_glue::Event::TermWindow => {
                let mut stopped = self.0.stopped.as_ref().unwrap().lock();
                *stopped = true;
            }
            _ => {
                return;
            }
        };
    }
}

impl Context {
    #[inline]
    pub fn new_windowed<T>(
        wb: WindowBuilder,
        el: &EventLoopWindowTarget<T>,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
    ) -> Result<(winit::window::Window, Self), CreationError> {
        let win = wb.build(el)?;
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.0.egl_context);
        let nwin = unsafe { android_glue::get_native_window() };
        if nwin.is_null() {
            return Err(OsError("Android's native window is null".to_string()));
        }
        let native_display = NativeDisplay::Android;
        let egl_context =
            EglContext::new(pf_reqs, &gl_attr, native_display, EglSurfaceType::Window, |c, _| {
                Ok(c[0])
            })
            .and_then(|p| p.finish(nwin as *const _))?;
        let ctx = Arc::new(AndroidContext { egl_context, stopped: Some(Mutex::new(false)) });

        let handler = Box::new(AndroidSyncEventHandler(ctx.clone()));
        android_glue::add_sync_event_handler(handler);
        let context = Context(ctx.clone());

        el.set_suspend_callback(Some(Box::new(move |suspended| {
            let mut stopped = ctx.stopped.as_ref().unwrap().lock();
            *stopped = suspended;
            if suspended {
                // Android has stopped the activity or sent it to background.
                // Release the EGL surface and stop the animation loop.
                unsafe {
                    ctx.egl_context.on_surface_destroyed();
                }
            } else {
                // Android has started the activity or sent it to foreground.
                // Restore the EGL surface and animation loop.
                unsafe {
                    let nwin = android_glue::get_native_window();
                    ctx.egl_context.on_surface_created(nwin as *const _);
                }
            }
        })));

        Ok((win, context))
    }

    #[inline]
    pub fn new_headless<T>(
        _el: &EventLoopWindowTarget<T>,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Context>,
        size: dpi::PhysicalSize<u32>,
    ) -> Result<Self, CreationError> {
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.0.egl_context);
        let context = EglContext::new(
            pf_reqs,
            &gl_attr,
            NativeDisplay::Android,
            EglSurfaceType::PBuffer,
            |c, _| Ok(c[0]),
        )?;
        let egl_context = context.finish_pbuffer(size)?;
        let ctx = Arc::new(AndroidContext { egl_context, stopped: None });
        Ok(Context(ctx))
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }

        self.0.egl_context.make_current()
    }

    #[inline]
    pub unsafe fn make_not_current(&self) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }

        self.0.egl_context.make_not_current()
    }

    #[inline]
    pub fn resize(&self, _: u32, _: u32) {}

    #[inline]
    pub fn is_current(&self) -> bool {
        self.0.egl_context.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const core::ffi::c_void {
        self.0.egl_context.get_proc_address(addr)
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }
        self.0.egl_context.swap_buffers()
    }

    #[inline]
    pub fn swap_buffers_with_damage(&self, rects: &[Rect]) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }
        self.0.egl_context.swap_buffers_with_damage(rects)
    }

    #[inline]
    pub fn swap_buffers_with_damage_supported(&self) -> bool {
        self.0.egl_context.swap_buffers_with_damage_supported()
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.0.egl_context.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.0.egl_context.get_pixel_format()
    }

    #[inline]
    pub unsafe fn raw_handle(&self) -> ffi::EGLContext {
        self.0.egl_context.raw_handle()
    }

    #[inline]
    pub unsafe fn get_egl_display(&self) -> ffi::EGLDisplay {
        self.0.egl_context.get_egl_display()
    }
}
<commit_msg>api/android: Implement missing `buffer_age()` function (#1410)<commit_after>#![cfg(target_os = "android")]

use crate::api::egl::{Context as EglContext, NativeDisplay, SurfaceType as EglSurfaceType};
use crate::CreationError::{self, OsError};
use crate::{Api, ContextError, GlAttributes, PixelFormat, PixelFormatRequirements, Rect};

use crate::platform::android::EventLoopExtAndroid;
use glutin_egl_sys as ffi;
use parking_lot::Mutex;
use winit;
use winit::dpi;
use winit::event_loop::EventLoopWindowTarget;
use winit::window::WindowBuilder;

use std::sync::Arc;

#[derive(Debug)]
struct AndroidContext {
    egl_context: EglContext,
    stopped: Option<Mutex<bool>>,
}

#[derive(Debug)]
pub struct Context(Arc<AndroidContext>);

#[derive(Debug)]
struct AndroidSyncEventHandler(Arc<AndroidContext>);

impl android_glue::SyncEventHandler for AndroidSyncEventHandler {
    fn handle(&mut self, event: &android_glue::Event) {
        match *event {
            // 'on_surface_destroyed' Android event can arrive with some delay
            // because multithreading communication. Because of
            // that, swap_buffers can be called before processing
            // 'on_surface_destroyed' event, with the native window
            // surface already destroyed. EGL generates a BAD_SURFACE error in
            // this situation. Set stop to true to prevent
            // swap_buffer call race conditions.
            android_glue::Event::TermWindow => {
                let mut stopped = self.0.stopped.as_ref().unwrap().lock();
                *stopped = true;
            }
            _ => {
                return;
            }
        };
    }
}

impl Context {
    #[inline]
    pub fn new_windowed<T>(
        wb: WindowBuilder,
        el: &EventLoopWindowTarget<T>,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Self>,
    ) -> Result<(winit::window::Window, Self), CreationError> {
        let win = wb.build(el)?;
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.0.egl_context);
        let nwin = unsafe { android_glue::get_native_window() };
        if nwin.is_null() {
            return Err(OsError("Android's native window is null".to_string()));
        }
        let native_display = NativeDisplay::Android;
        let egl_context =
            EglContext::new(pf_reqs, &gl_attr, native_display, EglSurfaceType::Window, |c, _| {
                Ok(c[0])
            })
            .and_then(|p| p.finish(nwin as *const _))?;
        let ctx = Arc::new(AndroidContext { egl_context, stopped: Some(Mutex::new(false)) });

        let handler = Box::new(AndroidSyncEventHandler(ctx.clone()));
        android_glue::add_sync_event_handler(handler);
        let context = Context(ctx.clone());

        el.set_suspend_callback(Some(Box::new(move |suspended| {
            let mut stopped = ctx.stopped.as_ref().unwrap().lock();
            *stopped = suspended;
            if suspended {
                // Android has stopped the activity or sent it to background.
                // Release the EGL surface and stop the animation loop.
                unsafe {
                    ctx.egl_context.on_surface_destroyed();
                }
            } else {
                // Android has started the activity or sent it to foreground.
                // Restore the EGL surface and animation loop.
                unsafe {
                    let nwin = android_glue::get_native_window();
                    ctx.egl_context.on_surface_created(nwin as *const _);
                }
            }
        })));

        Ok((win, context))
    }

    #[inline]
    pub fn new_headless<T>(
        _el: &EventLoopWindowTarget<T>,
        pf_reqs: &PixelFormatRequirements,
        gl_attr: &GlAttributes<&Context>,
        size: dpi::PhysicalSize<u32>,
    ) -> Result<Self, CreationError> {
        let gl_attr = gl_attr.clone().map_sharing(|c| &c.0.egl_context);
        let context = EglContext::new(
            pf_reqs,
            &gl_attr,
            NativeDisplay::Android,
            EglSurfaceType::PBuffer,
            |c, _| Ok(c[0]),
        )?;
        let egl_context = context.finish_pbuffer(size)?;
        let ctx = Arc::new(AndroidContext { egl_context, stopped: None });
        Ok(Context(ctx))
    }

    #[inline]
    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }

        self.0.egl_context.make_current()
    }

    #[inline]
    pub unsafe fn make_not_current(&self) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }

        self.0.egl_context.make_not_current()
    }

    #[inline]
    pub fn resize(&self, _: u32, _: u32) {}

    #[inline]
    pub fn is_current(&self) -> bool {
        self.0.egl_context.is_current()
    }

    #[inline]
    pub fn get_proc_address(&self, addr: &str) -> *const core::ffi::c_void {
        self.0.egl_context.get_proc_address(addr)
    }

    #[inline]
    pub fn buffer_age(&self) -> u32 {
        self.0.egl_context.buffer_age()
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }
        self.0.egl_context.swap_buffers()
    }

    #[inline]
    pub fn swap_buffers_with_damage(&self, rects: &[Rect]) -> Result<(), ContextError> {
        if let Some(ref stopped) = self.0.stopped {
            let stopped = stopped.lock();
            if *stopped {
                return Err(ContextError::ContextLost);
            }
        }
        self.0.egl_context.swap_buffers_with_damage(rects)
    }

    #[inline]
    pub fn swap_buffers_with_damage_supported(&self) -> bool {
        self.0.egl_context.swap_buffers_with_damage_supported()
    }

    #[inline]
    pub fn get_api(&self) -> Api {
        self.0.egl_context.get_api()
    }

    #[inline]
    pub fn get_pixel_format(&self) -> PixelFormat {
        self.0.egl_context.get_pixel_format()
    }

    #[inline]
    pub unsafe fn raw_handle(&self) -> ffi::EGLContext {
        self.0.egl_context.raw_handle()
    }

    #[inline]
    pub unsafe fn get_egl_display(&self) -> ffi::EGLDisplay {
        self.0.egl_context.get_egl_display()
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::slice::Iter;
use std::vec::Vec;

use itertools::Itertools;

use types::*;

pub enum Field {
  Scalar (String, Ty),
  Record (String, Vec<Field>),
  Array (String, Vec<Field>),
  Map (String, Ty, Vec<Field>)
}

pub struct Record {
  fields: Vec<Field>
}

impl Record {
  pub fn new(fields: Vec<Field>) -> Record {
    Record {fields: fields}
  }
}

impl fmt::Display for Record {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", display_record(self))
  }
}

#[inline]
pub fn display_record(r: &Record) -> String {
  display_fields(&r.fields)
}

fn display_field(f: &Field) -> String {
  match *f {
    Field::Scalar(ref name, ref ty)     => format!("{} {}", name, ty),
    Field::Record(ref name, ref fields) => format!("{} record ({})", name, display_fields(fields)),
    Field::Array(ref name, ref fields)  => format!("{} array<{}>", name, display_fields(fields)),
    Field::Map(ref name, ref key_ty, ref fields) => {
        format!("{} map<{},{}>", name, key_ty, display_fields(fields))
    }
  }
}

#[inline]
fn display_fields(fields: &Vec<Field>) -> String {
  fields.iter().map(|f| display_field(f)).join(", ")
}
<commit_msg>Improved schema.<commit_after>use std::fmt;
use std::ops::Index;
use std::slice::Iter;
use std::vec::Vec;

use itertools::Itertools;

use types::*;

pub type ColumnId = usize;

#[derive(Clone, PartialEq, Debug)]
pub enum Field {
  Scalar (String, Ty),
  Record (String, Vec<Field>),
  Array (String, Vec<Field>),
  Map (String, Ty, Vec<Field>)
}

impl Field {
  pub fn name(&self) -> &str {
    match *self {
      Field::Scalar(ref name, ref ty)              => name,
      Field::Record(ref name, ref fields)          => name,
      Field::Array(ref name, ref fields)           => name,
      Field::Map(ref name, ref key_ty, ref fields) => name
    }
  }
}

impl fmt::Display for Field {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", display_field(self))
  }
}

pub struct Record {
  fields: Vec<Field>
}

impl Record {
  pub fn new(fields: Vec<Field>) -> Record {
    Record {fields: fields}
  }

  pub fn size(&self) -> usize {
    self.fields.len()
  }

  pub fn find_id(&self, name: &str) -> Option<ColumnId> {
    self.fields.iter().position(|f| f.name() == name)
  }

  pub fn find_by_name(&self, name : &str) -> Option<&Field> {
    self.fields.iter().filter(|&f| f.name() == name).next()
  }

  pub fn iter(&self) -> Iter<Field> {
    self.fields.iter()
  }
}

impl Index<ColumnId> for Record {
  type Output = Field;
  fn index<'a>(&'a self, id: ColumnId) -> &'a Field {
    debug_assert!(id < self.fields.len(), "Field index is out of range");
    &self.fields[id]
  }
}

impl fmt::Display for Record {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", display_record(self))
  }
}

#[inline]
pub fn display_record(r: &Record) -> String {
  display_fields(&r.fields)
}

fn display_field(f: &Field) -> String {
  match *f {
    Field::Scalar(ref name, ref ty)     => format!("{} {}", name, ty),
    Field::Record(ref name, ref fields) => format!("{} record ({})", name, display_fields(fields)),
    Field::Array(ref name, ref fields)  => format!("{} array<{}>", name, display_fields(fields)),
    Field::Map(ref name, ref key_ty, ref fields) => {
        format!("{} map<{},{}>", name, key_ty, display_fields(fields))
    }
  }
}

#[inline]
fn display_fields(fields: &Vec<Field>) -> String {
  fields.iter().map(|f| display_field(f)).join(", ")
}

#[test]
fn test_creation() {
    let mut fields = Vec::new();
    fields.push(Field::Scalar("col1".to_owned(), *INT4_TY));
    fields.push(Field::Record("col2".to_owned(), vec![
        Field::Scalar("col3".to_owned(), *INT4_TY),
        Field::Scalar("col4".to_owned(), *INT4_TY)
    ]));

    let r = Record::new(fields);
    println!("{}", r);
}
<|endoftext|>


<commit_before>use godcoin::{prelude::*, script::*};
use std::{error::Error, num::ParseIntError};

#[derive(Clone, Debug)]
pub enum BuildError {
    EmptyScript,
    ScriptSizeOverflow,
    UnknownOp(String),
    MissingArgForOp(String),
    WifError(WifError),
    Other(String),
}

pub fn build(ops: &[String]) -> Result<Script, BuildError> {
    let mut builder = Builder::new();

    let mut iter = ops.iter();
    while let Some(op) = iter.next() {
        builder = match op.as_ref() {
            // Push value
            "OP_FALSE" => builder.try_push(OpFrame::False),
            "OP_TRUE" => builder.try_push(OpFrame::True),
            "OP_PUBKEY" => {
                let key = iter.next();
                if let Some(key) = key {
                    let key = PublicKey::from_wif(key).map_err(BuildError::WifError)?;
                    builder.try_push(OpFrame::PubKey(key))
                } else {
                    return Err(BuildError::MissingArgForOp(op.to_owned()));
                }
            }
            // Logic
            "OP_NOT" => builder.try_push(OpFrame::OpNot),
            "OP_IF" => builder.try_push(OpFrame::OpIf),
            "OP_ELSE" => builder.try_push(OpFrame::OpElse),
            "OP_ENDIF" => builder.try_push(OpFrame::OpEndIf),
            "OP_RETURN" => builder.try_push(OpFrame::OpReturn),
            // Crypto
            "OP_CHECKSIG" => builder.try_push(OpFrame::OpCheckSig),
            "OP_CHECKSIGFASTFAIL" => builder.try_push(OpFrame::OpCheckSigFastFail),
            "OP_CHECKMULTISIG" => {
                let threshold = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                let key_count = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                builder.try_push(OpFrame::OpCheckMultiSig(threshold, key_count))
            }
            "OP_CHECKMULTISIGFASTFAIL" => {
                let threshold = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                let key_count = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                builder.try_push(OpFrame::OpCheckMultiSigFastFail(threshold, key_count))
            }
            _ => return Err(BuildError::UnknownOp(op.to_owned())),
        }
        .ok_or(BuildError::ScriptSizeOverflow)?;
    }

    if !builder.as_ref().is_empty() {
        Ok(builder.build())
    } else {
        Err(BuildError::EmptyScript)
    }
}
<commit_msg>CLI script builder supports pushing assets<commit_after>use godcoin::{prelude::*, script::*};
use std::{error::Error, num::ParseIntError};

#[derive(Clone, Debug)]
pub enum BuildError {
    EmptyScript,
    ScriptSizeOverflow,
    UnknownOp(String),
    MissingArgForOp(String),
    WifError(WifError),
    AssetParseError(AssetError),
    Other(String),
}

pub fn build(ops: &[String]) -> Result<Script, BuildError> {
    let mut builder = Builder::new();

    let mut iter = ops.iter();
    while let Some(op) = iter.next() {
        builder = match op.as_ref() {
            // Push value
            "OP_FALSE" => builder.try_push(OpFrame::False),
            "OP_TRUE" => builder.try_push(OpFrame::True),
            "OP_PUBKEY" => {
                let key = iter.next();
                if let Some(key) = key {
                    let key = PublicKey::from_wif(key).map_err(BuildError::WifError)?;
                    builder.try_push(OpFrame::PubKey(key))
                } else {
                    return Err(BuildError::MissingArgForOp(op.to_owned()));
                }
            }
            "OP_ASSET" => {
                let asset = iter.next();
                if let Some(asset) = asset {
                    let asset = asset.parse().map_err(BuildError::AssetParseError)?;
                    builder.try_push(OpFrame::Asset(asset))
                } else {
                    return Err(BuildError::MissingArgForOp(op.to_owned()));
                }
            }
            // Logic
            "OP_NOT" => builder.try_push(OpFrame::OpNot),
            "OP_IF" => builder.try_push(OpFrame::OpIf),
            "OP_ELSE" => builder.try_push(OpFrame::OpElse),
            "OP_ENDIF" => builder.try_push(OpFrame::OpEndIf),
            "OP_RETURN" => builder.try_push(OpFrame::OpReturn),
            // Crypto
            "OP_CHECKSIG" => builder.try_push(OpFrame::OpCheckSig),
            "OP_CHECKSIGFASTFAIL" => builder.try_push(OpFrame::OpCheckSigFastFail),
            "OP_CHECKMULTISIG" => {
                let threshold = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                let key_count = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                builder.try_push(OpFrame::OpCheckMultiSig(threshold, key_count))
            }
            "OP_CHECKMULTISIGFASTFAIL" => {
                let threshold = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                let key_count = iter
                    .next()
                    .ok_or_else(|| BuildError::MissingArgForOp(op.to_owned()))?
                    .parse()
                    .map_err(|e: ParseIntError| BuildError::Other(e.description().to_owned()))?;
                builder.try_push(OpFrame::OpCheckMultiSigFastFail(threshold, key_count))
            }
            _ => return Err(BuildError::UnknownOp(op.to_owned())),
        }
        .ok_or(BuildError::ScriptSizeOverflow)?;
    }

    if !builder.as_ref().is_empty() {
        Ok(builder.build())
    } else {
        Err(BuildError::EmptyScript)
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Common functionality for the `x86` and `x86_64` Interrupt Descriptor Table.

use core::{fmt, ptr};
use core::fmt::Write;

use core::mem::size_of;

use memory::PAddr;

use arch::cpu::{dtable, control_regs};
use arch::cpu::dtable::DTable;

use super::InterruptContext;

use io::term::CONSOLE;

use vga::Color;

extern {
    /// Array of interrupt handlers exported by ASM
    //  TODO: hopefully, we will not need this much longer.
    static interrupt_handlers: [*const Handler; ENTRIES];
}

/// An interrupt handler function.
pub type Handler = unsafe extern "C" fn() -> !;

/// Number of entries in the system's Interrupt Descriptor Table.
pub const ENTRIES: usize = 256;

//==------------------------------------------------------------------------==
// IDT Gates
#[cfg(target_arch = "x86")]    #[path = "gate32.rs"] pub mod gate;
#[cfg(target_arch = "x86_64")] #[path = "gate64.rs"] pub mod gate;
pub use self::gate::*;

/// `x86` interrupt gate types.
///
/// Bit-and this with the attribute half-byte to produce the
/// `type_attr` field for a `Gate`
#[repr(u8)]
#[derive(Copy,Clone,Debug)]
pub enum GateType { Absent    = 0b0000_0000
                  , Interrupt = 0b1000_1110
                  , Call      = 0b1000_1100
                  , Trap      = 0b1000_1111
                  }

impl fmt::Display for GateType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { GateType::Absent    => write!(f, "Absent")
                    , GateType::Interrupt => write!(f, "Interrupt")
                    , GateType::Call      => write!(f, "Call")
                    , GateType::Trap      => write!(f, "Trap")
                    }
    }
}

//==------------------------------------------------------------------------==
//  IDT implementation
/// An Interrupt Descriptor Table
///
/// The IDT is either 64-bit or 32-bit.
pub struct Idt([Gate; ENTRIES]);

impl Idt {

    /// Construct a new IDT with all interrupt gates set to `absent`.
    pub const fn new() -> Self {
        Idt([Gate::absent(); ENTRIES])
    }

    /// Enable interrupts
    pub unsafe fn enable_interrupts() { asm!("sti") }
    /// Disable interrupts
    pub unsafe fn disable_interrupts() { asm!("cli") }

    /// Add a new interrupt gate pointing to the given handler
    pub fn add_gate(&mut self, idx: usize, handler: Handler) {
        self.0[idx] = Gate::from(handler)
    }

    /// Handle a CPU exception with a given interrupt context.
    pub unsafe fn handle_cpu_exception(state: &InterruptContext) -> ! {
        let ex_info = state.exception();
        let cr_state = control_regs::dump();
        let _ = write!( CONSOLE.lock()
                              .set_colors(Color::White, Color::Blue)
                            //   .clear()
                      , "CPU EXCEPTION {}: {}\n\
                         {} on vector {} with error code {:#x}\n\
                         Source: {}.\nThis is fine.\n\n"
                      , ex_info.mnemonic, ex_info.name
                      , ex_info.irq_type, state.int_id, state.err_no
                      , ex_info.source );

        // TODO: parse error codes
        let _ = match state.int_id {
            14 => unimplemented!() //TODO: special handling for page faults
           , _ => write!( CONSOLE.lock()
                                 .set_colors(Color::White, Color::Blue)
                        , "Registers:\n{:?}\n    {}\n"
                        , state.registers
                        , cr_state
                        )
        };

        loop { }
    }

    /// Add interrupt handlers exported by assembly to the IDT.
    pub unsafe fn add_handlers(&mut self) -> &mut Self {
        for (i, &handler_ptr) in interrupt_handlers.iter()
            .enumerate()
            .filter(|&(_, &ptr)| ptr != ptr::null() ) {
                self.0[i] = Gate::from(*handler_ptr)
        }

        println!("{:<38}{:>40}", " . . Adding interrupt handlers to IDT"
             , "[ OKAY ]");
        self
    }

}

impl DTable for Idt {

    #[inline] unsafe fn load(&self) {
        asm!(  "lidt ($0)"
            :: "r"(&self.get_ptr())
            :  "memory" );
        println!("{:<38}{:>40}", " . . Loading IDT", "[ OKAY ]");
    }
}
<commit_msg>[x86_all] remove unused imports<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Common functionality for the `x86` and `x86_64` Interrupt Descriptor Table.

use core::{fmt, ptr};
use core::fmt::Write;

use arch::cpu::control_regs;
use arch::cpu::dtable::DTable;

use super::InterruptContext;

use io::term::CONSOLE;

use vga::Color;

extern {
    /// Array of interrupt handlers exported by ASM
    //  TODO: hopefully, we will not need this much longer.
    static interrupt_handlers: [*const Handler; ENTRIES];
}

/// An interrupt handler function.
pub type Handler = unsafe extern "C" fn() -> !;

/// Number of entries in the system's Interrupt Descriptor Table.
pub const ENTRIES: usize = 256;

//==------------------------------------------------------------------------==
// IDT Gates
#[cfg(target_arch = "x86")]    #[path = "gate32.rs"] pub mod gate;
#[cfg(target_arch = "x86_64")] #[path = "gate64.rs"] pub mod gate;
pub use self::gate::*;

/// `x86` interrupt gate types.
///
/// Bit-and this with the attribute half-byte to produce the
/// `type_attr` field for a `Gate`
#[repr(u8)]
#[derive(Copy,Clone,Debug)]
pub enum GateType { Absent    = 0b0000_0000
                  , Interrupt = 0b1000_1110
                  , Call      = 0b1000_1100
                  , Trap      = 0b1000_1111
                  }

impl fmt::Display for GateType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { GateType::Absent    => write!(f, "Absent")
                    , GateType::Interrupt => write!(f, "Interrupt")
                    , GateType::Call      => write!(f, "Call")
                    , GateType::Trap      => write!(f, "Trap")
                    }
    }
}

//==------------------------------------------------------------------------==
//  IDT implementation
/// An Interrupt Descriptor Table
///
/// The IDT is either 64-bit or 32-bit.
pub struct Idt([Gate; ENTRIES]);

impl Idt {

    /// Construct a new IDT with all interrupt gates set to `absent`.
    pub const fn new() -> Self {
        Idt([Gate::absent(); ENTRIES])
    }

    /// Enable interrupts
    pub unsafe fn enable_interrupts() { asm!("sti") }
    /// Disable interrupts
    pub unsafe fn disable_interrupts() { asm!("cli") }

    /// Add a new interrupt gate pointing to the given handler
    pub fn add_gate(&mut self, idx: usize, handler: Handler) {
        self.0[idx] = Gate::from(handler)
    }

    /// Handle a CPU exception with a given interrupt context.
    pub unsafe fn handle_cpu_exception(state: &InterruptContext) -> ! {
        let ex_info = state.exception();
        let cr_state = control_regs::dump();
        let _ = write!( CONSOLE.lock()
                              .set_colors(Color::White, Color::Blue)
                            //   .clear()
                      , "CPU EXCEPTION {}: {}\n\
                         {} on vector {} with error code {:#x}\n\
                         Source: {}.\nThis is fine.\n\n"
                      , ex_info.mnemonic, ex_info.name
                      , ex_info.irq_type, state.int_id, state.err_no
                      , ex_info.source );

        // TODO: parse error codes
        let _ = match state.int_id {
            14 => unimplemented!() //TODO: special handling for page faults
           , _ => write!( CONSOLE.lock()
                                 .set_colors(Color::White, Color::Blue)
                        , "Registers:\n{:?}\n    {}\n"
                        , state.registers
                        , cr_state
                        )
        };

        loop { }
    }

    /// Add interrupt handlers exported by assembly to the IDT.
    pub unsafe fn add_handlers(&mut self) -> &mut Self {
        for (i, &handler_ptr) in interrupt_handlers.iter()
            .enumerate()
            .filter(|&(_, &ptr)| ptr != ptr::null() ) {
                self.0[i] = Gate::from(*handler_ptr)
        }

        println!("{:<38}{:>40}", " . . Adding interrupt handlers to IDT"
             , "[ OKAY ]");
        self
    }

}

impl DTable for Idt {

    #[inline] unsafe fn load(&self) {
        asm!(  "lidt ($0)"
            :: "r"(&self.get_ptr())
            :  "memory" );
        println!("{:<38}{:>40}", " . . Loading IDT", "[ OKAY ]");
    }
}
<|endoftext|>


<commit_before>extern crate futures;

use std::thread;
use futures::{oneshot, Future};
use futures::future::IntoShared;

fn send_shared_oneshot_and_wait_on_multiple_threads(threads_number: u32) {
    let (tx, rx) = oneshot::<u32>();
    let f = rx.shared();
    let mut cloned_futures_waited_oneshots = vec![];
    for _ in 0..threads_number {
        let cloned_future = f.clone();
        let (tx2, rx2) = oneshot::<()>();
        cloned_futures_waited_oneshots.push(rx2);
        thread::spawn(move || {
            assert!(*cloned_future.wait().unwrap() == 6);
            tx2.complete(());
        });
    }
    tx.complete(6);
    for f in cloned_futures_waited_oneshots {
        f.wait().unwrap();
    }
}

#[test]
fn one_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(2);
}

#[test]
fn two_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(2);
}

#[test]
fn many_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(10000);
}
<commit_msg>Compile with --no-default-features<commit_after>extern crate futures;

use std::thread;
use futures::sync::oneshot;
use futures::Future;
use futures::future::IntoShared;

fn send_shared_oneshot_and_wait_on_multiple_threads(threads_number: u32) {
    let (tx, rx) = oneshot::channel::<u32>();
    let f = rx.shared();
    let mut cloned_futures_waited_oneshots = vec![];
    for _ in 0..threads_number {
        let cloned_future = f.clone();
        let (tx2, rx2) = oneshot::channel::<()>();
        cloned_futures_waited_oneshots.push(rx2);
        thread::spawn(move || {
            assert!(*cloned_future.wait().unwrap() == 6);
            tx2.complete(());
        });
    }
    tx.complete(6);
    for f in cloned_futures_waited_oneshots {
        f.wait().unwrap();
    }
}

#[test]
fn one_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(2);
}

#[test]
fn two_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(2);
}

#[test]
fn many_threads() {
    send_shared_oneshot_and_wait_on_multiple_threads(10000);
}
<|endoftext|>


<commit_before>extern crate xfdocs;
use xfdocs::xflow::xfstruct::{XFlowStruct};

use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

fn read_file_mf() -> String {
    // Create a path to the desired file
    let path = Path::new("data/flows/10_steps.json");
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!(
            "couldn't open {}: {}",
            display,
            Error::description(&why)
            ),
        Ok(file) => file,
    };

    // Read the file contents into a string, returns `io::Result<usize>`
    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("couldn't read {}: {}", display,
                                                   Error::description(&why)),
        Ok(_)    => print!("{} contains:\n{}", display, s),
    };

    s

}

#[test]
fn test_xfs() {
    let xfs = XFlowStruct::new();
    println!("Hello, xflow {:?}", xfs.to_string());
    assert_eq!(xfs.nodes.len(), 5);
    assert_eq!(xfs.edges.len(), 5);
    assert_eq!(xfs.branches.len(), 5);
}

#[test]
fn test_xfs_fields() {
    let xfs = XFlowStruct::new();
    println!("Hello, xflow {:?}", xfs.to_string());
    assert_eq!(xfs.version, 1);
    assert_eq!(xfs.id, "id1".to_string());
    assert_eq!(xfs.name, "Some name");
}

#[test]
fn test_xfs_entry() {
    let xfs = XFlowStruct::new();
    assert_eq!(xfs.get_entry_nodes(), 4);
}

#[test]
fn test_xfs_to_json() {
    let xfs = XFlowStruct::new();
    assert_eq!(xfs.to_json(), "asd");
}

#[test]
fn test_xfs_from_json() {
    let json_string = read_file_mf();
    let xfs = XFlowStruct::from_json(json_string);
    assert_eq!(xfs.to_json(), "asd");
}

<commit_msg>Update json load test<commit_after>extern crate xfdocs;
use xfdocs::xflow::xfstruct::{XFlowStruct};

use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

fn read_file_mf() -> String {
    // Create a path to the desired file
    let path = Path::new("data/flows/10_steps.json");
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!(
            "couldn't open {}: {}",
            display,
            Error::description(&why)
            ),
        Ok(file) => file,
    };

    // Read the file contents into a string, returns `io::Result<usize>`
    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("couldn't read {}: {}", display,
                                                   Error::description(&why)),
        Ok(_)    => print!("{} contains:\n{}", display, s),
    };

    s

}

#[test]
fn test_xfs() {
    let xfs = XFlowStruct::new();

    assert_eq!(xfs.nodes.len(), 5);
    assert_eq!(xfs.edges.len(), 5);
    assert_eq!(xfs.branches.len(), 5);
}

#[test]
fn test_xfs_fields() {
    let xfs = XFlowStruct::new();

    assert_eq!(xfs.version, 1);
    assert_eq!(xfs.id, "id1".to_string());
    assert_eq!(xfs.name, "Some name");
}

#[test]
#[should_panic]
fn test_xfs_entry() {
    let xfs = XFlowStruct::new();

    assert_eq!(xfs.get_entry_nodes(), 5);
}

#[test]
fn test_xfs_from_json() {
    let json_string = read_file_mf();
    let xfs = XFlowStruct::from_json(json_string);

    assert_eq!(xfs.name, "steps".to_string());
    assert_eq!(xfs.nodes.len(), 10);
    assert_eq!(xfs.edges.len(), 9);
    assert_eq!(xfs.branches.len(), 0);
}

<|endoftext|>