<commit_before>use crate::ast::{Enum, Field, Input, Struct};
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::spanned::Spanned;
use syn::{Data, DeriveInput, GenericArgument, Member, PathArguments, Result, Type, Visibility};

pub fn derive(node: &DeriveInput) -> Result<TokenStream> {
    let input = Input::from_syn(node)?;
    input.validate()?;
    Ok(match input {
        Input::Struct(input) => impl_struct(input),
        Input::Enum(input) => impl_enum(input),
    })
}

fn impl_struct(input: Struct) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_body = if input.attrs.transparent.is_some() {
        let only_field = &input.fields[0].member;
        Some(quote! {
            std::error::Error::source(self.#only_field.as_dyn_error())
        })
    } else if let Some(source_field) = input.source_field() {
        let source = &source_field.member;
        let asref = if type_is_option(source_field.ty) {
            Some(quote_spanned!(source.span()=> .as_ref()?))
        } else {
            None
        };
        let dyn_error = quote_spanned!(source.span()=> self.#source #asref.as_dyn_error());
        Some(quote! {
            std::option::Option::Some(#dyn_error)
        })
    } else {
        None
    };
    let source_method = source_body.map(|body| {
        quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                #body
            }
        }
    });

    let backtrace_method = input.backtrace_field().map(|backtrace_field| {
        let backtrace = &backtrace_field.member;
        let body = if let Some(source_field) = input.source_field() {
            let source = &source_field.member;
            let source_backtrace = if type_is_option(source_field.ty) {
                quote_spanned! {source.span()=>
                    self.#source.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                }
            } else {
                quote_spanned! {source.span()=>
                    self.#source.as_dyn_error().backtrace()
                }
            };
            let combinator = if source == backtrace {
                source_backtrace
            } else if type_is_option(backtrace_field.ty) {
                quote! {
                    #source_backtrace.or(self.#backtrace.as_ref())
                }
            } else {
                quote! {
                    std::option::Option::Some(#source_backtrace.unwrap_or(&self.#backtrace))
                }
            };
            quote! {
                use thiserror::private::AsDynError;
                #combinator
            }
        } else if type_is_option(backtrace_field.ty) {
            quote! {
                self.#backtrace.as_ref()
            }
        } else {
            quote! {
                std::option::Option::Some(&self.#backtrace)
            }
        };
        quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                #body
            }
        }
    });

    let display_body = if input.attrs.transparent.is_some() {
        let only_field = &input.fields[0].member;
        Some(quote! {
            std::fmt::Display::fmt(&self.#only_field, __formatter)
        })
    } else if let Some(display) = &input.attrs.display {
        let use_as_display = if display.has_bonus_display {
            Some(quote! {
                #[allow(unused_imports)]
                use thiserror::private::{DisplayAsDisplay, PathAsDisplay};
            })
        } else {
            None
        };
        let pat = fields_pat(&input.fields);
        Some(quote! {
            #use_as_display
            #[allow(unused_variables, deprecated)]
            let Self #pat = self;
            #display
        })
    } else {
        None
    };
    let display_impl = display_body.map(|body| {
        quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                #[allow(
                    // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
                    clippy::nonstandard_macro_braces,
                    clippy::used_underscore_binding,
                )]
                fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #body
                }
            }
        }
    });

    let from_impl = input.from_field().map(|from_field| {
        let backtrace_field = input.distinct_backtrace_field();
        let from = unoptional_type(from_field.ty);
        let body = from_initializer(from_field, backtrace_field);
        quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
                #[allow(deprecated)]
                fn from(source: #from) -> Self {
                    #ty #body
                }
            }
        }
    });

    let error_trait = spanned_error_trait(input.original);

    quote! {
        #[allow(unused_qualifications)]
        impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
        #from_impl
    }
}

fn impl_enum(input: Enum) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_method = if input.has_source() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            if variant.attrs.transparent.is_some() {
                let only_field = &variant.fields[0].member;
                let source = quote!(std::error::Error::source(transparent.as_dyn_error()));
                quote! {
                    #ty::#ident {#only_field: transparent} => #source,
                }
            } else if let Some(source_field) = variant.source_field() {
                let source = &source_field.member;
                let asref = if type_is_option(source_field.ty) {
                    Some(quote_spanned!(source.span()=> .as_ref()?))
                } else {
                    None
                };
                let varsource = quote!(source);
                let dyn_error = quote_spanned!(source.span()=> #varsource #asref.as_dyn_error());
                quote! {
                    #ty::#ident {#source: #varsource, ..} => std::option::Option::Some(#dyn_error),
                }
            } else {
                quote! {
                    #ty::#ident {..} => std::option::Option::None,
                }
            }
        });
        Some(quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                #[allow(deprecated)]
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let backtrace_method = if input.has_backtrace() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            match (variant.backtrace_field(), variant.source_field()) {
                (Some(backtrace_field), Some(source_field))
                    if backtrace_field.attrs.backtrace.is_none() =>
                {
                    let backtrace = &backtrace_field.member;
                    let source = &source_field.member;
                    let varsource = quote!(source);
                    let source_backtrace = if type_is_option(source_field.ty) {
                        quote_spanned! {source.span()=>
                            #varsource.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                        }
                    } else {
                        quote_spanned! {source.span()=>
                            #varsource.as_dyn_error().backtrace()
                        }
                    };
                    let combinator = if type_is_option(backtrace_field.ty) {
                        quote! {
                            #source_backtrace.or(backtrace.as_ref())
                        }
                    } else {
                        quote! {
                            std::option::Option::Some(#source_backtrace.unwrap_or(backtrace))
                        }
                    };
                    quote! {
                        #ty::#ident {
                            #backtrace: backtrace,
                            #source: #varsource,
                            ..
                        } => {
                            use thiserror::private::AsDynError;
                            #combinator
                        }
                    }
                }
                (Some(backtrace_field), Some(source_field))
                    if backtrace_field.member == source_field.member =>
                {
                    let backtrace = &backtrace_field.member;
                    let varsource = quote!(source);
                    let source_backtrace = if type_is_option(source_field.ty) {
                        quote_spanned! {backtrace.span()=>
                            #varsource.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                        }
                    } else {
                        quote_spanned! {backtrace.span()=>
                            #varsource.as_dyn_error().backtrace()
                        }
                    };
                    quote! {
                        #ty::#ident {#backtrace: #varsource, ..} => {
                            use thiserror::private::AsDynError;
                            #source_backtrace
                        }
                    }
                }
                (Some(backtrace_field), _) => {
                    let backtrace = &backtrace_field.member;
                    let body = if type_is_option(backtrace_field.ty) {
                        quote!(backtrace.as_ref())
                    } else {
                        quote!(std::option::Option::Some(backtrace))
                    };
                    quote! {
                        #ty::#ident {#backtrace: backtrace, ..} => #body,
                    }
                }
                (None, _) => quote! {
                    #ty::#ident {..} => std::option::Option::None,
                },
            }
        });
        Some(quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                #[allow(deprecated)]
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let display_impl = if input.has_display() {
        let use_as_display = if input.variants.iter().any(|v| {
            v.attrs
                .display
                .as_ref()
                .map_or(false, |display| display.has_bonus_display)
        }) {
            Some(quote! {
                #[allow(unused_imports)]
                use thiserror::private::{DisplayAsDisplay, PathAsDisplay};
            })
        } else {
            None
        };
        let void_deref = if input.variants.is_empty() {
            Some(quote!(*))
        } else {
            None
        };
        let arms = input.variants.iter().map(|variant| {
            let display = match &variant.attrs.display {
                Some(display) => display.to_token_stream(),
                None => {
                    let only_field = match &variant.fields[0].member {
                        Member::Named(ident) => ident.clone(),
                        Member::Unnamed(index) => format_ident!("_{}", index),
                    };
                    quote!(std::fmt::Display::fmt(#only_field, __formatter))
                }
            };
            let ident = &variant.ident;
            let pat = fields_pat(&variant.fields);
            quote! {
                #ty::#ident #pat => #display
            }
        });
        Some(quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #use_as_display
                    #[allow(
                        unused_variables,
                        deprecated,
                        // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
                        clippy::nonstandard_macro_braces,
                        clippy::used_underscore_binding,
                    )]
                    match #void_deref self {
                        #(#arms,)*
                    }
                }
            }
        })
    } else {
        None
    };

    let from_impls = input.variants.iter().filter_map(|variant| {
        let from_field = variant.from_field()?;
        let backtrace_field = variant.distinct_backtrace_field();
        let variant = &variant.ident;
        let from = unoptional_type(from_field.ty);
        let body = from_initializer(from_field, backtrace_field);
        Some(quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
                #[allow(deprecated)]
                fn from(source: #from) -> Self {
                    #ty::#variant #body
                }
            }
        })
    });

    let error_trait = spanned_error_trait(input.original);

    quote! {
        #[allow(unused_qualifications)]
        impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
        #(#from_impls)*
    }
}

