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

use proc_macro::TokenStream;
use syn::{ItemFn, Stmt, Item, Block, Expr,
          spanned::Spanned,
          fold::Fold};

/// Parses a list of variable names separated by commas
///
/// This is how the compiler passes in arguments to our attribute -- it is
/// everything inside the delimiters after the attribute name.
///```rust,ignore
///     #[wlroots_dehandle(a, b, c)]
///```
struct Args;

impl Fold for Args {
    fn fold_block(&mut self, block: Block) -> Block {
        build_block(block.stmts.iter(), self)
    }
}

/// Attribute to automatically call the `run` method on handles with the
/// remaining block of code.
///
/// The name of the variable you want to use as the upgraded handle should be
/// provided as an argument to the attribute. It does not need to be the same
/// as the handle variable.
///
/// The syntax in the code should be `use $handle as $upgraded_handle`.
/// E.g the variable in the code that stores the handle should go on the
/// **left** and the variable you used in the attribute declaration should
/// go on the **right**.
///
/// # Panics
/// If the handle is invalid (e.g. default constructed, or is a dangling
/// handle) then your code will `panic!`.
///
/// If this is undesirable, please use the non-proc macro `with_handles!`.
///
/// # Example
///
/// ```rust,ignore
/// impl InputManagerHandler for InputManager {
///     #[wlroots_dehandle]
///     fn keyboard_added(&mut self,
///                       compositor_handle: CompositorHandle,
///                       keyboard: KeyboardHandle)
///                       -> Option<Box<Keyboard Handler>> {
///         {
///             #[dehandle] let compositor = compositor_handle;
///             #[dehandle] let keyboard = keyboard;
///             let server: &mut ::Server = compositor.into();
///             server.keyboards.push(keyboard.weak_reference());
///             // Now that we have at least one keyboard, update the seat capabilities.
///             #[dehandle] let seat = &server.seat.seat;
///             let mut capabilities = seat.capabilities();
///             capabilities.insert(Capability::Keyboard);
///             seat.set_capabilities(capabilities);
///             seat.set_keyboard(keyboard.input_device());
///         }
///         // Due to some weird closure inference rules, this has to be outside
///         // of the above block.
///         Some(Box::new(::Keyboard))
///     }
/// }
/// ```
#[proc_macro_attribute]
pub fn wlroots_dehandle(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as ItemFn);
    let output = Args.fold_item_fn(input);
    TokenStream::from(quote!(#output))
}

fn build_block(mut input: std::slice::Iter<Stmt>, args: &mut Args) -> Block {
    let mut output = vec![];
    let mut inner = None;
    while let Some(stmt) = input.next().cloned() {
        use syn::{Pat, punctuated::Pair};
        match stmt.clone() {
            // Recurse into function body
            Stmt::Item(Item::Fn(mut function)) => {
                let inner_block = function.block.clone();
                *function.block = build_block(inner_block.stmts.iter(), args);
                output.push(Stmt::Item(Item::Fn(function)))
            },
            Stmt::Local(mut local) => {
                // Ensure attribute is prefaced here
                let mut dehandle = false;
                for attribute in &local.attrs {
                    let meta = attribute.parse_meta();
                    match meta {
                        Ok(syn::Meta::Word(name)) => {
                            if name.to_string() == "dehandle" {
                                dehandle = true;
                                break;
                            }
                        },
                        _ => {}
                    }
                };
                // Check if this is prefaced with #[dehandle]
                match (dehandle, local.pats.first().map(Pair::into_value).cloned(), local.init.clone()) {
                    (true,
                     Some(Pat::Ident(dehandle_name)),
                     Some((_, body))) => {
                        inner = Some((body, dehandle_name));
                        break;
                    },
                    // Recurse into let call
                    (false, _, Some((_, body))) => {
                        let body = build_block_expr(*body.clone(), args);
                        let stream = quote_spanned!(stmt.span()=> #body);
                        let body: Expr = syn::parse_quote::parse(stream.into());
                        local.init.as_mut().unwrap().1 = Box::new(body);
                        output.push(Stmt::Local(local))
                    },
                    _ => {}
                }
            },
            Stmt::Expr(expr) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body}).into()))
            }
            Stmt::Semi(expr, _) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body;}).into()))
            }
            _ => output.push(stmt)
        }
    }
    if let Some((handle, dehandle)) = inner {
        let inner_block = build_block(input, args);
        let handle_call = syn::parse_quote::parse(quote_spanned!(handle.span()=>
            {(#handle).run(|#dehandle|{
                #inner_block
            }).expect(concat!("Could not upgrade handle ",
                              stringify!(#handle), " to ",
                              stringify!(#dehandle)))}
        ).into());
        output.push(handle_call);
    }
    parse_quote!({#(#output)*})
}

/// Tries to build a block from the expression.
fn build_block_expr(expr: Expr, args: &mut Args) -> Expr {
    match expr {
        Expr::Block(block) => {
            let block = build_block(block.block.stmts.iter(), args);
            syn::parse_quote::parse(quote_spanned!(block.span()=> #block))
        }
        Expr::Let(mut let_expr) => {
            *let_expr.expr = build_block_expr(*let_expr.expr.clone(), args);
            Expr::Let(let_expr)
        },
        Expr::If(mut if_expr) => {
            let then_branch = if_expr.then_branch.clone();
            let then_parsed = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            let then_branch = build_block_expr(then_parsed, args);
            if_expr.then_branch = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            if_expr.else_branch = match if_expr.else_branch.clone() {
                None => if_expr.else_branch,
                Some((token, else_branch)) => {
                    Some((token, Box::new( build_block_expr(*else_branch, args))))
                }
            };
            Expr::If(if_expr)
        },
        Expr::While(mut while_expr) => {
            let body = while_expr.body.clone();
            let body = build_block_expr(syn::parse_quote::parse(
                quote_spanned!(body.span()=> #body)), args);
            while_expr.body = parse_quote!(#body);
            Expr::While(while_expr)
        },
        Expr::ForLoop(mut for_expr) => {
            let body = for_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            for_expr.body = parse_quote!(#body);
            Expr::ForLoop(for_expr)
        },
        Expr::Loop(mut loop_expr) => {
            let body = loop_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            loop_expr.body = parse_quote!(#body);
            Expr::Loop(loop_expr)
        },
        Expr::Match(mut match_expr) => {
            for arm in &mut match_expr.arms {
                *arm.body = build_block_expr(*arm.body.clone(), args)
            }
            Expr::Match(match_expr)
        },
        Expr::Struct(mut struct_expr) => {
            for field in &mut struct_expr.fields {
                field.expr = build_block_expr(field.expr.clone(), args);
            }
            Expr::Struct(struct_expr)
        },
        Expr::Call(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::Call(call_expr)
        },
        Expr::MethodCall(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::MethodCall(call_expr)
        },
        Expr::Closure(mut closure_expr) => {
            *closure_expr.body = build_block_expr(*closure_expr.body.clone(),
                                                  args);
            Expr::Closure(closure_expr)
        },
        Expr::Unsafe(mut unsafe_expr) => {
            unsafe_expr.block = build_block(unsafe_expr.block.stmts.iter(),
                                            args);
            Expr::Unsafe(unsafe_expr)
        },
        Expr::Assign(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::Assign(assign_expr)
        },
        Expr::AssignOp(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::AssignOp(assign_expr)
        },
        Expr::Break(mut break_expr) => {
            match break_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Break(break_expr)
        },
        Expr::Return(mut return_expr) => {
            match return_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Return(return_expr)
        },
        Expr::Reference(mut reference_expr) => {
            *reference_expr.expr = build_block_expr(*reference_expr.expr.clone(),
                                                    args);
            Expr::Reference(reference_expr)
        },
        Expr::Paren(mut paren_expr) => {
            *paren_expr.expr = build_block_expr(*paren_expr.expr.clone(), args);
            Expr::Paren(paren_expr)
        },
        Expr::Unary(mut unary_expr) => {
            *unary_expr.expr = build_block_expr(*unary_expr.expr.clone(), args);
            Expr::Unary(unary_expr)
        },
        Expr::Binary(mut binary_expr) => {
            *binary_expr.left = build_block_expr(*binary_expr.left.clone(), args);
            *binary_expr.right = build_block_expr(*binary_expr.right.clone(), args);
            Expr::Binary(binary_expr)
        },
        v => {
            v
        }
    }
}
<commit_msg>Fixed missing normal lets, cleanup<commit_after>extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;
use syn::{ItemFn, Stmt, Item, Block, Expr,
          spanned::Spanned,
          fold::Fold};

/// Parses a list of variable names separated by commas
///
/// This is how the compiler passes in arguments to our attribute -- it is
/// everything inside the delimiters after the attribute name.
///```rust,ignore
///     #[wlroots_dehandle(a, b, c)]
///```
struct Args;

impl Fold for Args {
    fn fold_block(&mut self, block: Block) -> Block {
        build_block(block.stmts.iter(), self)
    }
}

/// Attribute to automatically call the `run` method on handles with the
/// remaining block of code.
///
/// The name of the variable you want to use as the upgraded handle should be
/// provided as an argument to the attribute. It does not need to be the same
/// as the handle variable.
///
/// The syntax in the code should be `use $handle as $upgraded_handle`.
/// E.g the variable in the code that stores the handle should go on the
/// **left** and the variable you used in the attribute declaration should
/// go on the **right**.
///
/// # Panics
/// If the handle is invalid (e.g. default constructed, or is a dangling
/// handle) then your code will `panic!`.
///
/// If this is undesirable, please use the non-proc macro `with_handles!`.
///
/// # Example
///
/// ```rust,ignore
/// impl InputManagerHandler for InputManager {
///     #[wlroots_dehandle]
///     fn keyboard_added(&mut self,
///                       compositor_handle: CompositorHandle,
///                       keyboard: KeyboardHandle)
///                       -> Option<Box<Keyboard Handler>> {
///         {
///             #[dehandle] let compositor = compositor_handle;
///             #[dehandle] let keyboard = keyboard;
///             let server: &mut ::Server = compositor.into();
///             server.keyboards.push(keyboard.weak_reference());
///             // Now that we have at least one keyboard, update the seat capabilities.
///             #[dehandle] let seat = &server.seat.seat;
///             let mut capabilities = seat.capabilities();
///             capabilities.insert(Capability::Keyboard);
///             seat.set_capabilities(capabilities);
///             seat.set_keyboard(keyboard.input_device());
///         }
///         // Due to some weird closure inference rules, this has to be outside
///         // of the above block.
///         Some(Box::new(::Keyboard))
///     }
/// }
/// ```
#[proc_macro_attribute]
pub fn wlroots_dehandle(_args: TokenStream, input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as ItemFn);
    let output = Args.fold_item_fn(input);
    TokenStream::from(quote!(#output))
}

fn build_block(mut input: std::slice::Iter<Stmt>, args: &mut Args) -> Block {
    let mut output = vec![];
    let mut inner = None;
    while let Some(stmt) = input.next().cloned() {
        use syn::{Pat, punctuated::Pair};
        match stmt.clone() {
            // Recurse into function body
            Stmt::Item(Item::Fn(mut function)) => {
                let inner_block = function.block.clone();
                *function.block = build_block(inner_block.stmts.iter(), args);
                output.push(Stmt::Item(Item::Fn(function)))
            },
            Stmt::Local(mut local) => {
                // Ensure attribute is prefaced here
                let mut dehandle = false;
                for attribute in &local.attrs {
                    let meta = attribute.parse_meta();
                    match meta {
                        Ok(syn::Meta::Word(name)) => {
                            if name.to_string() == "dehandle" {
                                dehandle = true;
                                break;
                            }
                        },
                        _ => {}
                    }
                };
                let left_side = local.pats.first().map(Pair::into_value).cloned();
                let right_side = local.init.clone();
                match (dehandle, left_side, right_side) {
                    (true,
                     Some(Pat::Ident(dehandle_name)),
                     Some((_, body))) => {
                        inner = Some((body, dehandle_name));
                        break;
                    },
                    // Recurse into let call
                    (false, _, Some((_, body))) => {
                        let body = build_block_expr(*body.clone(), args);
                        let stream = quote_spanned!(stmt.span()=> #body);
                        let body: Expr = syn::parse_quote::parse(stream.into());
                        local.init.as_mut().unwrap().1 = Box::new(body);
                        output.push(Stmt::Local(local))
                    },
                    _ => output.push(Stmt::Local(local))
                }
            },
            Stmt::Expr(expr) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body}).into()))
            }
            Stmt::Semi(expr, _) => {
                let body = build_block_expr(expr, args);
                output.push(syn::parse_quote::parse(quote_spanned!(stmt.span()=> {#body;}).into()))
            }
            _ => output.push(stmt)
        }
    }
    if let Some((handle, dehandle)) = inner {
        let inner_block = build_block(input, args);
        let handle_call = syn::parse_quote::parse(quote_spanned!(handle.span()=>
            {(#handle).run(|#dehandle|{
                #inner_block
            }).expect(concat!("Could not upgrade handle ",
                              stringify!(#handle), " to ",
                              stringify!(#dehandle)))}
        ).into());
        output.push(handle_call);
    }
    parse_quote!({#(#output)*})
}

/// Tries to build a block from the expression.
fn build_block_expr(expr: Expr, args: &mut Args) -> Expr {
    match expr {
        Expr::Block(block) => {
            let block = build_block(block.block.stmts.iter(), args);
            syn::parse_quote::parse(quote_spanned!(block.span()=> #block))
        }
        Expr::Let(mut let_expr) => {
            *let_expr.expr = build_block_expr(*let_expr.expr.clone(), args);
            Expr::Let(let_expr)
        },
        Expr::If(mut if_expr) => {
            let then_branch = if_expr.then_branch.clone();
            let then_parsed = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            let then_branch = build_block_expr(then_parsed, args);
            if_expr.then_branch = syn::parse_quote::parse(
                quote_spanned!(then_branch.span()=> #then_branch));
            if_expr.else_branch = match if_expr.else_branch.clone() {
                None => if_expr.else_branch,
                Some((token, else_branch)) => {
                    Some((token, Box::new( build_block_expr(*else_branch, args))))
                }
            };
            Expr::If(if_expr)
        },
        Expr::While(mut while_expr) => {
            let body = while_expr.body.clone();
            let body = build_block_expr(syn::parse_quote::parse(
                quote_spanned!(body.span()=> #body)), args);
            while_expr.body = parse_quote!(#body);
            Expr::While(while_expr)
        },
        Expr::ForLoop(mut for_expr) => {
            let body = for_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            for_expr.body = parse_quote!(#body);
            Expr::ForLoop(for_expr)
        },
        Expr::Loop(mut loop_expr) => {
            let body = loop_expr.body.clone();
            let body = build_block_expr(parse_quote!(#body), args);
            loop_expr.body = parse_quote!(#body);
            Expr::Loop(loop_expr)
        },
        Expr::Match(mut match_expr) => {
            for arm in &mut match_expr.arms {
                *arm.body = build_block_expr(*arm.body.clone(), args)
            }
            Expr::Match(match_expr)
        },
        Expr::Struct(mut struct_expr) => {
            for field in &mut struct_expr.fields {
                field.expr = build_block_expr(field.expr.clone(), args);
            }
            Expr::Struct(struct_expr)
        },
        Expr::Call(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::Call(call_expr)
        },
        Expr::MethodCall(mut call_expr) => {
            for arg in &mut call_expr.args {
                *arg = build_block_expr(arg.clone(), args);
            }
            Expr::MethodCall(call_expr)
        },
        Expr::Closure(mut closure_expr) => {
            *closure_expr.body = build_block_expr(*closure_expr.body.clone(),
                                                  args);
            Expr::Closure(closure_expr)
        },
        Expr::Unsafe(mut unsafe_expr) => {
            unsafe_expr.block = build_block(unsafe_expr.block.stmts.iter(),
                                            args);
            Expr::Unsafe(unsafe_expr)
        },
        Expr::Assign(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::Assign(assign_expr)
        },
        Expr::AssignOp(mut assign_expr) => {
            *assign_expr.right = build_block_expr(*assign_expr.right.clone(),
                                                  args);
            Expr::AssignOp(assign_expr)
        },
        Expr::Break(mut break_expr) => {
            match break_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Break(break_expr)
        },
        Expr::Return(mut return_expr) => {
            match return_expr.expr {
                None => {},
                Some(ref mut expr) => {
                    **expr = build_block_expr(*expr.clone(), args);
                }
            }
            Expr::Return(return_expr)
        },
        Expr::Reference(mut reference_expr) => {
            *reference_expr.expr = build_block_expr(*reference_expr.expr.clone(),
                                                    args);
            Expr::Reference(reference_expr)
        },
        Expr::Paren(mut paren_expr) => {
            *paren_expr.expr = build_block_expr(*paren_expr.expr.clone(), args);
            Expr::Paren(paren_expr)
        },
        Expr::Unary(mut unary_expr) => {
            *unary_expr.expr = build_block_expr(*unary_expr.expr.clone(), args);
            Expr::Unary(unary_expr)
        },
        Expr::Binary(mut binary_expr) => {
            *binary_expr.left = build_block_expr(*binary_expr.left.clone(), args);
            *binary_expr.right = build_block_expr(*binary_expr.right.clone(), args);
            Expr::Binary(binary_expr)
        },
        v => {
            v
        }
    }
}
<|endoftext|>


<commit_before>
use npffi;
use pyffi;
use cpython::*;
use npffi::types::npy_intp;
use super::{NPY_TYPES, NPY_ORDER};

pub struct PyArray(PyObject);

impl PyArray {
    pub fn as_ptr(&self) -> *mut npffi::PyArrayObject {
        self.0.as_ptr() as *mut npffi::PyArrayObject
    }

    pub fn steal_ptr(self) -> *mut npffi::PyArrayObject {
        self.0.steal_ptr() as *mut npffi::PyArrayObject
    }

    pub unsafe fn from_owned_ptr(py: Python, ptr: *mut pyffi::PyObject) -> Self {
        let obj = PyObject::from_owned_ptr(py, ptr);
        PyArray(obj)
    }

    pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut pyffi::PyObject) -> Self {
        let obj = PyObject::from_borrowed_ptr(py, ptr);
        PyArray(obj)
    }

    pub fn ndim(&self) -> usize {
        let ptr = self.as_ptr();
        unsafe { (*ptr).nd as usize }
    }

    pub fn dims(&self) -> Vec<usize> {
        let n = self.ndim();
        let ptr = self.as_ptr();
        let dims = unsafe {
            let p = (*ptr).dimensions;
            ::std::slice::from_raw_parts(p, n)
        };
        dims.into_iter().map(|d| *d as usize).collect()
    }

    pub fn len(&self) -> usize {
        self.dims().iter().fold(1, |a, b| a * b)
    }

    pub fn shape(&self) -> Vec<usize> {
        self.dims()
    }

    pub fn strides(&self) -> Vec<isize> {
        let n = self.ndim();
        let ptr = self.as_ptr();
        let dims = unsafe {
            let p = (*ptr).strides;
            ::std::slice::from_raw_parts(p, n)
        };
        dims.into_iter().map(|d| *d as isize).collect()
    }

    pub fn as_slice<T>(&self) -> &[T] {
        let n = self.len();
        let ptr = self.as_ptr();
        unsafe {
            let p = (*ptr).data as *mut T;
            ::std::slice::from_raw_parts(p, n)
        }
    }

    pub fn as_slice_mut<T>(&mut self) -> &mut [T] {
        let n = self.len();
        let ptr = self.as_ptr();
        unsafe {
            let p = (*ptr).data as *mut T;
            ::std::slice::from_raw_parts_mut(p, n)
        }
    }

    /// a wrapper of PyArray_SimpleNew
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_SimpleNew
    pub fn new(py: Python, dims: &[usize], typenum: NPY_TYPES) -> Self {
        let dims: Vec<npy_intp> = dims.iter().map(|d| *d as npy_intp).collect();
        unsafe {
            let ptr = npffi::PyArray_New(npffi::ARRAY_TYPE::PyArray_Type.as_type_object(),
                                         dims.len() as i32,
                                         dims.as_ptr() as *mut npy_intp,
                                         typenum as i32,
                                         ::std::ptr::null_mut(),
                                         ::std::ptr::null_mut(),
                                         0,
                                         0,
                                         ::std::ptr::null_mut());
            Self::from_owned_ptr(py, ptr)
        }
    }

    /// a wrapper of PyArray_ZEROS
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_ZEROS
    pub fn zeros(py: Python, dims: &[usize], typenum: NPY_TYPES, order: NPY_ORDER) -> Self {
        let dims: Vec<npy_intp> = dims.iter().map(|d| *d as npy_intp).collect();
        unsafe {
            let descr = npffi::PyArray_DescrFromType(typenum as i32);
            let ptr = npffi::PyArray_Zeros(dims.len() as i32,
                                           dims.as_ptr() as *mut npy_intp,
                                           descr,
                                           order as i32);
            Self::from_owned_ptr(py, ptr)
        }
    }

    /// a wrapper of PyArray_Arange
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_Arange
    pub fn arange(py: Python, start: f64, stop: f64, step: f64, typenum: NPY_TYPES) -> Self {
        unsafe {
            let ptr = npffi::PyArray_Arange(start, stop, step, typenum as i32);
            Self::from_owned_ptr(py, ptr)
        }
    }
}

impl ToPyObject for PyArray {
    type ObjectType = Self;

    fn to_py_object(&self, py: Python) -> Self {
        PyClone::clone_ref(self, py)
    }
}

impl PythonObject for PyArray {
    #[inline]
    fn as_object(&self) -> &PyObject {
        &self.0
    }

    #[inline]
    fn into_object(self) -> PyObject {
        self.0
    }

    #[inline]
    unsafe fn unchecked_downcast_from(obj: PyObject) -> Self {
        PyArray(obj)
    }

    #[inline]
    unsafe fn unchecked_downcast_borrow_from<'a>(obj: &'a PyObject) -> &'a Self {
        ::std::mem::transmute(obj)
    }
}

impl PythonObjectWithCheckedDowncast for PyArray {
    fn downcast_from<'p>(py: Python<'p>,
                         obj: PyObject)
                         -> Result<PyArray, PythonObjectDowncastError<'p>> {
        unsafe {
            if npffi::PyArray_Check(obj.as_ptr()) != 0 {
                Ok(PyArray(obj))
            } else {
                Err(PythonObjectDowncastError(py))
            }
        }
    }

    fn downcast_borrow_from<'a, 'p>(py: Python<'p>,
                                    obj: &'a PyObject)
                                    -> Result<&'a PyArray, PythonObjectDowncastError<'p>> {
        unsafe {
            if npffi::PyArray_Check(obj.as_ptr()) != 0 {
                Ok(::std::mem::transmute(obj))
            } else {
                Err(PythonObjectDowncastError(py))
            }
        }
    }
}
<commit_msg>Add documents<commit_after>
use npffi;
use pyffi;
use cpython::*;
use npffi::types::npy_intp;
use super::{NPY_TYPES, NPY_ORDER};

pub struct PyArray(PyObject);

impl PyArray {
    pub fn as_ptr(&self) -> *mut npffi::PyArrayObject {
        self.0.as_ptr() as *mut npffi::PyArrayObject
    }

    pub fn steal_ptr(self) -> *mut npffi::PyArrayObject {
        self.0.steal_ptr() as *mut npffi::PyArrayObject
    }

    pub unsafe fn from_owned_ptr(py: Python, ptr: *mut pyffi::PyObject) -> Self {
        let obj = PyObject::from_owned_ptr(py, ptr);
        PyArray(obj)
    }

    pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut pyffi::PyObject) -> Self {
        let obj = PyObject::from_borrowed_ptr(py, ptr);
        PyArray(obj)
    }

    /// The number of dimensions in the array
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_NDIM
    pub fn ndim(&self) -> usize {
        let ptr = self.as_ptr();
        unsafe { (*ptr).nd as usize }
    }

    /// dimensions of the array
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_DIMS
    pub fn dims(&self) -> Vec<usize> {
        let n = self.ndim();
        let ptr = self.as_ptr();
        let dims = unsafe {
            let p = (*ptr).dimensions;
            ::std::slice::from_raw_parts(p, n)
        };
        dims.into_iter().map(|d| *d as usize).collect()
    }

    pub fn len(&self) -> usize {
        self.dims().iter().fold(1, |a, b| a * b)
    }

    /// A synonym for PyArray_DIMS, named to be consistent with the ‘shape’ usage within Python.
    pub fn shape(&self) -> Vec<usize> {
        self.dims()
    }

    /// The number of elements matches the number of dimensions of the array
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_STRIDES
    /// For the explaination of stride, see also https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.strides.html#numpy.ndarray.strides
    pub fn strides(&self) -> Vec<isize> {
        let n = self.ndim();
        let ptr = self.as_ptr();
        let dims = unsafe {
            let p = (*ptr).strides;
            ::std::slice::from_raw_parts(p, n)
        };
        dims.into_iter().map(|d| *d as isize).collect()
    }

    /// Get data as a Rust immutable slice
    pub fn as_slice<T>(&self) -> &[T] {
        let n = self.len();
        let ptr = self.as_ptr();
        unsafe {
            let p = (*ptr).data as *mut T;
            ::std::slice::from_raw_parts(p, n)
        }
    }

    /// Get data as a Rust mutable slice
    pub fn as_slice_mut<T>(&mut self) -> &mut [T] {
        let n = self.len();
        let ptr = self.as_ptr();
        unsafe {
            let p = (*ptr).data as *mut T;
            ::std::slice::from_raw_parts_mut(p, n)
        }
    }

    /// a wrapper of PyArray_SimpleNew
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_SimpleNew
    pub fn new(py: Python, dims: &[usize], typenum: NPY_TYPES) -> Self {
        let dims: Vec<npy_intp> = dims.iter().map(|d| *d as npy_intp).collect();
        unsafe {
            let ptr = npffi::PyArray_New(npffi::ARRAY_TYPE::PyArray_Type.as_type_object(),
                                         dims.len() as i32,
                                         dims.as_ptr() as *mut npy_intp,
                                         typenum as i32,
                                         ::std::ptr::null_mut(),
                                         ::std::ptr::null_mut(),
                                         0,
                                         0,
                                         ::std::ptr::null_mut());
            Self::from_owned_ptr(py, ptr)
        }
    }

    /// a wrapper of PyArray_ZEROS
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_ZEROS
    pub fn zeros(py: Python, dims: &[usize], typenum: NPY_TYPES, order: NPY_ORDER) -> Self {
        let dims: Vec<npy_intp> = dims.iter().map(|d| *d as npy_intp).collect();
        unsafe {
            let descr = npffi::PyArray_DescrFromType(typenum as i32);
            let ptr = npffi::PyArray_Zeros(dims.len() as i32,
                                           dims.as_ptr() as *mut npy_intp,
                                           descr,
                                           order as i32);
            Self::from_owned_ptr(py, ptr)
        }
    }

    /// a wrapper of PyArray_Arange
    /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_Arange
    pub fn arange(py: Python, start: f64, stop: f64, step: f64, typenum: NPY_TYPES) -> Self {
        unsafe {
            let ptr = npffi::PyArray_Arange(start, stop, step, typenum as i32);
            Self::from_owned_ptr(py, ptr)
        }
    }
}

impl ToPyObject for PyArray {
    type ObjectType = Self;

    fn to_py_object(&self, py: Python) -> Self {
        PyClone::clone_ref(self, py)
    }
}

impl PythonObject for PyArray {
    #[inline]
    fn as_object(&self) -> &PyObject {
        &self.0
    }

    #[inline]
    fn into_object(self) -> PyObject {
        self.0
    }

    #[inline]
    unsafe fn unchecked_downcast_from(obj: PyObject) -> Self {
        PyArray(obj)
    }

    #[inline]
    unsafe fn unchecked_downcast_borrow_from<'a>(obj: &'a PyObject) -> &'a Self {
        ::std::mem::transmute(obj)
    }
}

impl PythonObjectWithCheckedDowncast for PyArray {
    fn downcast_from<'p>(py: Python<'p>,
                         obj: PyObject)
                         -> Result<PyArray, PythonObjectDowncastError<'p>> {
        unsafe {
            if npffi::PyArray_Check(obj.as_ptr()) != 0 {
                Ok(PyArray(obj))
            } else {
                Err(PythonObjectDowncastError(py))
            }
        }
    }

    fn downcast_borrow_from<'a, 'p>(py: Python<'p>,
                                    obj: &'a PyObject)
                                    -> Result<&'a PyArray, PythonObjectDowncastError<'p>> {
        unsafe {
            if npffi::PyArray_Check(obj.as_ptr()) != 0 {
                Ok(::std::mem::transmute(obj))
            } else {
                Err(PythonObjectDowncastError(py))
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::{Command, Merge};
#[cfg(feature = "display")]
use std::fmt;
use std::{
    iter::{FromIterator, IntoIterator},
    vec::IntoIter,
};

/// A chain of merged commands.
///
/// Commands in a chain are all executed in the order they was merged in.
///
/// # Examples
///
/// ```
/// # use undo::*;
/// # struct Add(char);
/// # impl Command<String> for Add {
/// #     fn apply(&mut self, s: &mut String) -> undo::Result {
/// #         s.push(self.0);
/// #         Ok(())
/// #     }
/// #     fn undo(&mut self, s: &mut String) -> undo::Result {
/// #         self.0 = s.pop().ok_or("`s` is empty")?;
/// #         Ok(())
/// #     }
/// # }
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let chain = Chain::new()
///     .join(Add('a'))
///     .join(Add('b'));
/// record.apply(chain)?;
/// assert_eq!(record.as_receiver(), "ab");
/// record.undo().unwrap()?;
/// assert_eq!(record.as_receiver(), "");
/// record.redo().unwrap()?;
/// assert_eq!(record.as_receiver(), "ab");
/// # Ok(())
/// # }
/// ```
pub struct Chain<R> {
    commands: Vec<Box<dyn Command<R>>>,
    merge: Option<Merge>,
    #[cfg(feature = "display")]
    text: Option<String>,
}

impl<R> Chain<R> {
    /// Returns an empty command.
    #[inline]
    pub fn new() -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Creates a new command with the provided text.
    #[inline]
    #[cfg(feature = "display")]
    pub fn with_text(text: impl Into<String>) -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: Some(text.into()),
        }
    }

    /// Returns an empty command with the specified capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Chain<R> {
        Chain {
            commands: Vec::with_capacity(capacity),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Reserves capacity for at least `additional` more commands in the chain.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.commands.reserve(additional);
    }

    /// Returns the capacity of the chain.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.commands.capacity()
    }

    /// Returns the amount of commands that have been merged.
    #[inline]
    pub fn len(&self) -> usize {
        self.commands.len()
    }

    /// Returns `true` if no commands have been merged.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.commands.is_empty()
    }

    /// Merges the command with the chain.
    #[inline]
    pub fn push(&mut self, command: impl Command<R> + 'static) {
        self.commands.push(Box::new(command));
    }

    /// Merges the command with the chain and returns the chain.
    #[inline]
    pub fn join(mut self, command: impl Command<R> + 'static) -> Chain<R> {
        self.push(command);
        self
    }

    /// Sets the merge behavior of the chain.
    #[inline]
    pub fn set_merge(&mut self, merge: Merge) {
        self.merge = Some(merge);
    }

    /// Returns the text for the chain.
    #[inline]
    #[cfg(feature = "display")]
    pub fn text(&self) -> Option<&str> {
        self.text.as_ref().map(String::as_str)
    }

    /// Sets the text for the chain.
    #[inline]
    #[cfg(feature = "display")]
    pub fn set_text(&mut self, text: impl Into<String>) {
        self.text = Some(text.into());
    }
}

impl<R> Command<R> for Chain<R> {
    #[inline]
    fn apply(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.apply(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> crate::Result {
        for command in self.commands.iter_mut().rev() {
            command.undo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn redo(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.redo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn merge(&self) -> Merge {
        self.merge
            .or_else(|| self.commands.first().map(Command::merge))
            .unwrap_or(Merge::Yes)
    }

    #[inline]
    fn is_dead(&self) -> bool {
        self.commands.iter().any(Command::is_dead)
    }
}

impl<R> Default for Chain<R> {
    #[inline]
    fn default() -> Self {
        Chain::new()
    }
}

impl<R, C: Command<R> + 'static> FromIterator<C> for Chain<R> {
    #[inline]
    fn from_iter<T: IntoIterator<Item = C>>(commands: T) -> Self {
        Chain {
            commands: commands.into_iter().map(|c| Box::new(c) as _).collect(),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }
}

impl<R> IntoIterator for Chain<R> {
    type Item = Box<dyn Command<R>>;
    type IntoIter = IntoIter<Self::Item>;

    #[inline]
    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.commands.into_iter()
    }
}

impl<R, C: Command<R> + 'static> Extend<C> for Chain<R> {
    #[inline]
    fn extend<T: IntoIterator<Item = C>>(&mut self, iter: T) {
        self.commands
            .extend(iter.into_iter().map(|c| Box::new(c) as _));
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Debug for Chain<R> {
    #[inline]
    #[cfg(not(feature = "display"))]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Merged")
            .field("commands", &self.commands)
            .finish()
    }

    #[inline]
    #[cfg(feature = "display")]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Merged")
            .field("commands", &self.commands)
            .field("text", &self.text)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Chain<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.text {
            Some(text) => f.write_str(text),
            None => {
                for command in &self.commands {
                    writeln!(f, "- {}", command)?;
                }
                Ok(())
            }
        }
    }
}
<commit_msg>Add merge field to debug impl<commit_after>use crate::{Command, Merge};
#[cfg(feature = "display")]
use std::fmt;
use std::{
    iter::{FromIterator, IntoIterator},
    vec::IntoIter,
};

/// A chain of merged commands.
///
/// Commands in a chain are all executed in the order they was merged in.
///
/// # Examples
///
/// ```
/// # use undo::*;
/// # struct Add(char);
/// # impl Command<String> for Add {
/// #     fn apply(&mut self, s: &mut String) -> undo::Result {
/// #         s.push(self.0);
/// #         Ok(())
/// #     }
/// #     fn undo(&mut self, s: &mut String) -> undo::Result {
/// #         self.0 = s.pop().ok_or("`s` is empty")?;
/// #         Ok(())
/// #     }
/// # }
/// # fn main() -> undo::Result {
/// let mut record = Record::default();
/// let chain = Chain::with_capacity(2)
///     .join(Add('a'))
///     .join(Add('b'));
/// record.apply(chain)?;
/// assert_eq!(record.as_receiver(), "ab");
/// record.undo().unwrap()?;
/// assert_eq!(record.as_receiver(), "");
/// record.redo().unwrap()?;
/// assert_eq!(record.as_receiver(), "ab");
/// # Ok(())
/// # }
/// ```
pub struct Chain<R> {
    commands: Vec<Box<dyn Command<R>>>,
    merge: Option<Merge>,
    #[cfg(feature = "display")]
    text: Option<String>,
}

impl<R> Chain<R> {
    /// Returns an empty command.
    #[inline]
    pub fn new() -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Creates a new command with the provided text.
    #[inline]
    #[cfg(feature = "display")]
    pub fn with_text(text: impl Into<String>) -> Chain<R> {
        Chain {
            commands: vec![],
            merge: None,
            #[cfg(feature = "display")]
            text: Some(text.into()),
        }
    }

    /// Returns an empty command with the specified capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Chain<R> {
        Chain {
            commands: Vec::with_capacity(capacity),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }

    /// Reserves capacity for at least `additional` more commands in the chain.
    ///
    /// # Panics
    /// Panics if the new capacity overflows usize.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.commands.reserve(additional);
    }

    /// Returns the capacity of the chain.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.commands.capacity()
    }

    /// Returns the amount of commands in the chain.
    #[inline]
    pub fn len(&self) -> usize {
        self.commands.len()
    }

    /// Returns `true` if no commands have been merged.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.commands.is_empty()
    }

    /// Merges the command with the chain.
    #[inline]
    pub fn push(&mut self, command: impl Command<R> + 'static) {
        self.commands.push(Box::new(command));
    }

    /// Merges the command with the chain and returns the chain.
    #[inline]
    pub fn join(mut self, command: impl Command<R> + 'static) -> Chain<R> {
        self.push(command);
        self
    }

    /// Sets the merge behavior of the chain.
    ///
    /// By default the merge behavior of the first command in the chain is used,
    /// and it always merges if the chain is empty.
    #[inline]
    pub fn set_merge(&mut self, merge: Merge) {
        self.merge = Some(merge);
    }

    /// Returns the text for the chain.
    #[inline]
    #[cfg(feature = "display")]
    pub fn text(&self) -> Option<&str> {
        self.text.as_ref().map(String::as_str)
    }

    /// Sets the text for the chain.
    #[inline]
    #[cfg(feature = "display")]
    pub fn set_text(&mut self, text: impl Into<String>) {
        self.text = Some(text.into());
    }
}

impl<R> Command<R> for Chain<R> {
    #[inline]
    fn apply(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.apply(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn undo(&mut self, receiver: &mut R) -> crate::Result {
        for command in self.commands.iter_mut().rev() {
            command.undo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn redo(&mut self, receiver: &mut R) -> crate::Result {
        for command in &mut self.commands {
            command.redo(receiver)?;
        }
        Ok(())
    }

    #[inline]
    fn merge(&self) -> Merge {
        self.merge
            .or_else(|| self.commands.first().map(Command::merge))
            .unwrap_or(Merge::Yes)
    }

    #[inline]
    fn is_dead(&self) -> bool {
        self.commands.iter().any(Command::is_dead)
    }
}

impl<R> Default for Chain<R> {
    #[inline]
    fn default() -> Self {
        Chain::new()
    }
}

impl<R, C: Command<R> + 'static> FromIterator<C> for Chain<R> {
    #[inline]
    fn from_iter<T: IntoIterator<Item = C>>(commands: T) -> Self {
        Chain {
            commands: commands.into_iter().map(|c| Box::new(c) as _).collect(),
            merge: None,
            #[cfg(feature = "display")]
            text: None,
        }
    }
}

impl<R> IntoIterator for Chain<R> {
    type Item = Box<dyn Command<R>>;
    type IntoIter = IntoIter<Self::Item>;

    #[inline]
    fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
        self.commands.into_iter()
    }
}

impl<R, C: Command<R> + 'static> Extend<C> for Chain<R> {
    #[inline]
    fn extend<T: IntoIterator<Item = C>>(&mut self, iter: T) {
        self.commands
            .extend(iter.into_iter().map(|c| Box::new(c) as _));
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Debug for Chain<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Chain")
            .field("commands", &self.commands)
            .field("merge", &self.merge)
            .field("text", &self.text)
            .finish()
    }
}

#[cfg(feature = "display")]
impl<R> fmt::Display for Chain<R> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.text {
            Some(text) => f.write_str(text),
            None => {
                for command in &self.commands {
                    writeln!(f, "- {}", command)?;
                }
                Ok(())
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate zmq;

use zmq::{Context, Message};

fn main() {
    println!("24 days of Rust - zmq (day 20)");
    let args = std::env::args().collect::<Vec<_>>();
    if args.len() < 2 {
        println!("Usage: {} (client|server)", args[0]);
        return;
    }
    let mut ctx = Context::new();
    let addr = "tcp://127.0.0.1:25933";
    if args[1] == "client" {
        println!("ZeroMQ client connecting to {}", addr);
        let mut sock = ctx.socket(zmq::REQ).unwrap();
        let _ = sock.connect(addr);
        let payload = "Hello world!";
        println!("-> {:?}", payload);
        let mut msg = Message::new().unwrap();
        sock.send(payload.as_bytes(), 0).unwrap();
        sock.recv(&mut msg, 0).unwrap();
        let contents = msg.as_str().unwrap();
        println!("<- {:?}", contents);
    }
    else {
        println!("ZeroMQ server listening on {}", addr);
        let mut sock = ctx.socket(zmq::REP).unwrap();
        let _ = sock.bind(addr);
        let mut msg = Message::new().unwrap();
        loop {
            if let Ok(_) = sock.recv(&mut msg, 0) {
                sock.send_str(msg.as_str().unwrap(), 0).unwrap();
            }
        }
    }
}
<commit_msg>Rewrite client and server to use try! for error handling.<commit_after>extern crate zmq;

use zmq::{Context, Message, Error};

fn run_client(ctx: &mut Context, addr: &str) -> Result<(), Error> {
    let mut sock = try!(ctx.socket(zmq::REQ));
    try!(sock.connect(addr));
    let payload = "Hello world!";
    println!("-> {:?}", payload);
    let mut msg = try!(Message::new());
    try!(sock.send(payload.as_bytes(), 0));
    try!(sock.recv(&mut msg, 0));
    let contents = msg.as_str().unwrap();
    println!("<- {:?}", contents);
    Ok(())
}

fn run_server(ctx: &mut Context, addr: &str) -> Result<(), Error> {
    let mut sock = try!(ctx.socket(zmq::REP));
    try!(sock.bind(addr));
    let mut msg = try!(Message::new());
    loop {
        if let Ok(_) = sock.recv(&mut msg, 0) {
            try!(sock.send_str(msg.as_str().unwrap(), 0));
        }
    }
    Ok(())
}

fn main() {
    println!("24 days of Rust - zmq (day 20)");
    let args = std::env::args().collect::<Vec<_>>();
    if args.len() < 2 {
        println!("Usage: {} (client|server)", args[0]);
        return;
    }
    let mut ctx = Context::new();
    let addr = "tcp://127.0.0.1:25933";
    if args[1] == "client" {
        println!("ZeroMQ client connecting to {}", addr);
        run_client(&mut ctx, addr).unwrap_or_else(|err| println!("{:?}", err));
    }
    else {
        println!("ZeroMQ server listening on {}", addr);
        run_server(&mut ctx, addr).unwrap_or_else(|err| println!("{:?}", err));
    }
}
<|endoftext|>


<commit_before>fn main() {
    assert_eq!(my_list(&vec![1, 2, 3]), List::Cons(1, Some(Box::new(List::Cons(2, Some(Box::new(List::Cons(3, Some(Box::new(List::Nil))))))))));
}

#[derive(Debug, PartialEq)]
enum List {
    Cons(i32, Option<Box<List>>),
    Nil,
}

fn my_list(xs: &[i32]) -> List {
    let mut list = List::Nil;
    for &x in xs.into_iter().rev() {
        let tail = Some(Box::new(list));
        list = List::Cons(x, tail);
    }
    list
}

<commit_msg>改善(になってるかな？)<commit_after>fn main() {
    assert_eq!(List::new(&vec![1, 2, 3]), List {
        elem: Elem::Cons(1, Some(Box::new(Elem::Cons(2, Some(Box::new(Elem::Cons(3, Some(Box::new(Elem::Nil)))))))))
    });
}

#[derive(Debug, PartialEq)]
struct List {
    elem: Elem,
}

impl List {
    fn new(xs: &[i32]) -> List {
        let mut elem = Elem::Nil;
        for &x in xs.into_iter().rev() {
            let tail = Some(Box::new(elem));
            elem = Elem::Cons(x, tail);
        }
        List {
            elem
        }
    }
}

#[derive(Debug, PartialEq)]
enum Elem {
    Cons(i32, Option<Box<Elem>>),
    Nil,
}

<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// limitations under the License.

mod lib;

use rusqlite::{Connection, Result};
use tagged_rusqlite::tagged_sql;

fn main() -> Result<()> {
    let conn = Connection::open_in_memory()?;

    tagged_sql!(
        CreateCustomers,
        r#"CREATE TABLE customers (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL
                  );"#
    );

    CreateCustomers::prepare(&conn).execute()?;

    tagged_sql!(
        CreateOrders,
        r#"CREATE TABLE orders (
                  id              INTEGER PRIMARY KEY,
                  item            TEXT NOT NULL,
                  customerid      INTEGER NOT NULL,
                  price           REAL NOT NULL,
                  discount_code   TEXT
                  );"#
    );

    CreateOrders::prepare(&conn).execute()?;

    tagged_sql!(
        InsertCustomer,
        r#"INSERT INTO  customers (name)
                VALUES (
                    ? /*:name:String*/
                );
                "#
    );

    InsertCustomer::prepare(&conn)
        .execute_bind(&InsertCustomerParams {
            name: "John".to_string(),
        })?;

    tagged_sql!(
        InsertOrder,
        r#"
        INSERT into orders(item, customerid, price, discount_code)
        VALUES(
                ? /*:item:String*/,
                ? /*:customerid:i64*/,
                ? /*:price:f64*/,
                ? /*:discount_code:Option<String>*/
        )
        "#
    );

    tagged_sql!(
        FindCustomer,
        r#"
        SELECT id /*:i64*/ from customers
        where name = ? /*:name:String*/
        "#
    );

    let customerid: i64 = FindCustomer::prepare(&conn)
        .query_row_bind(&FindCustomerParams {
            name: "John".into(),
        })?
        .id;

    let mut insert_order = InsertOrder::prepare(&conn);
    insert_order.execute_bind(&InsertOrderParams {
        item: "Phone".into(),
        price: 1444.44,
        customerid,
        discount_code: None,
    })?;
    insert_order.execute_bind(&InsertOrderParams {
        item: "Laptop".into(),
        price: 1300.44,
        customerid,
        discount_code: None,
    })?;
    insert_order.execute_bind(&InsertOrderParams {
        item: "Laptop".into(),
        price: 2000.0,
        customerid,
        discount_code: Some("BIGSALE".to_owned()),
    })?;

    tagged_sql!(
        FindOrders,
        r#"
        SELECT
            orders.id as oid /*:i64*/,
            name /*:String*/,
            item /*:String*/,
            price /*:f64*/,
            discount_code /*:Option<String>*/
            FROM orders JOIN customers on customers.id = customerid
            WHERE price > ?/*:min_price:f64*/
        "#
    );

    let mut find_orders = FindOrders::prepare(&conn);
    for orders in find_orders.query_bind(&FindOrdersParams { min_price: 100.0 })? {
        println!("{:?}", &orders);
    }
    Ok(())
}
<commit_msg>More explicit output for tagged sqlite example<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// limitations under the License.

mod lib;

use rusqlite::{Connection, Result};
use tagged_rusqlite::tagged_sql;

fn main() -> Result<()> {
    let conn = Connection::open_in_memory()?;

    tagged_sql!(
        CreateCustomers,
        r#"CREATE TABLE customers (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL
                  );"#
    );

    CreateCustomers::prepare(&conn).execute()?;

    tagged_sql!(
        CreateOrders,
        r#"CREATE TABLE orders (
                  id              INTEGER PRIMARY KEY,
                  item            TEXT NOT NULL,
                  customerid      INTEGER NOT NULL,
                  price           REAL NOT NULL,
                  discount_code   TEXT
                  );"#
    );

    CreateOrders::prepare(&conn).execute()?;

    tagged_sql!(
        InsertCustomer,
        r#"INSERT INTO  customers (name)
                VALUES (
                    ? /*:name:String*/
                );
                "#
    );

    InsertCustomer::prepare(&conn).execute_bind(&InsertCustomerParams {
        name: "John".to_string(),
    })?;

    tagged_sql!(
        InsertOrder,
        r#"
        INSERT into orders(item, customerid, price, discount_code)
        VALUES(
                ? /*:item:String*/,
                ? /*:customerid:i64*/,
                ? /*:price:f64*/,
                ? /*:discount_code:Option<String>*/
        )
        "#
    );

    tagged_sql!(
        FindCustomer,
        r#"
        SELECT id /*:i64*/ from customers
        where name = ? /*:name:String*/
        "#
    );

    let customerid: i64 = FindCustomer::prepare(&conn)
        .query_row_bind(&FindCustomerParams {
            name: "John".into(),
        })?
        .id;

    let mut insert_order = InsertOrder::prepare(&conn);
    insert_order.execute_bind(&InsertOrderParams {
        item: "Phone".into(),
        price: 1444.44,
        customerid,
        discount_code: None,
    })?;
    insert_order.execute_bind(&InsertOrderParams {
        item: "Laptop".into(),
        price: 1300.44,
        customerid,
        discount_code: None,
    })?;
    insert_order.execute_bind(&InsertOrderParams {
        item: "Laptop".into(),
        price: 2000.0,
        customerid,
        discount_code: Some("BIGSALE".to_owned()),
    })?;

    tagged_sql!(
        FindOrders,
        r#"
        SELECT
            orders.id as oid /*:i64*/,
            name /*:String*/,
            item /*:String*/,
            price /*:f64*/,
            discount_code /*:Option<String>*/
            FROM orders JOIN customers on customers.id = customerid
            WHERE price > ?/*:min_price:f64*/
        "#
    );

    let mut find_orders = FindOrders::prepare(&conn);
    for orders in find_orders.query_bind(&FindOrdersParams { min_price: 100.0 })? {
        let orders = orders?;
        println!(
            "{} {} {} {} {:?}",
            &orders.oid, &orders.name, &orders.item, &orders.price, &orders.discount_code
        );
    }
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
use std::error::Error;
use super::{
    Dimension,
};

/// An error related to array shape or layout.
#[derive(Clone)]
pub struct ShapeError {
    // we want to be able to change this representation later
    repr: ErrorKind,
}

impl ShapeError {
    /// Return the `ErrorKind` of this error.
    #[inline]
    pub fn kind(&self) -> ErrorKind {
        self.repr
    }

    /// Create a new `ShapeError`
    pub fn from_kind(error: ErrorKind) -> Self {
        from_kind(error)
    }
}

/// Error code for an error related to array shape or layout.
///
/// This enumeration is not exhaustive. The representation of the enum
/// is not guaranteed.
#[derive(Copy, Clone, Debug)]
pub enum ErrorKind {
    /// incompatible shape
    IncompatibleShape,
    /// incompatible memory layout
    IncompatibleLayout,
    /// the shape does not fit inside type limits
    RangeLimited,
    /// out of bounds indexing
    OutOfBounds,
    /// aliasing array elements
    Unsupported,
    #[doc(hidden)]
    __Incomplete,
}

#[inline(always)]
pub fn from_kind(k: ErrorKind) -> ShapeError {
    ShapeError {
        repr: k
    }
}

impl PartialEq for ErrorKind {
    #[inline(always)]
    fn eq(&self, rhs: &Self) -> bool {
        *self as u8 == *rhs as u8
    }
}

impl PartialEq for ShapeError {
    #[inline(always)]
    fn eq(&self, rhs: &Self) -> bool {
        self.repr == rhs.repr
    }
}

impl Error for ShapeError {
    fn description(&self) -> &str {
        match self.kind() {
            ErrorKind::IncompatibleShape => "incompatible shapes",
            ErrorKind::IncompatibleLayout => "incompatible memory layout",
            ErrorKind::RangeLimited => "the shape does not fit in type limits",
            ErrorKind::OutOfBounds => "out of bounds indexing",
            ErrorKind::Unsupported => "unsupported operation",
            ErrorKind::__Incomplete => "this error variant is not in use",
        }
    }
}

impl fmt::Display for ShapeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ShapeError/{:?}: {}", self.kind(), self.description())
    }
}

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

pub fn incompatible_shapes<D, E>(_a: &D, _b: &E) -> ShapeError
    where D: Dimension,
          E: Dimension
{
    from_kind(ErrorKind::IncompatibleShape)
}
<commit_msg>Use non-zero discriminants for ErrorKind<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
use std::error::Error;
use super::{
    Dimension,
};

/// An error related to array shape or layout.
#[derive(Clone)]
pub struct ShapeError {
    // we want to be able to change this representation later
    repr: ErrorKind,
}

impl ShapeError {
    /// Return the `ErrorKind` of this error.
    #[inline]
    pub fn kind(&self) -> ErrorKind {
        self.repr
    }

    /// Create a new `ShapeError`
    pub fn from_kind(error: ErrorKind) -> Self {
        from_kind(error)
    }
}

/// Error code for an error related to array shape or layout.
///
/// This enumeration is not exhaustive. The representation of the enum
/// is not guaranteed.
#[derive(Copy, Clone, Debug)]
pub enum ErrorKind {
    /// incompatible shape
    IncompatibleShape = 1,
    /// incompatible memory layout
    IncompatibleLayout,
    /// the shape does not fit inside type limits
    RangeLimited,
    /// out of bounds indexing
    OutOfBounds,
    /// aliasing array elements
    Unsupported,
    #[doc(hidden)]
    __Incomplete,
}

#[inline(always)]
pub fn from_kind(k: ErrorKind) -> ShapeError {
    ShapeError {
        repr: k
    }
}

impl PartialEq for ErrorKind {
    #[inline(always)]
    fn eq(&self, rhs: &Self) -> bool {
        *self as u8 == *rhs as u8
    }
}

impl PartialEq for ShapeError {
    #[inline(always)]
    fn eq(&self, rhs: &Self) -> bool {
        self.repr == rhs.repr
    }
}

impl Error for ShapeError {
    fn description(&self) -> &str {
        match self.kind() {
            ErrorKind::IncompatibleShape => "incompatible shapes",
            ErrorKind::IncompatibleLayout => "incompatible memory layout",
            ErrorKind::RangeLimited => "the shape does not fit in type limits",
            ErrorKind::OutOfBounds => "out of bounds indexing",
            ErrorKind::Unsupported => "unsupported operation",
            ErrorKind::__Incomplete => "this error variant is not in use",
        }
    }
}

impl fmt::Display for ShapeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ShapeError/{:?}: {}", self.kind(), self.description())
    }
}

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

pub fn incompatible_shapes<D, E>(_a: &D, _b: &E) -> ShapeError
    where D: Dimension,
          E: Dimension
{
    from_kind(ErrorKind::IncompatibleShape)
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Result as FmtResult};
use iron::prelude::*;
use iron::status::Status;
use iron::headers::{ContentType};
use iron::modifiers::Header;
use iron::mime::Mime;
use serde_json;
use serde::Serialize;
use serde::Serializer;
use std::str::FromStr;
use std::error;
use postgres;
use urlencoded;
use hyper;

#[derive(Debug)]
pub enum Error {
    BadRequest,
    Unprocessable,
    NotFound,
    DbError(postgres::error::Error),
    DbConnectError(postgres::error::ConnectError),
    Unexpected,
}

impl Serialize for Error {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        match *self {
            Error::BadRequest        => serializer.serialize_str("BadRequest"),
            Error::Unprocessable     => serializer.serialize_str("Unprocessable"),
            Error::NotFound          => serializer.serialize_str("NotFound"),
            Error::DbError(_)        => serializer.serialize_str("DbError"),
            Error::DbConnectError(_) => serializer.serialize_str("DbConnectError"),
            Error::Unexpected        => serializer.serialize_str("Unexpected"),
        }
    }
}

impl Error {
    pub fn status(&self) -> Status {
        match *self {
            Error::BadRequest        => Status::BadRequest,
            Error::Unprocessable     => Status::UnprocessableEntity,
            Error::NotFound          => Status::NotFound,
            Error::DbError(_)        => Status::InternalServerError,
            Error::DbConnectError(_) => Status::InternalServerError,
            Error::Unexpected        => Status::InternalServerError,
        }
    }

    pub fn as_response(&self) -> Response {
        let json_type = Header(ContentType(Mime::from_str("application/json").ok().unwrap()));
        Response::with((self.status(), json_type, serde_json::to_string(self).unwrap()))
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            Error::BadRequest            => write!(f, "BadRequest"),
            Error::Unprocessable         => write!(f, "Unproccesable"),
            Error::NotFound              => write!(f, "NotFound"),
            Error::DbError(ref e)        => write!(f, "UnexpectedError: DBError {}", e),
            Error::DbConnectError(ref e) => write!(f, "UnexpectedError: DBConnectError {}", e),
            Error::Unexpected            => write!(f, "UnexpectedError"),
        }
    }
}

impl From<postgres::error::Error> for Error {
    fn from(err: postgres::error::Error) -> Error {
        Error::DbError(err)
    }
}

impl From<postgres::error::ConnectError> for Error {
    fn from(err: postgres::error::ConnectError) -> Error {
        Error::DbConnectError(err)
    }
}

impl From<urlencoded::UrlDecodingError> for Error {
    fn from(_: urlencoded::UrlDecodingError) -> Error {
        Error::BadRequest
    }
}

impl From<hyper::Error> for Error {
    fn from(_: hyper::Error) -> Error {
        Error::BadRequest
    }
}

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

impl From<Error> for IronError {
    fn from(err: Error) -> IronError {
        match err {
            Error::BadRequest        => IronError::new(err, Status::BadRequest),
            Error::Unprocessable     => IronError::new(err, Status::BadRequest),
            Error::NotFound          => IronError::new(err, Status::NotFound),
            Error::DbError(_)        => IronError::new(err, Status::BadRequest),
            Error::DbConnectError(_) => IronError::new(err, Status::BadRequest),
            Error::Unexpected        => IronError::new(err, Status::BadRequest),
        }
    }
}

impl From<serde_json::Error> for Error {
    fn from(_: serde_json::Error) -> Error {
        Error::Unexpected
    }
}
<commit_msg>Add Error::UrlParseError<commit_after>use std::fmt::{Display, Formatter, Result as FmtResult};
use iron::prelude::*;
use iron::status::Status;
use iron::headers::{ContentType};
use iron::modifiers::Header;
use iron::mime::Mime;
use serde_json;
use serde::Serialize;
use serde::Serializer;
use std::str::FromStr;
use std::error;
use postgres;
use urlencoded;
use hyper;
use url;

#[derive(Debug)]
pub enum Error {
    BadRequest,
    Unprocessable,
    NotFound,
    DbError(postgres::error::Error),
    DbConnectError(postgres::error::ConnectError),
    UrlParseError(url::ParseError),
    Unexpected,
}

impl Serialize for Error {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        match *self {
            Error::BadRequest        => serializer.serialize_str("BadRequest"),
            Error::Unprocessable     => serializer.serialize_str("Unprocessable"),
            Error::NotFound          => serializer.serialize_str("NotFound"),
            Error::DbError(_)        => serializer.serialize_str("DbError"),
            Error::DbConnectError(_) => serializer.serialize_str("DbConnectError"),
            Error::UrlParseError(_)  => serializer.serialize_str("UrlParseError"),
            Error::Unexpected        => serializer.serialize_str("Unexpected"),
        }
    }
}

impl Error {
    pub fn status(&self) -> Status {
        match *self {
            Error::BadRequest        => Status::BadRequest,
            Error::Unprocessable     => Status::UnprocessableEntity,
            Error::NotFound          => Status::NotFound,
            Error::DbError(_)        => Status::InternalServerError,
            Error::DbConnectError(_) => Status::InternalServerError,
            Error::UrlParseError(_)  => Status::InternalServerError,
            Error::Unexpected        => Status::InternalServerError,
        }
    }

    pub fn as_response(&self) -> Response {
        let json_type = Header(ContentType(Mime::from_str("application/json").ok().unwrap()));
        Response::with((self.status(), json_type, serde_json::to_string(self).unwrap()))
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            Error::BadRequest            => write!(f, "BadRequest"),
            Error::Unprocessable         => write!(f, "Unproccesable"),
            Error::NotFound              => write!(f, "NotFound"),
            Error::DbError(ref e)        => write!(f, "DBError {}", e),
            Error::DbConnectError(ref e) => write!(f, "DBConnectError {}", e),
            Error::UrlParseError(ref e)  => write!(f, "UrlParseError:  {}", e),
            Error::Unexpected            => write!(f, "UnexpectedError"),
        }
    }
}

impl From<url::ParseError> for Error {
    fn from(err: url::ParseError) -> Error {
        Error::UrlParseError(err)
    }
}

impl From<postgres::error::Error> for Error {
    fn from(err: postgres::error::Error) -> Error {
        Error::DbError(err)
    }
}

impl From<postgres::error::ConnectError> for Error {
    fn from(err: postgres::error::ConnectError) -> Error {
        Error::DbConnectError(err)
    }
}

impl From<urlencoded::UrlDecodingError> for Error {
    fn from(_: urlencoded::UrlDecodingError) -> Error {
        Error::BadRequest
    }
}

impl From<hyper::Error> for Error {
    fn from(_: hyper::Error) -> Error {
        Error::BadRequest
    }
}

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

impl From<Error> for IronError {
    fn from(err: Error) -> IronError {
        match err {
            Error::BadRequest        => IronError::new(err, Status::BadRequest),
            Error::Unprocessable     => IronError::new(err, Status::BadRequest),
            Error::NotFound          => IronError::new(err, Status::NotFound),
            Error::DbError(_)        => IronError::new(err, Status::InternalServerError),
            Error::DbConnectError(_) => IronError::new(err, Status::InternalServerError),
            Error::UrlParseError(_)  => IronError::new(err, Status::InternalServerError),
            Error::Unexpected        => IronError::new(err, Status::InternalServerError),
        }
    }
}

impl From<serde_json::Error> for Error {
    fn from(_: serde_json::Error) -> Error {
        Error::Unexpected
    }
}
<|endoftext|>


<commit_before>use rand;
use rand::Rng;
use std::collections::VecDeque;
use piston_window::*;

pub enum Content {
    Number(u8),
    Bomb,
    None
}

struct Cell {
    index: u32,
    content: Content,
    revealed: bool
}

impl Cell {
    pub fn clear(&mut self) {
        self.content = Content::None;
        self.revealed = false;
    }

    fn reveal(&mut self) {
        self.revealed = true;
    }
}

pub struct Field {
    cells: Vec<Cell>,
    width: u32,
    height: u32,
    mines: u32,
    size: u32
}

impl Field {
    pub fn new(width: u32, height: u32, mines: u32) -> Field {
        let mut field = Field {
            width: width,
            height: height,
            cells: vec![],
            mines: mines,
            size: width*height
        };
        for i in 0..field.size {
            field.cells.push(Cell{index: i,
                           content: Content::None,
                           revealed: false});
        }
        field.fill();
        field
    }

    fn fill(&mut self) {
        self.clear();
        for _i in 0..self.mines {
            let ind = rand::thread_rng().gen_range(0, self.size);
            self.get_cell_mut(ind).content = Content::Bomb
        }
        let mut i: i32 = -1;
        let w = self.width as i32;
        while i < (self.size - 1) as i32 {
            i += 1;
            match self.get_content_safe(i) {
                Some(&Content::None) => {
                    let ct_bomb = |b| {
                        match b {
                            true => 1,
                            false => 0
                        }
                    };
                     // don`t care about row
                    let mut ct = ct_bomb(self.is_bomb_safe(i-w)) +
                                 ct_bomb(self.is_bomb_safe(i+w));
                    if i % w > 0 { // check left side position
                        ct += ct_bomb(self.is_bomb_safe(i-w-1)) +
                              ct_bomb(self.is_bomb_safe(i-1)) +
                              ct_bomb(self.is_bomb_safe(i+w-1));
                    }
                    if i % w < w - 1 { // check right side position
                        ct += ct_bomb(self.is_bomb_safe(i-w+1)) +
                              ct_bomb(self.is_bomb_safe(i+1)) +
                              ct_bomb(self.is_bomb_safe(i+w+1));
                    }
                    if ct > 0 {
                        self.get_cell_mut(i as u32).content = Content::Number(ct);
                    }
                },
                _ => {}
            }
        }
    }

    fn clear(&mut self) {
        for i in 0..self.size {
            self.get_cell_mut(i).clear();
        }
    }

    pub fn reveal(&mut self, i: u32) -> &Content {
        let cell = self.get_cell_mut(i);
        cell.reveal();
        &cell.content
    }

    pub fn revealed(&self, i: u32) -> bool {
        self.get_cell(i).revealed
    }

    fn get_cell_mut(&mut self, i:u32) -> &mut Cell {
        self.cells.get_mut(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell_mut ({})", i))
    }

    fn get_cell(& self, i:u32) -> &Cell {
        self.cells.get(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell ({})", i))
    }

    fn get_content_safe(&self, i:i32) -> Option<&Content> {
        if (i < 0) || ((i as u32) >= self.size) {
            None
        } else {
            Some(self.get_content(i as u32))
        }
    }

    pub fn get_content(& self, i: u32) -> &Content {
        &self.get_cell(i).content
    }

    fn is_bomb_safe(&self, i: i32) -> bool {
        match self.get_content_safe(i) {
            Some(&Content::Bomb) => true,
            _ => false
        }
    }

    pub fn get_width(&self) -> u32 {
        self.width
    }

    pub fn get_height(&self) -> u32 {
        self.height
    }

    pub fn restart(&mut self) {
        self.fill();
    }

    pub fn reveal_all(&mut self) {
      for i in 0..self.size {
            self.get_cell_mut(i).revealed = true;
        }
    }

    pub fn chain_reveal(&mut self, u: u32) {
        let w = self.width as i32;
        // clojure to check for blank cells
        let mut check = |x, d: &mut VecDeque<i32>| {
            match self.get_content_safe(x) {
                Some(&Content::None) => {
                    if !self.revealed(x as u32) {
                        d.push_back(x);
                    }
                    self.reveal(x as u32);
                },
                Some(&Content::Number(_n)) => {
                    self.reveal(x as u32);
                },
                _ => {}
            }
        };
        // BFS initialize
        let deq = &mut VecDeque::new();
        deq.push_back(u as i32);
        // BFS
        while !deq.is_empty() {
            let i = deq.pop_front().unwrap();
            // don`t care about row
            check(i-w, deq);
            check(i+w, deq);
            if i % w > 0 { // check left side position
                check(i-w-1, deq);
                check(i-1, deq);
                check(i+w-1, deq);
            }
            if i % w < w - 1 { // check right side position
                check(i-w+1, deq);
                check(i+1, deq);
                check(i+w+1, deq);
            }
        }
    }

    pub fn draw(&mut self,
            context: Context,
            graphics: &mut G2d,
            field_rect: [u32; 4],
            glyps: &mut Glyphs)
    {
        let cell_w = field_rect[2] / self.get_width();
        let cell_h = field_rect[3] / self.get_height();
        for i in 0..self.get_width() {
            for j in 0..self.get_height() {
                if !self.revealed(i + j*self.get_width()) {
                    continue;
                }
                match *self.get_content(i + j*self.get_width()) {
                    Content::Bomb => {
                        rectangle([1.0, 0.0, 0.0, 1.0],
                                  [
                                    (field_rect[0] + i*cell_w) as f64,
                                    (field_rect[1] + j*cell_h) as f64,
                                    cell_w as f64,
                                    cell_h as f64
                                  ],
                                  context.transform,
                                  graphics);

                    },
                    Content::Number(n) => {
                        let transform = context.transform.trans(10.0 + (field_rect[0] + i*cell_w) as f64,
                                                                (field_rect[1] + (j+1)*cell_h) as f64 - 5.0);
                        text::Text::colored([1.0, 1.0, 1.0, 1.0], 32).draw(
                            &*n.to_string(),
                            glyps,
                            &context.draw_state,
                            transform,
                            graphics
                        );
                    },
                    Content::None => {
                        rectangle([1.0, 1.0, 1.0, 1.0],
                                  [
                                    (field_rect[0] + i*cell_w) as f64,
                                    (field_rect[1] + j*cell_h) as f64,
                                    cell_w as f64,
                                    cell_h as f64
                                  ],
                                  context.transform,
                                  graphics);
                    }
                }
            }
        }
        for i in 0..self.get_width()+1 {
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        (field_rect[0] + i*cell_w) as f64,
                        field_rect[1] as f64,
                        (field_rect[0] + i*cell_w) as f64,
                        (field_rect[1] + field_rect[3]) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        field_rect[0] as f64,
                        (field_rect[1] + i*cell_h) as f64,
                        (field_rect[0] + field_rect[2]) as f64,
                        (field_rect[1] + i*cell_h) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
        }
    }
}<commit_msg>chore: some magic<commit_after>use rand;
use rand::Rng;
use std::collections::VecDeque;
use piston_window::*;

pub enum Content {
    Number(u8),
    Bomb,
    None
}

struct Cell {
    index: u32,
    content: Content,
    revealed: bool
}

impl Cell {
    pub fn clear(&mut self) {
        self.content = Content::None;
        self.revealed = false;
    }

    fn reveal(&mut self) {
        self.revealed = true;
    }
}

pub struct Field {
    cells: Vec<Cell>,
    width: u32,
    height: u32,
    mines: u32,
    size: u32
}

impl Field {
    pub fn new(width: u32, height: u32, mines: u32) -> Field {
        let mut field = Field {
            width: width,
            height: height,
            cells: vec![],
            mines: mines,
            size: width*height
        };
        for i in 0..field.size {
            field.cells.push(Cell{index: i,
                           content: Content::None,
                           revealed: false});
        }
        field.fill();
        field
    }

    fn fill(&mut self) {
        self.clear();
        for _i in 0..self.mines {
            let ind = rand::thread_rng().gen_range(0, self.size);
            self.get_cell_mut(ind).content = Content::Bomb
        }
        let mut i: i32 = -1;
        let w = self.width as i32;
        while i < (self.size - 1) as i32 {
            i += 1;
            match self.get_content_safe(i) {
                Some(&Content::None) => {
                    let ct_bomb = |b| {
                        match b {
                            true => 1,
                            false => 0
                        }
                    };
                     // don`t care about row
                    let mut ct = ct_bomb(self.is_bomb_safe(i-w)) +
                                 ct_bomb(self.is_bomb_safe(i+w));
                    if i % w > 0 { // check left side position
                        ct += ct_bomb(self.is_bomb_safe(i-w-1)) +
                              ct_bomb(self.is_bomb_safe(i-1)) +
                              ct_bomb(self.is_bomb_safe(i+w-1));
                    }
                    if i % w < w - 1 { // check right side position
                        ct += ct_bomb(self.is_bomb_safe(i-w+1)) +
                              ct_bomb(self.is_bomb_safe(i+1)) +
                              ct_bomb(self.is_bomb_safe(i+w+1));
                    }
                    if ct > 0 {
                        self.get_cell_mut(i as u32).content = Content::Number(ct);
                    }
                },
                _ => {}
            }
        }
    }

    fn clear(&mut self) {
        for i in 0..self.size {
            self.get_cell_mut(i).clear();
        }
    }

    pub fn reveal(&mut self, i: u32) -> &Content {
        let cell = self.get_cell_mut(i);
        cell.reveal();
        &cell.content
    }

    pub fn revealed(&self, i: u32) -> bool {
        self.get_cell(i).revealed
    }

    fn get_cell_mut(&mut self, i:u32) -> &mut Cell {
        self.cells.get_mut(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell_mut ({})", i))
    }

    fn get_cell(& self, i:u32) -> &Cell {
        self.cells.get(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell ({})", i))
    }

    fn get_content_safe(&self, i:i32) -> Option<&Content> {
        if (i < 0) || ((i as u32) >= self.size) {
            None
        } else {
            Some(self.get_content(i as u32))
        }
    }

    pub fn get_content(& self, i: u32) -> &Content {
        &self.get_cell(i).content
    }

    fn is_bomb_safe(&self, i: i32) -> bool {
        match self.get_content_safe(i) {
            Some(&Content::Bomb) => true,
            _ => false
        }
    }

    pub fn get_width(&self) -> u32 {
        self.width
    }

    pub fn get_height(&self) -> u32 {
        self.height
    }

    pub fn restart(&mut self) {
        self.fill();
    }

    pub fn reveal_all(&mut self) {
      for i in 0..self.size {
            self.get_cell_mut(i).revealed = true;
        }
    }

    pub fn chain_reveal(&mut self, u: u32) {
        let w = self.width as i32;
        // clojure to check for blank cells
        let mut check = |x, d: &mut VecDeque<i32>| {
            match self.get_content_safe(x) {
                Some(&Content::None) => {
                    if !self.revealed(x as u32) {
                        d.push_back(x);
                    }
                    self.reveal(x as u32);
                },
                Some(&Content::Number(_n)) => {
                    self.reveal(x as u32);
                },
                _ => {}
            }
        };
        // BFS initialize
        let deq = &mut VecDeque::new();
        deq.push_back(u as i32);
        // BFS
        while !deq.is_empty() {
            let i = deq.pop_front().unwrap();
            // don`t care about row
            check(i-w, deq);
            check(i+w, deq);
            if i % w > 0 { // check left side position
                check(i-w-1, deq);
                check(i-1, deq);
                check(i+w-1, deq);
            }
            if i % w < w - 1 { // check right side position
                check(i-w+1, deq);
                check(i+1, deq);
                check(i+w+1, deq);
            }
        }
    }

    pub fn draw(&mut self,
            context: Context,
            graphics: &mut G2d,
            field_rect: [u32; 4],
            glyps: &mut Glyphs)
    {
        let cell_w = field_rect[2] / self.get_width();
        let cell_h = field_rect[3] / self.get_height();
        for i in 0..self.get_width() {
            for j in 0..self.get_height() {
                if !self.revealed(i + j*self.get_width()) {
                    continue;
                }
                match *self.get_content(i + j*self.get_width()) {
                    Content::Bomb => {
                        rectangle([1.0, 0.0, 0.0, 1.0],
                                  [
                                    (field_rect[0] + i*cell_w) as f64,
                                    (field_rect[1] + j*cell_h) as f64,
                                    cell_w as f64,
                                    cell_h as f64
                                  ],
                                  context.transform,
                                  graphics);

                    },
                    Content::Number(n) => {
                        let transform = context.transform.trans((field_rect[0] + i*cell_w) as f64 + 5.0,
                                                                (field_rect[1] + (j+1)*cell_h) as f64 - 5.0);
                        text::Text::colored([1.0, 1.0, 1.0, 1.0], cell_h).draw(
                            &*n.to_string(),
                            glyps,
                            &context.draw_state,
                            transform,
                            graphics
                        );
                    },
                    Content::None => {
                        rectangle([1.0, 1.0, 1.0, 1.0],
                                  [
                                    (field_rect[0] + i*cell_w) as f64,
                                    (field_rect[1] + j*cell_h) as f64,
                                    cell_w as f64,
                                    cell_h as f64
                                  ],
                                  context.transform,
                                  graphics);
                    }
                }
            }
        }
        for i in 0..self.get_width()+1 {
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        (field_rect[0] + i*cell_w) as f64,
                        field_rect[1] as f64,
                        (field_rect[0] + i*cell_w) as f64,
                        (field_rect[1] + field_rect[3]) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        field_rect[0] as f64,
                        (field_rect[1] + i*cell_h) as f64,
                        (field_rect[0] + field_rect[2]) as f64,
                        (field_rect[1] + i*cell_h) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
        }
    }
}<|endoftext|>


<commit_before>#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
#[cfg(feature = "parsing")]
use crate::lookahead;
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseStream, Result};
#[cfg(feature = "parsing")]
use crate::token::Token;
use unicode_xid::UnicodeXID;

pub use proc_macro2::Ident;

#[cfg(feature = "parsing")]
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn Ident(marker: lookahead::TokenMarker) -> Ident {
    match marker {}
}

#[cfg(feature = "parsing")]
fn accept_as_ident(ident: &Ident) -> bool {
    match ident.to_string().as_str() {
        "_" |
        // Based on https://doc.rust-lang.org/grammar.html#keywords
        // and https://github.com/rust-lang/rfcs/blob/master/text/2421-unreservations-2018.md
        // and https://github.com/rust-lang/rfcs/blob/master/text/2420-unreserve-proc.md
        "abstract" | "as" | "become" | "box" | "break" | "const" | "continue" |
        "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" |
        "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" |
        "mod" | "move" | "mut" | "override" | "priv" | "pub" | "ref" |
        "return" | "Self" | "self" | "static" | "struct" | "super" | "trait" |
        "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" |
        "where" | "while" | "yield" => false,
        _ => true,
    }
}

#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Ident {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step(|cursor| {
            if let Some((ident, rest)) = cursor.ident() {
                if accept_as_ident(&ident) {
                    return Ok((ident, rest));
                }
            }
            Err(cursor.error("expected identifier"))
        })
    }
}

#[cfg(feature = "parsing")]
impl Token for Ident {
    fn peek(cursor: Cursor) -> bool {
        if let Some((ident, _rest)) = cursor.ident() {
            accept_as_ident(&ident)
        } else {
            false
        }
    }

    fn display() -> &'static str {
        "identifier"
    }
}

macro_rules! ident_from_token {
    ($token:ident) => {
        impl From<Token![$token]> for Ident {
            fn from(token: Token![$token]) -> Ident {
                Ident::new(stringify!($token), token.span)
            }
        }
    };
}

ident_from_token!(self);
ident_from_token!(Self);
ident_from_token!(super);
ident_from_token!(crate);
ident_from_token!(extern);

impl From<Token![_]> for Ident {
    fn from(token: Token![_]) -> Ident {
        Ident::new("_", token.span)
    }
}

pub fn xid_ok(symbol: &str) -> bool {
    let mut chars = symbol.chars();
    let first = chars.next().unwrap();
    if !(UnicodeXID::is_xid_start(first) || first == '_') {
        return false;
    }
    for ch in chars {
        if !UnicodeXID::is_xid_continue(ch) {
            return false;
        }
    }
    true
}
<commit_msg>Avoid loading XID_Start table on ASCII-only input<commit_after>#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
#[cfg(feature = "parsing")]
use crate::lookahead;
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseStream, Result};
#[cfg(feature = "parsing")]
use crate::token::Token;
use unicode_xid::UnicodeXID;

pub use proc_macro2::Ident;

#[cfg(feature = "parsing")]
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn Ident(marker: lookahead::TokenMarker) -> Ident {
    match marker {}
}

#[cfg(feature = "parsing")]
fn accept_as_ident(ident: &Ident) -> bool {
    match ident.to_string().as_str() {
        "_" |
        // Based on https://doc.rust-lang.org/grammar.html#keywords
        // and https://github.com/rust-lang/rfcs/blob/master/text/2421-unreservations-2018.md
        // and https://github.com/rust-lang/rfcs/blob/master/text/2420-unreserve-proc.md
        "abstract" | "as" | "become" | "box" | "break" | "const" | "continue" |
        "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" |
        "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" |
        "mod" | "move" | "mut" | "override" | "priv" | "pub" | "ref" |
        "return" | "Self" | "self" | "static" | "struct" | "super" | "trait" |
        "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" |
        "where" | "while" | "yield" => false,
        _ => true,
    }
}

#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Ident {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step(|cursor| {
            if let Some((ident, rest)) = cursor.ident() {
                if accept_as_ident(&ident) {
                    return Ok((ident, rest));
                }
            }
            Err(cursor.error("expected identifier"))
        })
    }
}

#[cfg(feature = "parsing")]
impl Token for Ident {
    fn peek(cursor: Cursor) -> bool {
        if let Some((ident, _rest)) = cursor.ident() {
            accept_as_ident(&ident)
        } else {
            false
        }
    }

    fn display() -> &'static str {
        "identifier"
    }
}

macro_rules! ident_from_token {
    ($token:ident) => {
        impl From<Token![$token]> for Ident {
            fn from(token: Token![$token]) -> Ident {
                Ident::new(stringify!($token), token.span)
            }
        }
    };
}

ident_from_token!(self);
ident_from_token!(Self);
ident_from_token!(super);
ident_from_token!(crate);
ident_from_token!(extern);

impl From<Token![_]> for Ident {
    fn from(token: Token![_]) -> Ident {
        Ident::new("_", token.span)
    }
}

pub fn xid_ok(symbol: &str) -> bool {
    let mut chars = symbol.chars();
    let first = chars.next().unwrap();
    if !(first == '_' || UnicodeXID::is_xid_start(first)) {
        return false;
    }
    for ch in chars {
        if !UnicodeXID::is_xid_continue(ch) {
            return false;
        }
    }
    true
}
<|endoftext|>