fn fields_pat(fields: &[Field]) -> TokenStream {
    let mut members = fields.iter().map(|field| &field.member).peekable();
    match members.peek() {
        Some(Member::Named(_)) => quote!({ #(#members),* }),
        Some(Member::Unnamed(_)) => {
            let vars = members.map(|member| match member {
                Member::Unnamed(member) => format_ident!("_{}", member),
                Member::Named(_) => unreachable!(),
            });
            quote!((#(#vars),*))
        }
        None => quote!({}),
    }
}

fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> TokenStream {
    let from_member = &from_field.member;
    let some_source = if type_is_option(from_field.ty) {
        quote!(std::option::Option::Some(source))
    } else {
        quote!(source)
    };
    let backtrace = backtrace_field.map(|backtrace_field| {
        let backtrace_member = &backtrace_field.member;
        if type_is_option(backtrace_field.ty) {
            quote! {
                #backtrace_member: std::option::Option::Some(std::backtrace::Backtrace::capture()),
            }
        } else {
            quote! {
                #backtrace_member: std::convert::From::from(std::backtrace::Backtrace::capture()),
            }
        }
    });
    quote!({
        #from_member: #some_source,
        #backtrace
    })
}

fn type_is_option(ty: &Type) -> bool {
    type_parameter_of_option(ty).is_some()
}

fn unoptional_type(ty: &Type) -> TokenStream {
    let unoptional = type_parameter_of_option(ty).unwrap_or(ty);
    quote!(#unoptional)
}

fn type_parameter_of_option(ty: &Type) -> Option<&Type> {
    let path = match ty {
        Type::Path(ty) => &ty.path,
        _ => return None,
    };

    let last = path.segments.last().unwrap();
    if last.ident != "Option" {
        return None;
    }

    let bracketed = match &last.arguments {
        PathArguments::AngleBracketed(bracketed) => bracketed,
        _ => return None,
    };

    if bracketed.args.len() != 1 {
        return None;
    }

    match &bracketed.args[0] {
        GenericArgument::Type(arg) => Some(arg),
        _ => None,
    }
}

fn spanned_error_trait(input: &DeriveInput) -> TokenStream {
    let vis_span = match &input.vis {
        Visibility::Public(vis) => Some(vis.pub_token.span()),
        Visibility::Crate(vis) => Some(vis.crate_token.span()),
        Visibility::Restricted(vis) => Some(vis.pub_token.span()),
        Visibility::Inherited => None,
    };
    let data_span = match &input.data {
        Data::Struct(data) => data.struct_token.span(),
        Data::Enum(data) => data.enum_token.span(),
        Data::Union(data) => data.union_token.span(),
    };
    let first_span = vis_span.unwrap_or(data_span);
    let last_span = input.ident.span();
    let path = quote_spanned!(first_span=> std::error::);
    let error = quote_spanned!(last_span=> Error);
    quote!(#path #error)
}
<commit_msg>Revert "Suppress nonstandard_macro_braces in generated code"<commit_after>use crate::ast::{Enum, Field, Input, Struct};
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned, ToTokens};
use syn::spanned::Spanned;
use syn::{Data, DeriveInput, GenericArgument, Member, PathArguments, Result, Type, Visibility};

pub fn derive(node: &DeriveInput) -> Result<TokenStream> {
    let input = Input::from_syn(node)?;
    input.validate()?;
    Ok(match input {
        Input::Struct(input) => impl_struct(input),
        Input::Enum(input) => impl_enum(input),
    })
}

fn impl_struct(input: Struct) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_body = if input.attrs.transparent.is_some() {
        let only_field = &input.fields[0].member;
        Some(quote! {
            std::error::Error::source(self.#only_field.as_dyn_error())
        })
    } else if let Some(source_field) = input.source_field() {
        let source = &source_field.member;
        let asref = if type_is_option(source_field.ty) {
            Some(quote_spanned!(source.span()=> .as_ref()?))
        } else {
            None
        };
        let dyn_error = quote_spanned!(source.span()=> self.#source #asref.as_dyn_error());
        Some(quote! {
            std::option::Option::Some(#dyn_error)
        })
    } else {
        None
    };
    let source_method = source_body.map(|body| {
        quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                #body
            }
        }
    });

    let backtrace_method = input.backtrace_field().map(|backtrace_field| {
        let backtrace = &backtrace_field.member;
        let body = if let Some(source_field) = input.source_field() {
            let source = &source_field.member;
            let source_backtrace = if type_is_option(source_field.ty) {
                quote_spanned! {source.span()=>
                    self.#source.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                }
            } else {
                quote_spanned! {source.span()=>
                    self.#source.as_dyn_error().backtrace()
                }
            };
            let combinator = if source == backtrace {
                source_backtrace
            } else if type_is_option(backtrace_field.ty) {
                quote! {
                    #source_backtrace.or(self.#backtrace.as_ref())
                }
            } else {
                quote! {
                    std::option::Option::Some(#source_backtrace.unwrap_or(&self.#backtrace))
                }
            };
            quote! {
                use thiserror::private::AsDynError;
                #combinator
            }
        } else if type_is_option(backtrace_field.ty) {
            quote! {
                self.#backtrace.as_ref()
            }
        } else {
            quote! {
                std::option::Option::Some(&self.#backtrace)
            }
        };
        quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                #body
            }
        }
    });

    let display_body = if input.attrs.transparent.is_some() {
        let only_field = &input.fields[0].member;
        Some(quote! {
            std::fmt::Display::fmt(&self.#only_field, __formatter)
        })
    } else if let Some(display) = &input.attrs.display {
        let use_as_display = if display.has_bonus_display {
            Some(quote! {
                #[allow(unused_imports)]
                use thiserror::private::{DisplayAsDisplay, PathAsDisplay};
            })
        } else {
            None
        };
        let pat = fields_pat(&input.fields);
        Some(quote! {
            #use_as_display
            #[allow(unused_variables, deprecated)]
            let Self #pat = self;
            #display
        })
    } else {
        None
    };
    let display_impl = display_body.map(|body| {
        quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                #[allow(clippy::used_underscore_binding)]
                fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #body
                }
            }
        }
    });

    let from_impl = input.from_field().map(|from_field| {
        let backtrace_field = input.distinct_backtrace_field();
        let from = unoptional_type(from_field.ty);
        let body = from_initializer(from_field, backtrace_field);
        quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
                #[allow(deprecated)]
                fn from(source: #from) -> Self {
                    #ty #body
                }
            }
        }
    });

    let error_trait = spanned_error_trait(input.original);

    quote! {
        #[allow(unused_qualifications)]
        impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
        #from_impl
    }
}

fn impl_enum(input: Enum) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_method = if input.has_source() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            if variant.attrs.transparent.is_some() {
                let only_field = &variant.fields[0].member;
                let source = quote!(std::error::Error::source(transparent.as_dyn_error()));
                quote! {
                    #ty::#ident {#only_field: transparent} => #source,
                }
            } else if let Some(source_field) = variant.source_field() {
                let source = &source_field.member;
                let asref = if type_is_option(source_field.ty) {
                    Some(quote_spanned!(source.span()=> .as_ref()?))
                } else {
                    None
                };
                let varsource = quote!(source);
                let dyn_error = quote_spanned!(source.span()=> #varsource #asref.as_dyn_error());
                quote! {
                    #ty::#ident {#source: #varsource, ..} => std::option::Option::Some(#dyn_error),
                }
            } else {
                quote! {
                    #ty::#ident {..} => std::option::Option::None,
                }
            }
        });
        Some(quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                #[allow(deprecated)]
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let backtrace_method = if input.has_backtrace() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            match (variant.backtrace_field(), variant.source_field()) {
                (Some(backtrace_field), Some(source_field))
                    if backtrace_field.attrs.backtrace.is_none() =>
                {
                    let backtrace = &backtrace_field.member;
                    let source = &source_field.member;
                    let varsource = quote!(source);
                    let source_backtrace = if type_is_option(source_field.ty) {
                        quote_spanned! {source.span()=>
                            #varsource.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                        }
                    } else {
                        quote_spanned! {source.span()=>
                            #varsource.as_dyn_error().backtrace()
                        }
                    };
                    let combinator = if type_is_option(backtrace_field.ty) {
                        quote! {
                            #source_backtrace.or(backtrace.as_ref())
                        }
                    } else {
                        quote! {
                            std::option::Option::Some(#source_backtrace.unwrap_or(backtrace))
                        }
                    };
                    quote! {
                        #ty::#ident {
                            #backtrace: backtrace,
                            #source: #varsource,
                            ..
                        } => {
                            use thiserror::private::AsDynError;
                            #combinator
                        }
                    }
                }
                (Some(backtrace_field), Some(source_field))
                    if backtrace_field.member == source_field.member =>
                {
                    let backtrace = &backtrace_field.member;
                    let varsource = quote!(source);
                    let source_backtrace = if type_is_option(source_field.ty) {
                        quote_spanned! {backtrace.span()=>
                            #varsource.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                        }
                    } else {
                        quote_spanned! {backtrace.span()=>
                            #varsource.as_dyn_error().backtrace()
                        }
                    };
                    quote! {
                        #ty::#ident {#backtrace: #varsource, ..} => {
                            use thiserror::private::AsDynError;
                            #source_backtrace
                        }
                    }
                }
                (Some(backtrace_field), _) => {
                    let backtrace = &backtrace_field.member;
                    let body = if type_is_option(backtrace_field.ty) {
                        quote!(backtrace.as_ref())
                    } else {
                        quote!(std::option::Option::Some(backtrace))
                    };
                    quote! {
                        #ty::#ident {#backtrace: backtrace, ..} => #body,
                    }
                }
                (None, _) => quote! {
                    #ty::#ident {..} => std::option::Option::None,
                },
            }
        });
        Some(quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                #[allow(deprecated)]
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let display_impl = if input.has_display() {
        let use_as_display = if input.variants.iter().any(|v| {
            v.attrs
                .display
                .as_ref()
                .map_or(false, |display| display.has_bonus_display)
        }) {
            Some(quote! {
                #[allow(unused_imports)]
                use thiserror::private::{DisplayAsDisplay, PathAsDisplay};
            })
        } else {
            None
        };
        let void_deref = if input.variants.is_empty() {
            Some(quote!(*))
        } else {
            None
        };
        let arms = input.variants.iter().map(|variant| {
            let display = match &variant.attrs.display {
                Some(display) => display.to_token_stream(),
                None => {
                    let only_field = match &variant.fields[0].member {
                        Member::Named(ident) => ident.clone(),
                        Member::Unnamed(index) => format_ident!("_{}", index),
                    };
                    quote!(std::fmt::Display::fmt(#only_field, __formatter))
                }
            };
            let ident = &variant.ident;
            let pat = fields_pat(&variant.fields);
            quote! {
                #ty::#ident #pat => #display
            }
        });
        Some(quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #use_as_display
                    #[allow(unused_variables, deprecated, clippy::used_underscore_binding)]
                    match #void_deref self {
                        #(#arms,)*
                    }
                }
            }
        })
    } else {
        None
    };

    let from_impls = input.variants.iter().filter_map(|variant| {
        let from_field = variant.from_field()?;
        let backtrace_field = variant.distinct_backtrace_field();
        let variant = &variant.ident;
        let from = unoptional_type(from_field.ty);
        let body = from_initializer(from_field, backtrace_field);
        Some(quote! {
            #[allow(unused_qualifications)]
            impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
                #[allow(deprecated)]
                fn from(source: #from) -> Self {
                    #ty::#variant #body
                }
            }
        })
    });

    let error_trait = spanned_error_trait(input.original);

    quote! {
        #[allow(unused_qualifications)]
        impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
        #(#from_impls)*
    }
}

fn fields_pat(fields: &[Field]) -> TokenStream {
    let mut members = fields.iter().map(|field| &field.member).peekable();
    match members.peek() {
        Some(Member::Named(_)) => quote!({ #(#members),* }),
        Some(Member::Unnamed(_)) => {
            let vars = members.map(|member| match member {
                Member::Unnamed(member) => format_ident!("_{}", member),
                Member::Named(_) => unreachable!(),
            });
            quote!((#(#vars),*))
        }
        None => quote!({}),
    }
}

fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> TokenStream {
    let from_member = &from_field.member;
    let some_source = if type_is_option(from_field.ty) {
        quote!(std::option::Option::Some(source))
    } else {
        quote!(source)
    };
    let backtrace = backtrace_field.map(|backtrace_field| {
        let backtrace_member = &backtrace_field.member;
        if type_is_option(backtrace_field.ty) {
            quote! {
                #backtrace_member: std::option::Option::Some(std::backtrace::Backtrace::capture()),
            }
        } else {
            quote! {
                #backtrace_member: std::convert::From::from(std::backtrace::Backtrace::capture()),
            }
        }
    });
    quote!({
        #from_member: #some_source,
        #backtrace
    })
}

fn type_is_option(ty: &Type) -> bool {
    type_parameter_of_option(ty).is_some()
}

fn unoptional_type(ty: &Type) -> TokenStream {
    let unoptional = type_parameter_of_option(ty).unwrap_or(ty);
    quote!(#unoptional)
}

fn type_parameter_of_option(ty: &Type) -> Option<&Type> {
    let path = match ty {
        Type::Path(ty) => &ty.path,
        _ => return None,
    };

    let last = path.segments.last().unwrap();
    if last.ident != "Option" {
        return None;
    }

    let bracketed = match &last.arguments {
        PathArguments::AngleBracketed(bracketed) => bracketed,
        _ => return None,
    };

    if bracketed.args.len() != 1 {
        return None;
    }

    match &bracketed.args[0] {
        GenericArgument::Type(arg) => Some(arg),
        _ => None,
    }
}

fn spanned_error_trait(input: &DeriveInput) -> TokenStream {
    let vis_span = match &input.vis {
        Visibility::Public(vis) => Some(vis.pub_token.span()),
        Visibility::Crate(vis) => Some(vis.crate_token.span()),
        Visibility::Restricted(vis) => Some(vis.pub_token.span()),
        Visibility::Inherited => None,
    };
    let data_span = match &input.data {
        Data::Struct(data) => data.struct_token.span(),
        Data::Enum(data) => data.enum_token.span(),
        Data::Union(data) => data.union_token.span(),
    };
    let first_span = vis_span.unwrap_or(data_span);
    let last_span = input.ident.span();
    let path = quote_spanned!(first_span=> std::error::);
    let error = quote_spanned!(last_span=> Error);
    quote!(#path #error)
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate enum_map;

use enum_map::{Enum, EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::convert::Infallible;
use std::marker::PhantomData;

trait From<T>: Sized {
    fn from(_: T) -> Self {
        unreachable!();
    }
}

impl<T, U> From<T> for U {}

#[derive(Copy, Clone, Debug, Enum, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn test_clear() {
    let mut map = enum_map! { false => 1, true => 2 };
    map.clear();
    assert_eq!(map[true], 0);
    assert_eq!(map[false], 0);
}

#[test]
fn discriminants() {
    #[derive(Debug, Enum, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(Enum)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn into_iter_len() {
    assert_eq!(enum_map! { Example::A | _ => 0 }.into_iter().len(), 3);
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

#[test]
fn into_iter_u8() {
    assert_eq!(
        <EnumMap<_, _> as core::convert::From<_>>::from(|i: u8| i)
            .into_iter()
            .collect::<Vec<_>>(),
        (0..256).map(|x| (x as u8, x as u8)).collect::<Vec<_>>()
    );
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }
    .into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn values_rev_collect() {
    assert_eq!(
        vec![3, 2, 1],
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .values()
            .rev()
            .cloned()
            .collect::<Vec<_>>()
    );
}

#[test]
fn values_len() {
    assert_eq!(enum_map! { false => 0, true => 1 }.values().len(), 2);
}

#[test]
fn values_mut_next_back() {
    let mut map = enum_map! { false => 0, true => 1 };
    assert_eq!(map.values_mut().next_back(), Some(&mut 1));
}
#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(Enum)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map! {};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[test]
fn empty_infallible_map() {
    let void: EnumMap<Infallible, Infallible> = enum_map! {};
    assert!(void.is_empty());
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Enum<V> for X {
    type Array = [V; 1];
    const POSSIBLE_VALUES: usize = 1;

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
    assert_eq!(map[X::A(PhantomData)], true);
}

#[test]
fn test_sum() {
    assert_eq!(
        enum_map! { i => u8::into(i) }
            .iter()
            .map(|(_, v)| v)
            .sum::<u32>(),
        32_640
    );
}

#[test]
fn test_sum_mut() {
    assert_eq!(
        enum_map! { i => u8::into(i) }
            .iter_mut()
            .map(|(_, &mut v)| -> u32 { v })
            .sum::<u32>(),
        32_640
    );
}

#[test]
fn test_iter_clone() {
    let map = enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 1 };
    let iter = map.iter();
    assert_eq!(iter.clone().map(|(_, v)| v).sum::<u32>(), 8);
    assert_eq!(iter.map(|(_, v)| v).sum::<u32>(), 8);
    let values = map.values();
    assert_eq!(values.clone().sum::<u32>(), 8);
    assert_eq!(values.sum::<u32>(), 8);
}
<commit_msg>Fix formatting in macros in tests<commit_after>#[macro_use]
extern crate enum_map;

use enum_map::{Enum, EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::convert::Infallible;
use std::marker::PhantomData;

trait From<T>: Sized {
    fn from(_: T) -> Self {
        unreachable!();
    }
}

impl<T, U> From<T> for U {}

#[derive(Copy, Clone, Debug, Enum, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn test_clear() {
    let mut map = enum_map! { false => 1, true => 2 };
    map.clear();
    assert_eq!(map[true], 0);
    assert_eq!(map[false], 0);
}

#[test]
fn discriminants() {
    #[derive(Debug, Enum, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example::A => 3, Example::B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(Enum)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn into_iter_len() {
    assert_eq!(enum_map! { Example::A | _ => 0 }.into_iter().len(), 3);
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

#[test]
fn into_iter_u8() {
    assert_eq!(
        <EnumMap<_, _> as core::convert::From<_>>::from(|i: u8| i)
            .into_iter()
            .collect::<Vec<_>>(),
        (0..256).map(|x| (x as u8, x as u8)).collect::<Vec<_>>()
    );
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }
    .into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn values_rev_collect() {
    assert_eq!(
        vec![3, 2, 1],
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .values()
            .rev()
            .cloned()
            .collect::<Vec<_>>()
    );
}

#[test]
fn values_len() {
    assert_eq!(enum_map! { false => 0, true => 1 }.values().len(), 2);
}

#[test]
fn values_mut_next_back() {
    let mut map = enum_map! { false => 0, true => 1 };
    assert_eq!(map.values_mut().next_back(), Some(&mut 1));
}
#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(Enum)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map! {};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[test]
fn empty_infallible_map() {
    let void: EnumMap<Infallible, Infallible> = enum_map! {};
    assert!(void.is_empty());
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Enum<V> for X {
    type Array = [V; 1];
    const POSSIBLE_VALUES: usize = 1;

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
    assert_eq!(map[X::A(PhantomData)], true);
}

#[test]
fn test_sum() {
    assert_eq!(
        enum_map! { i => u8::into(i) }
            .iter()
            .map(|(_, v)| v)
            .sum::<u32>(),
        32_640
    );
}

#[test]
fn test_sum_mut() {
    assert_eq!(
        enum_map! { i => u8::into(i) }
            .iter_mut()
            .map(|(_, &mut v)| -> u32 { v })
            .sum::<u32>(),
        32_640
    );
}

#[test]
fn test_iter_clone() {
    let map = enum_map! { Example::A => 3, Example::B => 4, Example::C => 1 };
    let iter = map.iter();
    assert_eq!(iter.clone().map(|(_, v)| v).sum::<u32>(), 8);
    assert_eq!(iter.map(|(_, v)| v).sum::<u32>(), 8);
    let values = map.values();
    assert_eq!(values.clone().sum::<u32>(), 8);
    assert_eq!(values.sum::<u32>(), 8);
}
<|endoftext|>


<commit_before>extern crate actix;
extern crate actix_web;
extern crate futures;
extern crate tokio_core;

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use actix::*;
use actix_web::*;
use futures::{future, Future};
use tokio_core::reactor::Timeout;

struct MiddlewareTest {
    start: Arc<AtomicUsize>,
    response: Arc<AtomicUsize>,
    finish: Arc<AtomicUsize>,
}

impl<S> middleware::Middleware<S> for MiddlewareTest {
    fn start(&self, _: &mut HttpRequest<S>) -> Result<middleware::Started> {
        self.start.store(
            self.start.load(Ordering::Relaxed) + 1,
            Ordering::Relaxed,
        );
        Ok(middleware::Started::Done)
    }

    fn response(
        &self, _: &mut HttpRequest<S>, resp: HttpResponse,
    ) -> Result<middleware::Response> {
        self.response.store(
            self.response.load(Ordering::Relaxed) + 1,
            Ordering::Relaxed,
        );
        Ok(middleware::Response::Done(resp))
    }

    fn finish(&self, _: &mut HttpRequest<S>, _: &HttpResponse) -> middleware::Finished {
        self.finish.store(
            self.finish.load(Ordering::Relaxed) + 1,
            Ordering::Relaxed,
        );
        middleware::Finished::Done
    }
}

#[test]
fn test_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        }).handler(|_| HttpResponse::Ok())
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_resource_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        }).handler(|_| HttpResponse::Ok())
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_scope_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        App::new().scope("/scope", |scope| {
            scope
                .middleware(MiddlewareAsyncTest {
                    start: Arc::clone(&act_num1),
                    response: Arc::clone(&act_num2),
                    finish: Arc::clone(&act_num3),
                })
                .resource("/test", |r| r.f(|_| HttpResponse::Ok()))
        })
    });

    let request = srv.get()
        .uri(srv.url("/scope/test"))
        .finish()
        .unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

fn index_test_middleware_async_error(_: HttpRequest) -> FutureResponse<HttpResponse> {
    future::result(Err(error::ErrorBadRequest("TEST"))).responder()
}

#[test]
fn test_middleware_async_error() {
    let req = Arc::new(AtomicUsize::new(0));
    let resp = Arc::new(AtomicUsize::new(0));
    let fin = Arc::new(AtomicUsize::new(0));

    let act_req = Arc::clone(&req);
    let act_resp = Arc::clone(&resp);
    let act_fin = Arc::clone(&fin);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareTest {
            start: Arc::clone(&act_req),
            response: Arc::clone(&act_resp),
            finish: Arc::clone(&act_fin),
        }).handler(index_test_middleware_async_error)
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);

    assert_eq!(req.load(Ordering::Relaxed), 1);
    assert_eq!(resp.load(Ordering::Relaxed), 1);
    assert_eq!(fin.load(Ordering::Relaxed), 1);
}

#[test]
fn test_scope_middleware_async_error() {
    let req = Arc::new(AtomicUsize::new(0));
    let resp = Arc::new(AtomicUsize::new(0));
    let fin = Arc::new(AtomicUsize::new(0));

    let act_req = Arc::clone(&req);
    let act_resp = Arc::clone(&resp);
    let act_fin = Arc::clone(&fin);

    let mut srv = test::TestServer::with_factory(move || {
        App::new().scope("/scope", |scope| {
            scope
                .middleware(MiddlewareAsyncTest {
                    start: Arc::clone(&act_req),
                    response: Arc::clone(&act_resp),
                    finish: Arc::clone(&act_fin),
                })
                .resource("/test", |r| r.f(index_test_middleware_async_error))
        })
    });

    let request = srv.get()
        .uri(srv.url("/scope/test"))
        .finish()
        .unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);

    assert_eq!(req.load(Ordering::Relaxed), 1);
    assert_eq!(resp.load(Ordering::Relaxed), 1);
    assert_eq!(fin.load(Ordering::Relaxed), 1);
}

#[test]
fn test_resource_middleware_async_error() {
    let req = Arc::new(AtomicUsize::new(0));
    let resp = Arc::new(AtomicUsize::new(0));
    let fin = Arc::new(AtomicUsize::new(0));

    let act_req = Arc::clone(&req);
    let act_resp = Arc::clone(&resp);
    let act_fin = Arc::clone(&fin);

    let mut srv = test::TestServer::with_factory(move || {
        let mw = MiddlewareAsyncTest {
            start: Arc::clone(&act_req),
            response: Arc::clone(&act_resp),
            finish: Arc::clone(&act_fin),
        };

        App::new().resource("/test", move |r| {
            r.middleware(mw);
            r.h(index_test_middleware_async_error);
        })
    });

    let request = srv.get().uri(srv.url("/test")).finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);

    assert_eq!(req.load(Ordering::Relaxed), 1);
    assert_eq!(resp.load(Ordering::Relaxed), 1);
    assert_eq!(fin.load(Ordering::Relaxed), 1);
}

struct MiddlewareAsyncTest {
    start: Arc<AtomicUsize>,
    response: Arc<AtomicUsize>,
    finish: Arc<AtomicUsize>,
}

impl<S> middleware::Middleware<S> for MiddlewareAsyncTest {
    fn start(&self, _: &mut HttpRequest<S>) -> Result<middleware::Started> {
        let to = Timeout::new(Duration::from_millis(10), &Arbiter::handle()).unwrap();

        let start = Arc::clone(&self.start);
        Ok(middleware::Started::Future(Box::new(
            to.from_err().and_then(move |_| {
                start.fetch_add(1, Ordering::Relaxed);
                Ok(None)
            }),
        )))
    }

    fn response(
        &self, _: &mut HttpRequest<S>, resp: HttpResponse,
    ) -> Result<middleware::Response> {
        let to = Timeout::new(Duration::from_millis(10), &Arbiter::handle()).unwrap();

        let response = Arc::clone(&self.response);
        Ok(middleware::Response::Future(Box::new(
            to.from_err().and_then(move |_| {
                response.fetch_add(1, Ordering::Relaxed);
                Ok(resp)
            }),
        )))
    }

    fn finish(&self, _: &mut HttpRequest<S>, _: &HttpResponse) -> middleware::Finished {
        let to = Timeout::new(Duration::from_millis(10), &Arbiter::handle()).unwrap();

        let finish = Arc::clone(&self.finish);
        middleware::Finished::Future(Box::new(to.from_err().and_then(move |_| {
            finish.fetch_add(1, Ordering::Relaxed);
            Ok(())
        })))
    }
}

#[test]
fn test_async_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareAsyncTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        }).handler(|_| HttpResponse::Ok())
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);

    thread::sleep(Duration::from_millis(20));
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_async_scope_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        App::new().scope("/scope", |scope| {
            scope
                .middleware(MiddlewareAsyncTest {
                    start: Arc::clone(&act_num1),
                    response: Arc::clone(&act_num2),
                    finish: Arc::clone(&act_num3),
                })
                .resource("/test", |r| r.f(|_| HttpResponse::Ok()))
        })
    });

    let request = srv.get()
        .uri(srv.url("/scope/test"))
        .finish()
        .unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);

    thread::sleep(Duration::from_millis(20));
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_async_resource_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        let mw = MiddlewareAsyncTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        };
        App::new().resource("/test", move |r| {
            r.middleware(mw);
            r.h(|_| HttpResponse::Ok());
        })
    });

    let request = srv.get().uri(srv.url("/test")).finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);

    thread::sleep(Duration::from_millis(20));
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}
<commit_msg>async handle middleware test<commit_after>extern crate actix;
extern crate actix_web;
extern crate futures;
extern crate tokio_core;

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use actix::*;
use actix_web::*;
use futures::{future, Future};
use tokio_core::reactor::Timeout;

struct MiddlewareTest {
    start: Arc<AtomicUsize>,
    response: Arc<AtomicUsize>,
    finish: Arc<AtomicUsize>,
}

impl<S> middleware::Middleware<S> for MiddlewareTest {
    fn start(&self, _: &mut HttpRequest<S>) -> Result<middleware::Started> {
        self.start.store(
            self.start.load(Ordering::Relaxed) + 1,
            Ordering::Relaxed,
        );
        Ok(middleware::Started::Done)
    }

    fn response(
        &self, _: &mut HttpRequest<S>, resp: HttpResponse,
    ) -> Result<middleware::Response> {
        self.response.store(
            self.response.load(Ordering::Relaxed) + 1,
            Ordering::Relaxed,
        );
        Ok(middleware::Response::Done(resp))
    }

    fn finish(&self, _: &mut HttpRequest<S>, _: &HttpResponse) -> middleware::Finished {
        self.finish.store(
            self.finish.load(Ordering::Relaxed) + 1,
            Ordering::Relaxed,
        );
        middleware::Finished::Done
    }
}

#[test]
fn test_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        }).handler(|_| HttpResponse::Ok())
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_resource_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        }).handler(|_| HttpResponse::Ok())
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_scope_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        App::new().scope("/scope", |scope| {
            scope
                .middleware(MiddlewareAsyncTest {
                    start: Arc::clone(&act_num1),
                    response: Arc::clone(&act_num2),
                    finish: Arc::clone(&act_num3),
                })
                .resource("/test", |r| r.f(|_| HttpResponse::Ok()))
        })
    });

    let request = srv.get()
        .uri(srv.url("/scope/test"))
        .finish()
        .unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_middleware_async_handler() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        App::new()
            .middleware(MiddlewareAsyncTest {
                start: Arc::clone(&act_num1),
                response: Arc::clone(&act_num2),
                finish: Arc::clone(&act_num3),
            })
            .resource("/", |r| {
                r.route().a(|_| {
                    Timeout::new(Duration::from_millis(10), &Arbiter::handle())
                        .unwrap()
                        .and_then(|_| Ok(HttpResponse::Ok()))
                })
            })
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    thread::sleep(Duration::from_millis(20));
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_resource_middleware_async_handler() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        let mw = MiddlewareAsyncTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        };
        App::new().resource("/test", |r| {
            r.middleware(mw);
            r.route().a(|_| {
                Timeout::new(Duration::from_millis(10), &Arbiter::handle())
                    .unwrap()
                    .and_then(|_| Ok(HttpResponse::Ok()))
            })
        })
    });

    let request = srv.get().uri(srv.url("/test")).finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_scope_middleware_async_handler() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        App::new().scope("/scope", |scope| {
            scope
                .middleware(MiddlewareAsyncTest {
                    start: Arc::clone(&act_num1),
                    response: Arc::clone(&act_num2),
                    finish: Arc::clone(&act_num3),
                })
                .resource("/test", |r| {
                    r.route().a(|_| {
                        Timeout::new(Duration::from_millis(10), &Arbiter::handle())
                            .unwrap()
                            .and_then(|_| Ok(HttpResponse::Ok()))
                    })
                })
        })
    });

    let request = srv.get()
        .uri(srv.url("/scope/test"))
        .finish()
        .unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

fn index_test_middleware_async_error(_: HttpRequest) -> FutureResponse<HttpResponse> {
    future::result(Err(error::ErrorBadRequest("TEST"))).responder()
}

#[test]
fn test_middleware_async_error() {
    let req = Arc::new(AtomicUsize::new(0));
    let resp = Arc::new(AtomicUsize::new(0));
    let fin = Arc::new(AtomicUsize::new(0));

    let act_req = Arc::clone(&req);
    let act_resp = Arc::clone(&resp);
    let act_fin = Arc::clone(&fin);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareTest {
            start: Arc::clone(&act_req),
            response: Arc::clone(&act_resp),
            finish: Arc::clone(&act_fin),
        }).handler(index_test_middleware_async_error)
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);

    assert_eq!(req.load(Ordering::Relaxed), 1);
    assert_eq!(resp.load(Ordering::Relaxed), 1);
    assert_eq!(fin.load(Ordering::Relaxed), 1);
}

#[test]
fn test_scope_middleware_async_error() {
    let req = Arc::new(AtomicUsize::new(0));
    let resp = Arc::new(AtomicUsize::new(0));
    let fin = Arc::new(AtomicUsize::new(0));

    let act_req = Arc::clone(&req);
    let act_resp = Arc::clone(&resp);
    let act_fin = Arc::clone(&fin);

    let mut srv = test::TestServer::with_factory(move || {
        App::new().scope("/scope", |scope| {
            scope
                .middleware(MiddlewareAsyncTest {
                    start: Arc::clone(&act_req),
                    response: Arc::clone(&act_resp),
                    finish: Arc::clone(&act_fin),
                })
                .resource("/test", |r| r.f(index_test_middleware_async_error))
        })
    });

    let request = srv.get()
        .uri(srv.url("/scope/test"))
        .finish()
        .unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);

    assert_eq!(req.load(Ordering::Relaxed), 1);
    assert_eq!(resp.load(Ordering::Relaxed), 1);
    assert_eq!(fin.load(Ordering::Relaxed), 1);
}

#[test]
fn test_resource_middleware_async_error() {
    let req = Arc::new(AtomicUsize::new(0));
    let resp = Arc::new(AtomicUsize::new(0));
    let fin = Arc::new(AtomicUsize::new(0));

    let act_req = Arc::clone(&req);
    let act_resp = Arc::clone(&resp);
    let act_fin = Arc::clone(&fin);

    let mut srv = test::TestServer::with_factory(move || {
        let mw = MiddlewareAsyncTest {
            start: Arc::clone(&act_req),
            response: Arc::clone(&act_resp),
            finish: Arc::clone(&act_fin),
        };

        App::new().resource("/test", move |r| {
            r.middleware(mw);
            r.h(index_test_middleware_async_error);
        })
    });

    let request = srv.get().uri(srv.url("/test")).finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);

    assert_eq!(req.load(Ordering::Relaxed), 1);
    assert_eq!(resp.load(Ordering::Relaxed), 1);
    assert_eq!(fin.load(Ordering::Relaxed), 1);
}

struct MiddlewareAsyncTest {
    start: Arc<AtomicUsize>,
    response: Arc<AtomicUsize>,
    finish: Arc<AtomicUsize>,
}

impl<S> middleware::Middleware<S> for MiddlewareAsyncTest {
    fn start(&self, _: &mut HttpRequest<S>) -> Result<middleware::Started> {
        let to = Timeout::new(Duration::from_millis(10), &Arbiter::handle()).unwrap();

        let start = Arc::clone(&self.start);
        Ok(middleware::Started::Future(Box::new(
            to.from_err().and_then(move |_| {
                start.fetch_add(1, Ordering::Relaxed);
                Ok(None)
            }),
        )))
    }

    fn response(
        &self, _: &mut HttpRequest<S>, resp: HttpResponse,
    ) -> Result<middleware::Response> {
        let to = Timeout::new(Duration::from_millis(10), &Arbiter::handle()).unwrap();

        let response = Arc::clone(&self.response);
        Ok(middleware::Response::Future(Box::new(
            to.from_err().and_then(move |_| {
                response.fetch_add(1, Ordering::Relaxed);
                Ok(resp)
            }),
        )))
    }

    fn finish(&self, _: &mut HttpRequest<S>, _: &HttpResponse) -> middleware::Finished {
        let to = Timeout::new(Duration::from_millis(10), &Arbiter::handle()).unwrap();

        let finish = Arc::clone(&self.finish);
        middleware::Finished::Future(Box::new(to.from_err().and_then(move |_| {
            finish.fetch_add(1, Ordering::Relaxed);
            Ok(())
        })))
    }
}

#[test]
fn test_async_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::new(move |app| {
        app.middleware(MiddlewareAsyncTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        }).handler(|_| HttpResponse::Ok())
    });

    let request = srv.get().finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);

    thread::sleep(Duration::from_millis(20));
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_async_scope_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        App::new().scope("/scope", |scope| {
            scope
                .middleware(MiddlewareAsyncTest {
                    start: Arc::clone(&act_num1),
                    response: Arc::clone(&act_num2),
                    finish: Arc::clone(&act_num3),
                })
                .resource("/test", |r| r.f(|_| HttpResponse::Ok()))
        })
    });

    let request = srv.get()
        .uri(srv.url("/scope/test"))
        .finish()
        .unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);

    thread::sleep(Duration::from_millis(20));
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}

#[test]
fn test_async_resource_middleware() {
    let num1 = Arc::new(AtomicUsize::new(0));
    let num2 = Arc::new(AtomicUsize::new(0));
    let num3 = Arc::new(AtomicUsize::new(0));

    let act_num1 = Arc::clone(&num1);
    let act_num2 = Arc::clone(&num2);
    let act_num3 = Arc::clone(&num3);

    let mut srv = test::TestServer::with_factory(move || {
        let mw = MiddlewareAsyncTest {
            start: Arc::clone(&act_num1),
            response: Arc::clone(&act_num2),
            finish: Arc::clone(&act_num3),
        };
        App::new().resource("/test", move |r| {
            r.middleware(mw);
            r.h(|_| HttpResponse::Ok());
        })
    });

    let request = srv.get().uri(srv.url("/test")).finish().unwrap();
    let response = srv.execute(request.send()).unwrap();
    assert!(response.status().is_success());

    assert_eq!(num1.load(Ordering::Relaxed), 1);
    assert_eq!(num2.load(Ordering::Relaxed), 1);

    thread::sleep(Duration::from_millis(20));
    assert_eq!(num3.load(Ordering::Relaxed), 1);
}
<|endoftext|>


<commit_before>//! Slither Link solver logic.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate union_find;
extern crate slsr_core;

use std::fmt;
use slsr_core::board::Board;
use slsr_core::geom::CellId;

use solver::Solver;
use theorem_define::THEOREM_DEFINE;

mod model {
    pub mod connect_map;
    pub mod side_map;
    pub mod theorem;
}
mod step {
    pub mod apply_theorem;
    pub mod connect_analysis;
}
mod theorem_define;
mod solver;

#[derive(Copy, Clone, Debug)]
pub struct LogicError;

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

pub type SolverResult<T> = Result<T, LogicError>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum State<T> {
    Fixed(T), Unknown, Conflict
}

impl<T> Into<Result<Option<T>, LogicError>> for State<T> {
    fn into(self) -> Result<Option<T>, LogicError> {
        match self {
            State::Fixed(st) => Ok(Some(st)),
            State::Unknown => Ok(None),
            State::Conflict => Err(LogicError)
        }
    }
}

fn solve_by_logic(solver: &mut Solver) -> SolverResult<()>
{
    let mut init_rev = solver.revision();

    while !solver.all_filled() {
        let mut rev = solver.revision();
        loop {
            try!(solver.apply_all_theorem());

            if solver.revision() == rev {
                break
            }
            rev = solver.revision();
        }

        if solver.all_filled() {
            return Ok(())
        }

        let mut rev = solver.revision();
        loop {
            try!(solver.connect_analysis());

            if solver.revision() == rev {
                break
            }
            rev = solver.revision();
        }

        if solver.revision() == init_rev {
            break;
        }

        init_rev = solver.revision();
    }

    Ok(())
}

fn solve_by_backtracking_one_step(solver: &mut Solver, pts: &[CellId])
                                  -> SolverResult<bool>
{
    let rev = solver.revision();

    for &p in pts {
        match solver.get_side(p) {
            State::Fixed(_) => continue,
            State::Unknown => {}
            State::Conflict => { return Err(LogicError) }
        }

        let mut solver_0 = solver.clone();
        solver_0.set_inside(p);

        if solve_by_logic(&mut solver_0).is_err() {
            solver.set_outside(p);
            try!(solve_by_logic(solver));
            continue
        }

        let mut solver_1 = solver.clone();
        solver_1.set_outside(p);

        if solve_by_logic(&mut solver_1).is_err() {
            *solver = solver_0;
        }
    }

    Ok(solver.revision() != rev)
}

pub fn solve(board: &Board) -> Result<Board, LogicError> {
    let theorem = THEOREM_DEFINE.iter().map(|theo| theo.parse().unwrap());

    let mut queue = vec![try!(Solver::new(board, theorem))];

    'failure: while let Some(mut solver) = queue.pop() {
        if solve_by_logic(&mut solver).is_err() {
            continue
        }

        if solver.all_filled() {
            if solver.validate_result().is_err() {
                continue
            }
            return solver.into()
        }

        let mut pts = solver.get_unknown_points();
        loop {
            match solve_by_backtracking_one_step(&mut solver, &pts) {
                Ok(true) => {
                    if solver.all_filled() {
                        if solver.validate_result().is_err() {
                            continue
                        }
                        return solver.into()
                    }
                    pts = solver.get_unknown_points();
                }
                Ok(false) => break,
                Err(_) => continue 'failure,
            }
        }

        let p = *pts.last().unwrap();
        let mut solver_0 = solver.clone();
        let mut solver_1 = solver;
        solver_0.set_outside(p);
        solver_1.set_inside(p);
        queue.push(solver_0);
        queue.push(solver_1);
    }

    Err(LogicError)
}
<commit_msg>solver: Reduce extra loop<commit_after>//! Slither Link solver logic.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate union_find;
extern crate slsr_core;

use std::fmt;
use slsr_core::board::Board;
use slsr_core::geom::CellId;

use solver::Solver;
use theorem_define::THEOREM_DEFINE;

mod model {
    pub mod connect_map;
    pub mod side_map;
    pub mod theorem;
}
mod step {
    pub mod apply_theorem;
    pub mod connect_analysis;
}
mod theorem_define;
mod solver;

#[derive(Copy, Clone, Debug)]
pub struct LogicError;

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

pub type SolverResult<T> = Result<T, LogicError>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum State<T> {
    Fixed(T), Unknown, Conflict
}

impl<T> Into<Result<Option<T>, LogicError>> for State<T> {
    fn into(self) -> Result<Option<T>, LogicError> {
        match self {
            State::Fixed(st) => Ok(Some(st)),
            State::Unknown => Ok(None),
            State::Conflict => Err(LogicError)
        }
    }
}

fn solve_by_logic(solver: &mut Solver) -> SolverResult<()>
{
    while !solver.all_filled() {
        let rev = solver.revision();

        try!(solver.apply_all_theorem());
        if solver.revision() != rev {
            continue
        }

        try!(solver.connect_analysis());
        if solver.revision() != rev {
            continue
        }

        break
    }

    Ok(())
}

fn solve_by_backtracking_one_step(solver: &mut Solver, pts: &[CellId])
                                  -> SolverResult<bool>
{
    let rev = solver.revision();

    for &p in pts {
        match solver.get_side(p) {
            State::Fixed(_) => continue,
            State::Unknown => {}
            State::Conflict => { return Err(LogicError) }
        }

        let mut solver_0 = solver.clone();
        solver_0.set_inside(p);

        if solve_by_logic(&mut solver_0).is_err() {
            solver.set_outside(p);
            try!(solve_by_logic(solver));
            continue
        }

        let mut solver_1 = solver.clone();
        solver_1.set_outside(p);

        if solve_by_logic(&mut solver_1).is_err() {
            *solver = solver_0;
        }
    }

    Ok(solver.revision() != rev)
}

pub fn solve(board: &Board) -> Result<Board, LogicError> {
    let theorem = THEOREM_DEFINE.iter().map(|theo| theo.parse().unwrap());

    let mut queue = vec![try!(Solver::new(board, theorem))];

    'failure: while let Some(mut solver) = queue.pop() {
        if solve_by_logic(&mut solver).is_err() {
            continue
        }

        if solver.all_filled() {
            if solver.validate_result().is_err() {
                continue
            }
            return solver.into()
        }

        let mut pts = solver.get_unknown_points();
        loop {
            match solve_by_backtracking_one_step(&mut solver, &pts) {
                Ok(true) => {
                    if solver.all_filled() {
                        if solver.validate_result().is_err() {
                            continue
                        }
                        return solver.into()
                    }
                    pts = solver.get_unknown_points();
                }
                Ok(false) => break,
                Err(_) => continue 'failure,
            }
        }

        let p = *pts.last().unwrap();
        let mut solver_0 = solver.clone();
        let mut solver_1 = solver;
        solver_0.set_outside(p);
        solver_1.set_inside(p);
        queue.push(solver_0);
        queue.push(solver_1);
    }

    Err(LogicError)
}
<|endoftext|>


<commit_before>pub trait Key: Copy + PartialEq + Ord + Default {
    type Bytes: AsRef<[u8]>;
    fn into_bytes(self) -> Self::Bytes;
    fn from_bytes(bytes: Self::Bytes) -> Self;
}

macro_rules! impl_key {
    ($type:ident, $size:expr) => {
        impl Key for $type {
            type Bytes = [u8; $size];
            fn into_bytes(self) -> Self::Bytes {
                unsafe {
                    ::std::mem::transmute(self.to_be())
                }
            }

            fn from_bytes(bytes: Self::Bytes) -> Self {
                let integer = unsafe {
                    ::std::mem::transmute(bytes)
                };
                $type::from_be(integer)
            }
        }
    }
}

impl_key!(u8, 1);
impl_key!(u16, 2);
impl_key!(u32, 4);
impl_key!(u64, 8);
#[cfg(feature = "i128")]
impl_key!(u128, 16);
#[cfg(target_pointer_size = "64")]
impl_key!(usize, 8);
#[cfg(target_pointer_size = "32")]
impl_key!(usize, 4);
<commit_msg>Correct pointer size cfg variables<commit_after>pub trait Key: Copy + PartialEq + Ord + Default {
    type Bytes: AsRef<[u8]>;
    fn into_bytes(self) -> Self::Bytes;
    fn from_bytes(bytes: Self::Bytes) -> Self;
}

macro_rules! impl_key {
    ($type:ident, $size:expr) => {
        impl Key for $type {
            type Bytes = [u8; $size];
            fn into_bytes(self) -> Self::Bytes {
                unsafe {
                    ::std::mem::transmute(self.to_be())
                }
            }

            fn from_bytes(bytes: Self::Bytes) -> Self {
                let integer = unsafe {
                    ::std::mem::transmute(bytes)
                };
                $type::from_be(integer)
            }
        }
    }
}

impl_key!(u8, 1);
impl_key!(u16, 2);
impl_key!(u32, 4);
impl_key!(u64, 8);
#[cfg(feature = "i128")]
impl_key!(u128, 16);
#[cfg(target_pointer_width = "32")]
impl_key!(usize, 4);
#[cfg(target_pointer_width = "64")]
impl_key!(usize, 8);
<|endoftext|>


<commit_before>use std::iter;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Position {
  pub offset: usize,
  pub line: usize,
  pub column: usize,
}

impl Position {
  pub fn new(offset: usize, line: usize, column: usize) -> Self {
    Position{
      offset: offset,
      line: line,
      column: column,
    }
  }

  pub fn zero() -> Self {
    Position::new(0, 1, 1)
  }

  pub fn advance(&mut self, char: char) {
    self.offset += 1;
    if char == '\n' {
      self.line += 1;
      self.column = 1;
    } else {
      self.column += 1;
    }
  }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Lexeme<'a, T>(pub T, pub LexemeF<'a>);

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LexemeF<'a> {
  Identifier(&'a str),

  End,
  False,
  Fun,
  True,

  Arrow,
  LeftParenthesis,
  RightParenthesis,
  LeftBrace,
  RightBrace,

  Str(&'a str),
}

#[derive(Clone, Debug)]
pub struct Lexer<'a> {
  input: &'a str,
  position: Position,
  abort: bool,
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Self {
    Lexer{input: input, position: Position::zero(), abort: false}
  }

  pub fn next_position(&self) -> Position {
    self.position
  }

  fn peek_char(&self) -> Option<char> {
    self.input.chars().next()
  }

  fn take_char(&mut self) -> Option<char> {
    let mut chars = self.input.chars();
    let result = chars.next();
    for c in result {
      self.position.advance(c);
    }
    self.input = chars.as_str();
    result
  }

  fn take_chars_while<F>(&mut self, pred: F) -> &'a str
    where F: Fn(char) -> bool {
    let terminator = (self.input.len(), '\n');
    let mut len = 0;
    for (i, c) in self.input.char_indices().chain(iter::once(terminator)) {
      len = i;
      if !pred(c) {
        break;
      }
      self.position.advance(c);
    }
    let result = unsafe { self.input.slice_unchecked(0, len) };
    self.input = unsafe { self.input.slice_unchecked(len, self.input.len()) };
    result
  }
}

impl<'a> Iterator for Lexer<'a> {
  type Item = Result<Lexeme<'a, Position>, Position>;

  fn next(&mut self) -> Option<Self::Item> {
    if self.abort {
      return None;
    }
    self.take_chars_while(is_whitespace);
    let position = self.position;
    match self.peek_char() {
      None =>
        None,
      Some('(') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::LeftParenthesis)))
      },
      Some(')') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::RightParenthesis)))
      },
      Some('{') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::LeftBrace)))
      },
      Some('}') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::RightBrace)))
      },
      Some('-') => {
        self.take_char();
        if self.peek_char() == Some('>') {
          self.take_char();
          Some(Ok(Lexeme(position, LexemeF::Arrow)))
        } else {
          self.abort = true;
          Some(Err(position))
        }
      },
      Some('"') => {
        self.take_char();
        let value = self.take_chars_while(|c| c != '"');
        if self.take_char() != Some('"') {
          Some(Err(position))
        } else {
          Some(Ok(Lexeme(position, LexemeF::Str(value))))
        }
      },
      Some(c) if is_identifier_start(c) => {
        let name = self.take_chars_while(is_identifier_continue);
        Some(Ok(Lexeme(position, match name {
          "end"   => LexemeF::End,
          "false" => LexemeF::False,
          "fun"   => LexemeF::Fun,
          "true"  => LexemeF::True,
          _ => LexemeF::Identifier(name),
        })))
      },
      Some(_) => {
        self.abort = true;
        Some(Err(position))
      },
    }
  }
}

fn is_whitespace(char: char) -> bool {
  char.is_whitespace()
}

// FIXME: Switch to is_xid_start once it is stable.
fn is_identifier_start(char: char) -> bool {
  char.is_alphabetic()
  || char == '_'
}

// FIXME: Switch to is_xid_continue once it is stable.
fn is_identifier_continue(char: char) -> bool {
  is_identifier_start(char)
  || char.is_numeric()
  || char == '\''
  || char == '#'
}

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

  #[test]
  fn test_empty() {
    assert_eq!(
      Lexer::new("").collect::<Vec<_>>(),
      vec![]
    );
  }

  #[test]
  fn test_whitespace() {
    assert_eq!(
      Lexer::new(" \t\r\n").collect::<Vec<_>>(),
      vec![]
    );
  }

  #[test]
  fn test_identifier() {
    assert_eq!(
      Lexer::new("a").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("a")))]
    );
    assert_eq!(
      Lexer::new("ab").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab")))]
    );
    assert_eq!(
      Lexer::new("ab_c").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab_c")))]
    );
    assert_eq!(
      Lexer::new("ab_cd'").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab_cd'")))]
    );
    assert_eq!(
      Lexer::new("funend").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("funend")))]
    );
  }

  #[test]
  fn test_identifiers() {
    assert_eq!(
      Lexer::new("ab cd").collect::<Vec<_>>(),
      vec![
        Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab"))),
        Ok(Lexeme(Position::new(3, 1, 4), LexemeF::Identifier("cd"))),
      ]
    );
  }

  #[test]
  fn test_keywords() {
    assert_eq!(
      Lexer::new("fun end").collect::<Vec<_>>(),
      vec![
        Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Fun)),
        Ok(Lexeme(Position::new(4, 1, 5), LexemeF::End)),
      ]
    );
  }

  #[test]
  fn test_punctuation() {
    assert_eq!(
      Lexer::new("(){}->").collect::<Vec<_>>(),
      vec![
        Ok(Lexeme(Position::new(0, 1, 1), LexemeF::LeftParenthesis)),
        Ok(Lexeme(Position::new(1, 1, 2), LexemeF::RightParenthesis)),
        Ok(Lexeme(Position::new(2, 1, 3), LexemeF::LeftBrace)),
        Ok(Lexeme(Position::new(3, 1, 4), LexemeF::RightBrace)),
        Ok(Lexeme(Position::new(4, 1, 5), LexemeF::Arrow)),
      ]
    );
  }

  #[test]
  fn test_string() {
    assert_eq!(
      Lexer::new("\"foo\"").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Str("foo")))]
    );
    assert_eq!(
      Lexer::new("\"foo").collect::<Vec<_>>(),
      vec![Err(Position::new(0, 1, 1))]
    );
  }
}
<commit_msg>Add comma<commit_after>use std::iter;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Position {
  pub offset: usize,
  pub line: usize,
  pub column: usize,
}

impl Position {
  pub fn new(offset: usize, line: usize, column: usize) -> Self {
    Position{
      offset: offset,
      line: line,
      column: column,
    }
  }

  pub fn zero() -> Self {
    Position::new(0, 1, 1)
  }

  pub fn advance(&mut self, char: char) {
    self.offset += 1;
    if char == '\n' {
      self.line += 1;
      self.column = 1;
    } else {
      self.column += 1;
    }
  }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Lexeme<'a, T>(pub T, pub LexemeF<'a>);

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LexemeF<'a> {
  Identifier(&'a str),

  End,
  False,
  Fun,
  True,

  Arrow,
  Comma,
  LeftParenthesis,
  RightParenthesis,
  LeftBrace,
  RightBrace,

  Str(&'a str),
}

#[derive(Clone, Debug)]
pub struct Lexer<'a> {
  input: &'a str,
  position: Position,
  abort: bool,
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Self {
    Lexer{input: input, position: Position::zero(), abort: false}
  }

  pub fn next_position(&self) -> Position {
    self.position
  }

  fn peek_char(&self) -> Option<char> {
    self.input.chars().next()
  }

  fn take_char(&mut self) -> Option<char> {
    let mut chars = self.input.chars();
    let result = chars.next();
    for c in result {
      self.position.advance(c);
    }
    self.input = chars.as_str();
    result
  }

  fn take_chars_while<F>(&mut self, pred: F) -> &'a str
    where F: Fn(char) -> bool {
    let terminator = (self.input.len(), '\n');
    let mut len = 0;
    for (i, c) in self.input.char_indices().chain(iter::once(terminator)) {
      len = i;
      if !pred(c) {
        break;
      }
      self.position.advance(c);
    }
    let result = unsafe { self.input.slice_unchecked(0, len) };
    self.input = unsafe { self.input.slice_unchecked(len, self.input.len()) };
    result
  }
}

impl<'a> Iterator for Lexer<'a> {
  type Item = Result<Lexeme<'a, Position>, Position>;

  fn next(&mut self) -> Option<Self::Item> {
    if self.abort {
      return None;
    }
    self.take_chars_while(is_whitespace);
    let position = self.position;
    match self.peek_char() {
      None =>
        None,
      Some('(') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::LeftParenthesis)))
      },
      Some(')') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::RightParenthesis)))
      },
      Some('{') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::LeftBrace)))
      },
      Some('}') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::RightBrace)))
      },
      Some(',') => {
        self.take_char();
        Some(Ok(Lexeme(position, LexemeF::Comma)))
      },
      Some('-') => {
        self.take_char();
        if self.peek_char() == Some('>') {
          self.take_char();
          Some(Ok(Lexeme(position, LexemeF::Arrow)))
        } else {
          self.abort = true;
          Some(Err(position))
        }
      },
      Some('"') => {
        self.take_char();
        let value = self.take_chars_while(|c| c != '"');
        if self.take_char() != Some('"') {
          Some(Err(position))
        } else {
          Some(Ok(Lexeme(position, LexemeF::Str(value))))
        }
      },
      Some(c) if is_identifier_start(c) => {
        let name = self.take_chars_while(is_identifier_continue);
        Some(Ok(Lexeme(position, match name {
          "end"   => LexemeF::End,
          "false" => LexemeF::False,
          "fun"   => LexemeF::Fun,
          "true"  => LexemeF::True,
          _ => LexemeF::Identifier(name),
        })))
      },
      Some(_) => {
        self.abort = true;
        Some(Err(position))
      },
    }
  }
}

fn is_whitespace(char: char) -> bool {
  char.is_whitespace()
}

// FIXME: Switch to is_xid_start once it is stable.
fn is_identifier_start(char: char) -> bool {
  char.is_alphabetic()
  || char == '_'
}

// FIXME: Switch to is_xid_continue once it is stable.
fn is_identifier_continue(char: char) -> bool {
  is_identifier_start(char)
  || char.is_numeric()
  || char == '\''
  || char == '#'
}

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

  #[test]
  fn test_empty() {
    assert_eq!(
      Lexer::new("").collect::<Vec<_>>(),
      vec![]
    );
  }

  #[test]
  fn test_whitespace() {
    assert_eq!(
      Lexer::new(" \t\r\n").collect::<Vec<_>>(),
      vec![]
    );
  }

  #[test]
  fn test_identifier() {
    assert_eq!(
      Lexer::new("a").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("a")))]
    );
    assert_eq!(
      Lexer::new("ab").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab")))]
    );
    assert_eq!(
      Lexer::new("ab_c").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab_c")))]
    );
    assert_eq!(
      Lexer::new("ab_cd'").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab_cd'")))]
    );
    assert_eq!(
      Lexer::new("funend").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("funend")))]
    );
  }

  #[test]
  fn test_identifiers() {
    assert_eq!(
      Lexer::new("ab cd").collect::<Vec<_>>(),
      vec![
        Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Identifier("ab"))),
        Ok(Lexeme(Position::new(3, 1, 4), LexemeF::Identifier("cd"))),
      ]
    );
  }

  #[test]
  fn test_keywords() {
    assert_eq!(
      Lexer::new("fun end").collect::<Vec<_>>(),
      vec![
        Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Fun)),
        Ok(Lexeme(Position::new(4, 1, 5), LexemeF::End)),
      ]
    );
  }

  #[test]
  fn test_punctuation() {
    assert_eq!(
      Lexer::new("(){},->").collect::<Vec<_>>(),
      vec![
        Ok(Lexeme(Position::new(0, 1, 1), LexemeF::LeftParenthesis)),
        Ok(Lexeme(Position::new(1, 1, 2), LexemeF::RightParenthesis)),
        Ok(Lexeme(Position::new(2, 1, 3), LexemeF::LeftBrace)),
        Ok(Lexeme(Position::new(3, 1, 4), LexemeF::RightBrace)),
        Ok(Lexeme(Position::new(4, 1, 5), LexemeF::Comma)),
        Ok(Lexeme(Position::new(5, 1, 6), LexemeF::Arrow)),
      ]
    );
  }

  #[test]
  fn test_string() {
    assert_eq!(
      Lexer::new("\"foo\"").collect::<Vec<_>>(),
      vec![Ok(Lexeme(Position::new(0, 1, 1), LexemeF::Str("foo")))]
    );
    assert_eq!(
      Lexer::new("\"foo").collect::<Vec<_>>(),
      vec![Err(Position::new(0, 1, 1))]
    );
  }
}
<|endoftext|>