<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::vec::Vec;
use libc;
use capability::ClientHook;
use common::*;
use message;

pub use self::FirstSegment::{NumWords, ZeroedWords};

pub type SegmentId = u32;

#[derive(Copy)]
pub struct SegmentReader {
    pub arena : ArenaPtr,
    pub ptr : *const Word,
    pub size : WordCount32
}

unsafe impl Send for SegmentReader {}

impl SegmentReader {

    #[inline]
    pub unsafe fn get_start_ptr(&self) -> *const Word {
        self.ptr.offset(0)
    }

    #[inline]
    pub fn contains_interval(&self, from : *const Word, to : *const Word) -> bool {
        let this_begin : usize = self.ptr as usize;
        let this_end : usize = unsafe { self.ptr.offset(self.size as isize) as usize };
        return from as usize >= this_begin && to as usize <= this_end && from as usize <= to as usize;
        // TODO readLimiter
    }
}

#[derive(Copy)]
pub struct SegmentBuilder {
    pub reader : SegmentReader,
    pub id : SegmentId,
    pos : *mut Word,
}

unsafe impl Send for SegmentBuilder {}

impl SegmentBuilder {

    pub fn new(arena : *mut BuilderArena,
               id : SegmentId,
               ptr : *mut Word,
               size : WordCount32) -> SegmentBuilder {
        SegmentBuilder {
            reader : SegmentReader {
                arena : ArenaPtr::Builder(arena),
                ptr : unsafe {::std::mem::transmute(ptr)},
                size : size
            },
            id : id,
            pos : ptr,
        }
    }

    pub fn get_word_offset_to(&mut self, ptr : *mut Word) -> WordCount32 {
        let this_addr : usize = self.reader.ptr as usize;
        let ptr_addr : usize = ptr as usize;
        assert!(ptr_addr >= this_addr);
        let result = (ptr_addr - this_addr) / BYTES_PER_WORD;
        return result as u32;
    }

    #[inline]
    pub fn current_size(&self) -> WordCount32 {
        ptr_sub(self.pos, self.reader.ptr) as u32
    }

    #[inline]
    pub fn allocate(&mut self, amount : WordCount32) -> Option<*mut Word> {
        if amount > self.reader.size - self.current_size() {
            return None;
        } else {
            let result = self.pos;
            self.pos = unsafe { self.pos.offset(amount as isize) };
            return Some(result);
        }
    }

    #[inline]
    pub fn get_ptr_unchecked(&self, offset : WordCount32) -> *mut Word {
        unsafe {
            ::std::mem::transmute(self.reader.ptr.offset(offset as isize))
        }
    }

    #[inline]
    pub fn get_segment_id(&self) -> SegmentId { self.id }

    #[inline]
    pub fn get_arena(&self) -> *mut BuilderArena {
        match self.reader.arena {
            ArenaPtr::Builder(b) => b,
            _ => unreachable!()
        }
    }
}

pub struct ReaderArena {
    //    message : *message::MessageReader<'a>,
    pub segment0 : SegmentReader,

    pub more_segments : Vec<SegmentReader>,
    //XXX should this be a map as in capnproto-c++?

    pub cap_table : Vec<Option<Box<ClientHook+Send>>>,

    pub fail_fast : bool,
}

impl ReaderArena {
    pub fn new(segments : &[&[Word]], options : message::ReaderOptions) -> Box<ReaderArena> {
        assert!(segments.len() > 0);
        let mut arena = Box::new(ReaderArena {
            segment0 : SegmentReader {
                arena : ArenaPtr::Null,
                ptr : unsafe { segments[0].get_unchecked(0) },
                size : segments[0].len() as u32
            },
            more_segments : Vec::new(),
            cap_table : Vec::new(),
            fail_fast : options.fail_fast,
        });

        let arena_ptr = ArenaPtr::Reader (&*arena);

        arena.segment0.arena = arena_ptr;

        if segments.len() > 1 {
            let mut more_segment_readers = Vec::new();
            for segment in segments[1 ..].iter() {
                let segment_reader = SegmentReader {
                    arena : arena_ptr,
                    ptr : unsafe { segment.get_unchecked(0) },
                    size : segment.len() as u32
                };
                more_segment_readers.push(segment_reader);
            }
            arena.more_segments = more_segment_readers;
        }

        arena
    }

    pub fn try_get_segment(&self, id : SegmentId) -> *const SegmentReader {
        if id == 0 {
            return &self.segment0 as *const SegmentReader;
        } else {
            unsafe { self.more_segments.get_unchecked(id as usize - 1) as *const SegmentReader }
        }
    }

    #[inline]
    pub fn init_cap_table(&mut self, cap_table : Vec<Option<Box<ClientHook+Send>>>) {
        self.cap_table = cap_table;
    }

}

pub struct BuilderArena {
    pub segment0 : SegmentBuilder,
    pub more_segments : Vec<Box<SegmentBuilder>>,
    pub allocation_strategy : message::AllocationStrategy,
    pub owned_memory : Vec<*mut Word>,
    pub next_size : u32,
    pub cap_table : Vec<Option<Box<ClientHook+Send>>>,
    pub fail_fast : bool,
}

impl Drop for BuilderArena {
    fn drop(&mut self) {
        for &segment_ptr in self.owned_memory.iter() {
            unsafe { libc::free(::std::mem::transmute(segment_ptr)); }
        }
    }
}

pub enum FirstSegment<'a> {
    NumWords(u32),
    ZeroedWords(&'a mut [Word])
}

impl BuilderArena {

    pub fn new(allocation_strategy : message::AllocationStrategy,
               first_segment : FirstSegment,
               fail_fast : bool) -> Box<BuilderArena> {

        let (first_segment, num_words, owned_memory) : (*mut Word, u32, Vec<*mut Word>) = unsafe {
            match first_segment {
                NumWords(n) => {
                    let ptr = ::std::mem::transmute(
                        libc::calloc(n as libc::size_t,
                                          BYTES_PER_WORD as libc::size_t));
                    (ptr, n, vec!(ptr))
                }
                ZeroedWords(w) => (w.as_mut_ptr(), w.len() as u32, Vec::new())
            }};

        let mut result = Box::new(BuilderArena {
            segment0 : SegmentBuilder {
                reader : SegmentReader {
                    ptr : first_segment as *const Word,
                    size : num_words,
                    arena : ArenaPtr::Null },
                id : 0,
                pos : first_segment,
            },
            more_segments : Vec::new(),
            allocation_strategy : allocation_strategy,
            owned_memory : owned_memory,
            next_size : num_words,
            cap_table : Vec::new(),
            fail_fast : fail_fast,
        });

        let arena_ptr = { let ref mut ptr = *result; ptr as *mut BuilderArena};
        result.segment0.reader.arena = ArenaPtr::Builder(arena_ptr);

        result
    }

    pub fn allocate_owned_memory(&mut self, minimum_size : WordCount32) -> (*mut Word, WordCount32) {
        let size = ::std::cmp::max(minimum_size, self.next_size);
        let new_words : *mut Word = unsafe {
            ::std::mem::transmute(libc::calloc(size as libc::size_t,
                                                   BYTES_PER_WORD as libc::size_t)) };

        self.owned_memory.push(new_words);

        match self.allocation_strategy {
            message::AllocationStrategy::GrowHeuristically => { self.next_size += size; }
            _ => { }
        }
        (new_words, size)
    }

    #[inline]
    pub fn allocate(&mut self, amount : WordCount32) -> (*mut SegmentBuilder, *mut Word) {
        unsafe {
            match self.segment0.allocate(amount) {
                Some(result) => { return ((&mut self.segment0) as *mut SegmentBuilder, result) }
                None => {}
            }

            //# Need to fall back to additional segments.

            let id = {
                let len = self.more_segments.len();
                if len == 0 { 1 }
                else {
                    let result_ptr = &mut *self.more_segments.as_mut_slice()[len-1] as *mut SegmentBuilder;
                    match self.more_segments.as_mut_slice()[len - 1].allocate(amount) {
                        Some(result) => { return (result_ptr, result) }
                        None => { len + 1 }
                    }
                }};

            let (words, size) = self.allocate_owned_memory(amount);
            let mut new_builder = Box::new(SegmentBuilder::new(self, id as u32, words, size));
            let builder_ptr = &mut *new_builder as *mut SegmentBuilder;

            self.more_segments.push(new_builder);

            (builder_ptr, (*builder_ptr).allocate(amount).unwrap() )
        }
    }

    pub fn get_segment(&mut self, id : SegmentId) -> *mut SegmentBuilder {
        if id == 0 {
            &mut self.segment0 as *mut SegmentBuilder
        } else {
            &mut *self.more_segments.as_mut_slice()[(id - 1) as usize] as *mut SegmentBuilder
        }
    }

    pub fn get_segments_for_output<T, U : FnMut(&[&[Word]]) -> T>(&self, mut cont : U) -> T {
        unsafe {
            if self.more_segments.len() == 0 {
                let v = ::std::slice::from_raw_parts::<Word>(
                    self.segment0.reader.ptr,
                    self.segment0.current_size() as usize);
                cont(&[v])
            } else {
                let mut result = Vec::new();
                result.push(::std::slice::from_raw_parts(self.segment0.reader.ptr,
                                                         self.segment0.current_size() as usize));
                for seg in self.more_segments.iter() {
                    result.push(::std::slice::from_raw_parts(seg.reader.ptr,
                                                             seg.current_size() as usize))
                }
                cont(result.as_slice())
            }
        }
    }

    pub fn get_cap_table<'a>(&'a self) -> &'a [Option<Box<ClientHook+Send>>] {
        self.cap_table.as_slice()
    }

    pub fn inject_cap(&mut self, cap : Box<ClientHook+Send>) -> u32 {
        self.cap_table.push(Some(cap));
        self.cap_table.len() as u32 - 1
    }
}

#[derive(Copy)]
pub enum ArenaPtr {
    Reader(*const ReaderArena),
    Builder(*mut BuilderArena),
    Null
}

impl ArenaPtr {
    pub fn try_get_segment(&self, id : SegmentId) -> *const SegmentReader {
        unsafe {
            match self {
                &ArenaPtr::Reader(reader) => {
                    (&*reader).try_get_segment(id)
                }
                &ArenaPtr::Builder(builder) => {
                    if id == 0 {
                        &(*builder).segment0.reader as *const SegmentReader
                    } else {
                        &(*builder).more_segments.as_slice()[id as usize - 1].reader as *const SegmentReader
                    }
                }
                &ArenaPtr::Null => {
                    panic!()
                }
            }
        }
    }

    pub fn extract_cap(&self, index : usize) -> Option<Box<ClientHook+Send>> {
        unsafe {
            match self {
                &ArenaPtr::Reader(reader) => {
                    if index < (*reader).cap_table.len() {
                        match (*reader).cap_table.as_slice()[index] {
                            Some( ref hook ) => { Some(hook.copy()) }
                            None => {
                                None
                            }
                        }
                    } else {
                        None
                    }
                }
                &ArenaPtr::Builder(builder) => {
                    if index < (*builder).cap_table.len() {
                        match (*builder).cap_table.as_slice()[index] {
                            Some( ref hook ) => { Some(hook.copy()) }
                            None => {
                                None
                            }
                        }
                    } else {
                        None
                    }
                }
                &ArenaPtr::Null => {
                    panic!();
                }
            }
        }
    }

    pub fn fail_fast(&self) -> bool {
        unsafe {
            match self {
                &ArenaPtr::Reader(reader) => {
                    (*reader).fail_fast
                }
                &ArenaPtr::Builder(builder) => {
                    (*builder).fail_fast
                }
                &ArenaPtr::Null => {
                    panic!()
                }
            }
        }
    }

}
<commit_msg>panic on OOM<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::vec::Vec;
use libc;
use capability::ClientHook;
use common::*;
use message;

pub use self::FirstSegment::{NumWords, ZeroedWords};

pub type SegmentId = u32;

#[derive(Copy)]
pub struct SegmentReader {
    pub arena : ArenaPtr,
    pub ptr : *const Word,
    pub size : WordCount32
}

unsafe impl Send for SegmentReader {}

impl SegmentReader {

    #[inline]
    pub unsafe fn get_start_ptr(&self) -> *const Word {
        self.ptr.offset(0)
    }

    #[inline]
    pub fn contains_interval(&self, from : *const Word, to : *const Word) -> bool {
        let this_begin : usize = self.ptr as usize;
        let this_end : usize = unsafe { self.ptr.offset(self.size as isize) as usize };
        return from as usize >= this_begin && to as usize <= this_end && from as usize <= to as usize;
        // TODO readLimiter
    }
}

#[derive(Copy)]
pub struct SegmentBuilder {
    pub reader : SegmentReader,
    pub id : SegmentId,
    pos : *mut Word,
}

unsafe impl Send for SegmentBuilder {}

impl SegmentBuilder {

    pub fn new(arena : *mut BuilderArena,
               id : SegmentId,
               ptr : *mut Word,
               size : WordCount32) -> SegmentBuilder {
        SegmentBuilder {
            reader : SegmentReader {
                arena : ArenaPtr::Builder(arena),
                ptr : unsafe {::std::mem::transmute(ptr)},
                size : size
            },
            id : id,
            pos : ptr,
        }
    }

    pub fn get_word_offset_to(&mut self, ptr : *mut Word) -> WordCount32 {
        let this_addr : usize = self.reader.ptr as usize;
        let ptr_addr : usize = ptr as usize;
        assert!(ptr_addr >= this_addr);
        let result = (ptr_addr - this_addr) / BYTES_PER_WORD;
        return result as u32;
    }

    #[inline]
    pub fn current_size(&self) -> WordCount32 {
        ptr_sub(self.pos, self.reader.ptr) as u32
    }

    #[inline]
    pub fn allocate(&mut self, amount : WordCount32) -> Option<*mut Word> {
        if amount > self.reader.size - self.current_size() {
            return None;
        } else {
            let result = self.pos;
            self.pos = unsafe { self.pos.offset(amount as isize) };
            return Some(result);
        }
    }

    #[inline]
    pub fn get_ptr_unchecked(&self, offset : WordCount32) -> *mut Word {
        unsafe {
            ::std::mem::transmute(self.reader.ptr.offset(offset as isize))
        }
    }

    #[inline]
    pub fn get_segment_id(&self) -> SegmentId { self.id }

    #[inline]
    pub fn get_arena(&self) -> *mut BuilderArena {
        match self.reader.arena {
            ArenaPtr::Builder(b) => b,
            _ => unreachable!()
        }
    }
}

pub struct ReaderArena {
    //    message : *message::MessageReader<'a>,
    pub segment0 : SegmentReader,

    pub more_segments : Vec<SegmentReader>,
    //XXX should this be a map as in capnproto-c++?

    pub cap_table : Vec<Option<Box<ClientHook+Send>>>,

    pub fail_fast : bool,
}

impl ReaderArena {
    pub fn new(segments : &[&[Word]], options : message::ReaderOptions) -> Box<ReaderArena> {
        assert!(segments.len() > 0);
        let mut arena = Box::new(ReaderArena {
            segment0 : SegmentReader {
                arena : ArenaPtr::Null,
                ptr : unsafe { segments[0].get_unchecked(0) },
                size : segments[0].len() as u32
            },
            more_segments : Vec::new(),
            cap_table : Vec::new(),
            fail_fast : options.fail_fast,
        });

        let arena_ptr = ArenaPtr::Reader (&*arena);

        arena.segment0.arena = arena_ptr;

        if segments.len() > 1 {
            let mut more_segment_readers = Vec::new();
            for segment in segments[1 ..].iter() {
                let segment_reader = SegmentReader {
                    arena : arena_ptr,
                    ptr : unsafe { segment.get_unchecked(0) },
                    size : segment.len() as u32
                };
                more_segment_readers.push(segment_reader);
            }
            arena.more_segments = more_segment_readers;
        }

        arena
    }

    pub fn try_get_segment(&self, id : SegmentId) -> *const SegmentReader {
        if id == 0 {
            return &self.segment0 as *const SegmentReader;
        } else {
            unsafe { self.more_segments.get_unchecked(id as usize - 1) as *const SegmentReader }
        }
    }

    #[inline]
    pub fn init_cap_table(&mut self, cap_table : Vec<Option<Box<ClientHook+Send>>>) {
        self.cap_table = cap_table;
    }

}

pub struct BuilderArena {
    pub segment0 : SegmentBuilder,
    pub more_segments : Vec<Box<SegmentBuilder>>,
    pub allocation_strategy : message::AllocationStrategy,
    pub owned_memory : Vec<*mut Word>,
    pub next_size : u32,
    pub cap_table : Vec<Option<Box<ClientHook+Send>>>,
    pub fail_fast : bool,
}

impl Drop for BuilderArena {
    fn drop(&mut self) {
        for &segment_ptr in self.owned_memory.iter() {
            unsafe { libc::free(::std::mem::transmute(segment_ptr)); }
        }
    }
}

pub enum FirstSegment<'a> {
    NumWords(u32),
    ZeroedWords(&'a mut [Word])
}

impl BuilderArena {

    pub fn new(allocation_strategy : message::AllocationStrategy,
               first_segment : FirstSegment,
               fail_fast : bool) -> Box<BuilderArena> {

        let (first_segment, num_words, owned_memory) : (*mut Word, u32, Vec<*mut Word>) = unsafe {
            match first_segment {
                NumWords(n) => {
                    let ptr = ::std::mem::transmute(
                        libc::calloc(n as libc::size_t,
                                          BYTES_PER_WORD as libc::size_t));
                    (ptr, n, vec!(ptr))
                }
                ZeroedWords(w) => (w.as_mut_ptr(), w.len() as u32, Vec::new())
            }};

        let mut result = Box::new(BuilderArena {
            segment0 : SegmentBuilder {
                reader : SegmentReader {
                    ptr : first_segment as *const Word,
                    size : num_words,
                    arena : ArenaPtr::Null },
                id : 0,
                pos : first_segment,
            },
            more_segments : Vec::new(),
            allocation_strategy : allocation_strategy,
            owned_memory : owned_memory,
            next_size : num_words,
            cap_table : Vec::new(),
            fail_fast : fail_fast,
        });

        let arena_ptr = { let ref mut ptr = *result; ptr as *mut BuilderArena};
        result.segment0.reader.arena = ArenaPtr::Builder(arena_ptr);

        result
    }

    pub fn allocate_owned_memory(&mut self, minimum_size : WordCount32) -> (*mut Word, WordCount32) {
        let size = ::std::cmp::max(minimum_size, self.next_size);
        let new_words : *mut Word = unsafe {
            ::std::mem::transmute(libc::calloc(size as libc::size_t,
                                                   BYTES_PER_WORD as libc::size_t)) };

        if new_words.is_null() { panic!("could not allocate a new segment.") }

        self.owned_memory.push(new_words);

        match self.allocation_strategy {
            message::AllocationStrategy::GrowHeuristically => { self.next_size += size; }
            _ => { }
        }
        (new_words, size)
    }

    #[inline]
    pub fn allocate(&mut self, amount : WordCount32) -> (*mut SegmentBuilder, *mut Word) {
        unsafe {
            match self.segment0.allocate(amount) {
                Some(result) => { return ((&mut self.segment0) as *mut SegmentBuilder, result) }
                None => {}
            }

            //# Need to fall back to additional segments.

            let id = {
                let len = self.more_segments.len();
                if len == 0 { 1 }
                else {
                    let result_ptr = &mut *self.more_segments.as_mut_slice()[len-1] as *mut SegmentBuilder;
                    match self.more_segments.as_mut_slice()[len - 1].allocate(amount) {
                        Some(result) => { return (result_ptr, result) }
                        None => { len + 1 }
                    }
                }};

            let (words, size) = self.allocate_owned_memory(amount);
            let mut new_builder = Box::new(SegmentBuilder::new(self, id as u32, words, size));
            let builder_ptr = &mut *new_builder as *mut SegmentBuilder;

            self.more_segments.push(new_builder);

            (builder_ptr, (*builder_ptr).allocate(amount).unwrap() )
        }
    }

    pub fn get_segment(&mut self, id : SegmentId) -> *mut SegmentBuilder {
        if id == 0 {
            &mut self.segment0 as *mut SegmentBuilder
        } else {
            &mut *self.more_segments.as_mut_slice()[(id - 1) as usize] as *mut SegmentBuilder
        }
    }

    pub fn get_segments_for_output<T, U : FnMut(&[&[Word]]) -> T>(&self, mut cont : U) -> T {
        unsafe {
            if self.more_segments.len() == 0 {
                let v = ::std::slice::from_raw_parts::<Word>(
                    self.segment0.reader.ptr,
                    self.segment0.current_size() as usize);
                cont(&[v])
            } else {
                let mut result = Vec::new();
                result.push(::std::slice::from_raw_parts(self.segment0.reader.ptr,
                                                         self.segment0.current_size() as usize));
                for seg in self.more_segments.iter() {
                    result.push(::std::slice::from_raw_parts(seg.reader.ptr,
                                                             seg.current_size() as usize))
                }
                cont(result.as_slice())
            }
        }
    }

    pub fn get_cap_table<'a>(&'a self) -> &'a [Option<Box<ClientHook+Send>>] {
        self.cap_table.as_slice()
    }

    pub fn inject_cap(&mut self, cap : Box<ClientHook+Send>) -> u32 {
        self.cap_table.push(Some(cap));
        self.cap_table.len() as u32 - 1
    }
}

#[derive(Copy)]
pub enum ArenaPtr {
    Reader(*const ReaderArena),
    Builder(*mut BuilderArena),
    Null
}

impl ArenaPtr {
    pub fn try_get_segment(&self, id : SegmentId) -> *const SegmentReader {
        unsafe {
            match self {
                &ArenaPtr::Reader(reader) => {
                    (&*reader).try_get_segment(id)
                }
                &ArenaPtr::Builder(builder) => {
                    if id == 0 {
                        &(*builder).segment0.reader as *const SegmentReader
                    } else {
                        &(*builder).more_segments.as_slice()[id as usize - 1].reader as *const SegmentReader
                    }
                }
                &ArenaPtr::Null => {
                    panic!()
                }
            }
        }
    }

    pub fn extract_cap(&self, index : usize) -> Option<Box<ClientHook+Send>> {
        unsafe {
            match self {
                &ArenaPtr::Reader(reader) => {
                    if index < (*reader).cap_table.len() {
                        match (*reader).cap_table.as_slice()[index] {
                            Some( ref hook ) => { Some(hook.copy()) }
                            None => {
                                None
                            }
                        }
                    } else {
                        None
                    }
                }
                &ArenaPtr::Builder(builder) => {
                    if index < (*builder).cap_table.len() {
                        match (*builder).cap_table.as_slice()[index] {
                            Some( ref hook ) => { Some(hook.copy()) }
                            None => {
                                None
                            }
                        }
                    } else {
                        None
                    }
                }
                &ArenaPtr::Null => {
                    panic!();
                }
            }
        }
    }

    pub fn fail_fast(&self) -> bool {
        unsafe {
            match self {
                &ArenaPtr::Reader(reader) => {
                    (*reader).fail_fast
                }
                &ArenaPtr::Builder(builder) => {
                    (*builder).fail_fast
                }
                &ArenaPtr::Null => {
                    panic!()
                }
            }
        }
    }

}
<|endoftext|>


<commit_before>// xfail-fast
use std;
import std::task;
import std::comm;
import std::uint;

fn die() {
    fail;
}

fn iloop() {
    task::unsupervise();
    let f = die;
    task::spawn(f);
}

fn main() {
    for each i in uint::range(0u, 100u) {
        let f = iloop;
        task::spawn(f);
    }
}<commit_msg>Change run-pass/lots-a-fail.rs from xfail-fast to xfail-win32<commit_after>// xfail-win32 leaks
use std;
import std::task;
import std::comm;
import std::uint;

fn die() {
    fail;
}

fn iloop() {
    task::unsupervise();
    let f = die;
    task::spawn(f);
}

fn main() {
    for each i in uint::range(0u, 100u) {
        let f = iloop;
        task::spawn(f);
    }
}<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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::cell::Cell;
use std::mem::swap;

// Just a grab bag of stuff that you wouldn't want to actually write.

fn strange() -> bool { let _x: bool = return true; }

fn funny() {
    fn f(_x: ()) { }
    f(return);
}

fn what() {
    fn the(x: &Cell<bool>) {
        return while !x.get() { x.set(true); };
    }
    let i = &Cell::new(false);
    let dont = {||the(i)};
    dont();
    assert!((i.get()));
}

fn zombiejesus() {
    loop {
        while (return) {
            if (return) {
                match (return) {
                    1 => {
                        if (return) {
                            return
                        } else {
                            return
                        }
                    }
                    _ => { return }
                };
            } else if (return) {
                return;
            }
        }
        if (return) { break; }
    }
}

fn notsure() {
    let mut _x: isize;
    let mut _y = (_x = 0) == (_x = 0);
    let mut _z = (_x = 0) < (_x = 0);
    let _a = (_x += 0) == (_x = 0);
    let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z);
}

fn canttouchthis() -> usize {
    fn p() -> bool { true }
    let _a = (assert!((true)) == (assert!(p())));
    let _c = (assert!((p())) == ());
    let _b: bool = (println!("{}", 0) == (return 0));
}

fn angrydome() {
    loop { if break { } }
    let mut i = 0;
    loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } }
      break; }
}

fn evil_lincoln() { let _evil = println!("lincoln"); }

fn dots() {
    assert_eq!(String::from(".................................................."),
               format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..));
}

fn you_eight() {
    assert_eq!(8, {
        macro_rules! u8 {
            (u8) => {
                mod u8 {
                    pub fn u8<'u8>(u8: &'u8 u8) -> &'u8 u8 {
                        "u8";
                        u8
                    }
                }
            };
        }

        u8!(u8);
        let &u8: &u8 = u8::u8(&8u8);
        u8
    });
}

fn fishy() {
    assert_eq!(String::from("><>"), String::<>::from::<>("><>").chars::<>().rev::<>().collect::<String>());
}

pub fn main() {
    strange();
    funny();
    what();
    zombiejesus();
    notsure();
    canttouchthis();
    angrydome();
    evil_lincoln();
    dots();
    you_eight();
    fishy();
}
<commit_msg>tidy is an unnecessary roadblock to contributions<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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::cell::Cell;
use std::mem::swap;

// Just a grab bag of stuff that you wouldn't want to actually write.

fn strange() -> bool { let _x: bool = return true; }

fn funny() {
    fn f(_x: ()) { }
    f(return);
}

fn what() {
    fn the(x: &Cell<bool>) {
        return while !x.get() { x.set(true); };
    }
    let i = &Cell::new(false);
    let dont = {||the(i)};
    dont();
    assert!((i.get()));
}

fn zombiejesus() {
    loop {
        while (return) {
            if (return) {
                match (return) {
                    1 => {
                        if (return) {
                            return
                        } else {
                            return
                        }
                    }
                    _ => { return }
                };
            } else if (return) {
                return;
            }
        }
        if (return) { break; }
    }
}

fn notsure() {
    let mut _x: isize;
    let mut _y = (_x = 0) == (_x = 0);
    let mut _z = (_x = 0) < (_x = 0);
    let _a = (_x += 0) == (_x = 0);
    let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z);
}

fn canttouchthis() -> usize {
    fn p() -> bool { true }
    let _a = (assert!((true)) == (assert!(p())));
    let _c = (assert!((p())) == ());
    let _b: bool = (println!("{}", 0) == (return 0));
}

fn angrydome() {
    loop { if break { } }
    let mut i = 0;
    loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } }
      break; }
}

fn evil_lincoln() { let _evil = println!("lincoln"); }

fn dots() {
    assert_eq!(String::from(".................................................."),
               format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. ..
                               .. .. .. .. .. .. .. .. .. .. .. ..));
}

fn you_eight() {
    assert_eq!(8, {
        macro_rules! u8 {
            (u8) => {
                mod u8 {
                    pub fn u8<'u8>(u8: &'u8 u8) -> &'u8 u8 {
                        "u8";
                        u8
                    }
                }
            };
        }

        u8!(u8);
        let &u8: &u8 = u8::u8(&8u8);
        u8
    });
}

fn fishy() {
    assert_eq!(String::from("><>"),
               String::<>::from::<>("><>").chars::<>().rev::<>().collect::<String>());
}

pub fn main() {
    strange();
    funny();
    what();
    zombiejesus();
    notsure();
    canttouchthis();
    angrydome();
    evil_lincoln();
    dots();
    you_eight();
    fishy();
}
<|endoftext|>


<commit_before>// * This file is part of the uutils coreutils package.
// *
// * (c) 2015 Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
// * (c) 2020 nicoo            <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

use std::cmp::min;
use std::mem::swap;

pub fn gcd(mut u: u64, mut v: u64) -> u64 {
    // Stein's binary GCD algorithm
    // Base cases: gcd(n, 0) = gcd(0, n) = n
    if u == 0 {
        return v;
    } else if v == 0 {
        return u;
    }

    // gcd(2ⁱ u, 2ʲ v) = 2ᵏ gcd(u, v) with u, v odd and k = min(i, j)
    // 2ᵏ is the greatest power of two that divides both u and v
    let k = {
        let i = u.trailing_zeros();
        let j = v.trailing_zeros();
        u >>= i;
        v >>= j;
        min(i, j)
    };

    loop {
        // Loop invariant: u and v are odd
        debug_assert!(u % 2 == 1, "u = {} is even", u);
        debug_assert!(v % 2 == 1, "v = {} is even", v);

        // gcd(u, v) = gcd(|u - v|, min(u, v))
        if u > v {
            swap(&mut u, &mut v);
        }
        v -= u;

        if v == 0 {
            // Reached the base case; gcd is 2ᵏ u
            return u << k;
        }

        // gcd(u, 2ʲ v) = gcd(u, v) as u is odd
        v >>= v.trailing_zeros();
    }
}

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

    quickcheck! {
        fn euclidean(a: u64, b: u64) -> bool {
            // Test against the Euclidean algorithm
            let g = {
                let (mut a, mut b) = (a, b);
                while b > 0 {
                    a %= b;
                    swap(&mut a, &mut b);
                }
                a
            };
            gcd(a, b) == g
        }

        fn one(a: u64) -> bool {
            gcd(1, a) == 1
        }

        fn zero(a: u64) -> bool {
            gcd(0, a) == a
        }

        fn divisor(a: u64, b: u64) -> bool {
            // Test that gcd(a, b) divides a and b
            let g = gcd(a, b);
            (a == 0 && b == 0) || (a % g == 0 && b % g == 0)
        }

        fn commutative(a: u64, b: u64) -> bool {
            gcd(a, b) == gcd(b, a)
        }

        fn associative(a: u64, b: u64, c: u64) -> bool {
            gcd(a, gcd(b, c)) == gcd(gcd(a, b), c)
        }

        fn scalar_mult(a: u64, b: u64, k: u64) -> bool {
            gcd(k * a, k * b) == k * gcd(a, b)
        }

        fn multiplicative(a: u64, b: u64, c: u64) -> bool {
            // gcd(ab, c) = gcd(a, c) gcd(b, c) when a and b coprime
            gcd(a, b) != 1 || gcd(a * b, c) == gcd(a, c) * gcd(b, c)
        }

        fn linearity(a: u64, b: u64, k: u64) -> bool {
            gcd(a + k * b, b) == gcd(a, b)
        }
    }
}
<commit_msg>factor::numeric::gcd: modify `divisor()` test to return correct true/false results for all possible inputs<commit_after>// * This file is part of the uutils coreutils package.
// *
// * (c) 2015 Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
// * (c) 2020 nicoo            <nicoo@debian.org>
// *
// * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code.

use std::cmp::min;
use std::mem::swap;

pub fn gcd(mut u: u64, mut v: u64) -> u64 {
    // Stein's binary GCD algorithm
    // Base cases: gcd(n, 0) = gcd(0, n) = n
    if u == 0 {
        return v;
    } else if v == 0 {
        return u;
    }

    // gcd(2ⁱ u, 2ʲ v) = 2ᵏ gcd(u, v) with u, v odd and k = min(i, j)
    // 2ᵏ is the greatest power of two that divides both u and v
    let k = {
        let i = u.trailing_zeros();
        let j = v.trailing_zeros();
        u >>= i;
        v >>= j;
        min(i, j)
    };

    loop {
        // Loop invariant: u and v are odd
        debug_assert!(u % 2 == 1, "u = {} is even", u);
        debug_assert!(v % 2 == 1, "v = {} is even", v);

        // gcd(u, v) = gcd(|u - v|, min(u, v))
        if u > v {
            swap(&mut u, &mut v);
        }
        v -= u;

        if v == 0 {
            // Reached the base case; gcd is 2ᵏ u
            return u << k;
        }

        // gcd(u, 2ʲ v) = gcd(u, v) as u is odd
        v >>= v.trailing_zeros();
    }
}

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

    quickcheck! {
        fn euclidean(a: u64, b: u64) -> bool {
            // Test against the Euclidean algorithm
            let g = {
                let (mut a, mut b) = (a, b);
                while b > 0 {
                    a %= b;
                    swap(&mut a, &mut b);
                }
                a
            };
            gcd(a, b) == g
        }

        fn one(a: u64) -> bool {
            gcd(1, a) == 1
        }

        fn zero(a: u64) -> bool {
            gcd(0, a) == a
        }

        fn divisor(a: u64, b: u64) -> bool {
            // Test that gcd(a, b) divides a and b
            let g = gcd(a, b);
            (g != 0 && a % g == 0 && b % g == 0) || (g == 0 && a == 0 && b == 0)
        }

        fn commutative(a: u64, b: u64) -> bool {
            gcd(a, b) == gcd(b, a)
        }

        fn associative(a: u64, b: u64, c: u64) -> bool {
            gcd(a, gcd(b, c)) == gcd(gcd(a, b), c)
        }

        fn scalar_mult(a: u64, b: u64, k: u64) -> bool {
            gcd(k * a, k * b) == k * gcd(a, b)
        }

        fn multiplicative(a: u64, b: u64, c: u64) -> bool {
            // gcd(ab, c) = gcd(a, c) gcd(b, c) when a and b coprime
            gcd(a, b) != 1 || gcd(a * b, c) == gcd(a, c) * gcd(b, c)
        }

        fn linearity(a: u64, b: u64, k: u64) -> bool {
            gcd(a + k * b, b) == gcd(a, b)
        }
    }
}
<|endoftext|>


<commit_before>use std::net::{SocketAddr};
use std::str;
use std::collections::HashMap;

use futures::prelude::*;
use futures::{Future, Stream};

use hyper::Client;

use tokio::prelude::FutureExt;
use tokio::net::UdpSocket;

use bytes::Bytes;

use aio::Gateway;
use common::{messages, parsing, SearchOptions};
use errors::SearchError;

const MAX_RESPONSE_SIZE: usize = 1500;

/// Search for a gateway with the provided options
pub fn search_gateway(options: SearchOptions) -> impl Future<Item=Gateway, Error=SearchError> {
    use futures::future::{err, Either::A, Either::B};

    // Create socket for future calls
    let socket = match UdpSocket::bind(&options.bind_addr) {
        Ok(s) => s,
        Err(e) => return  A(err(SearchError::from(e))),
    };

    // Create future and issue request
    match options.timeout {
        Some(t) =>B(A(SearchFuture::search(socket, options.broadcast_address)
            .and_then(|search| search ).timeout(t).map_err(|e| SearchError::from(e) ))),
        _ =>B(B(SearchFuture::search(socket, options.broadcast_address).and_then(|search| search ))),
    }
}

pub struct SearchFuture {
    socket: UdpSocket,
    pending: HashMap<SocketAddr, SearchState>,
}

enum SearchState {
    Connecting(Box<Future<Item=Bytes, Error=SearchError> + Send>),
    Done(String),
    Error,
}

impl SearchFuture {
    // Create a new search
    fn search(socket: UdpSocket, addr: SocketAddr) -> impl Future<Item=SearchFuture, Error=SearchError> {
        debug!("sending broadcast request to: {} on interface: {:?}", addr, socket.local_addr());

        socket.send_dgram(messages::SEARCH_REQUEST.as_bytes(), &addr)
            .map(|(socket, _n)| SearchFuture{socket, pending: HashMap::new() })
            .map_err(|e| SearchError::from(e) )
    }

    // Handle a UDP response message
    fn handle_broadcast_resp(from: SocketAddr, data: &[u8]) -> Result<(SocketAddr, String), SearchError> {
        debug!("handling broadcast response from: {}", from);

        // Convert response to text
        let text = str::from_utf8(&data)
            .map_err(|e| SearchError::from(e))?;

        // Parse socket address and path
        let (addr, path) = parsing::parse_search_result(text)?;

        Ok((SocketAddr::V4(addr), path))
    }

    // Issue a control URL request over HTTP using the provided
    fn request_control_url(addr: SocketAddr, path: String) -> Result<Box<Future<Item=Bytes, Error=SearchError> + Send>, SearchError> {
        let client = Client::new();

        let uri = match format!("http://{}{}", addr, path).parse() {
            Ok(uri) => uri,
            Err(err) => return Err(SearchError::from(err)),
        };

        debug!("requesting control url from: {}", uri);

        Ok(Box::new(client.get(uri)
            .and_then(|resp| resp.into_body().concat2() )
            .map(|chunk| chunk.into_bytes() )
            .map_err(|e| SearchError::from(e) )
        ))
    }

    // Process a control response to extract the control URL
    fn handle_control_resp(addr: SocketAddr, resp: Bytes) -> Result<String, SearchError> {
        debug!("handling control response from: {}", addr);

        // Create a cursor over the response data
        let c = std::io::Cursor::new(&resp);

        // Parse control URL out of body
        let url = parsing::parse_control_url(c)?;

        Ok(url)
    }
}

impl Future for SearchFuture {
    type Item=Gateway;
    type Error=SearchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {

        // Poll for (and handle) incoming messages
        let mut buff = [0u8; MAX_RESPONSE_SIZE];
        if let Async::Ready((n, from)) = self.socket.poll_recv_from(&mut buff)? {
            // Try handle response messages
            if let Ok((addr, path)) = Self::handle_broadcast_resp(from, &buff[0..n]) {
                if !self.pending.contains_key(&addr) {
                    debug!("received broadcast response from: {}", from);

                    // Issue control request
                    let req = Self::request_control_url(addr, path)?;
                    // Store pending requests
                    self.pending.insert(addr, SearchState::Connecting(req));
                } else {
                    debug!("received duplicate broadcast response from: {}, dropping", from);
                }
            }
        }

        // Poll on any outstanding control requests
        for (addr, state) in &mut self.pending {
            // Poll if we're in the connecting state
            let resp = {
                let c = match state {
                    SearchState::Connecting(c) => c,
                    _ => continue,
                };

                match c.poll()? {
                    Async::Ready(resp) => resp,
                    _ => continue,
                }
            };

            // Handle any responses
            if let Ok(url) = Self::handle_control_resp(*addr, resp) {
                debug!("received control url from: {} (url: {})", addr, url);
                *state = SearchState::Done(url.clone());

                match addr {
                    SocketAddr::V4(a) => {
                        let g = Gateway::new(*a, url);
                        return Ok(Async::Ready(g));
                    }
                    _ => warn!("unsupported IPv6 gateway response from addr: {}", addr),
                }

            } else {
                *state = SearchState::Error;
            }
        }

        Ok(Async::NotReady)
    }
}
<commit_msg>Update search.rs<commit_after>use std::net::{SocketAddr};
use std::str;
use std::collections::HashMap;

use futures::prelude::*;
use futures::{Future, Stream};

use hyper::Client;

use tokio::prelude::FutureExt;
use tokio::net::UdpSocket;

use bytes::Bytes;

use aio::Gateway;
use common::{messages, parsing, SearchOptions};
use errors::SearchError;

const MAX_RESPONSE_SIZE: usize = 1500;

/// Search for a gateway with the provided options
pub fn search_gateway(options: SearchOptions) -> impl Future<Item=Gateway, Error=SearchError> {
    use futures::future::{err, Either::A, Either::B};

    // Create socket for future calls
    let socket = match UdpSocket::bind(&options.bind_addr) {
        Ok(s) => s,
        Err(e) => return  A(err(SearchError::from(e))),
    };

    // Create future and issue request
    match options.timeout {
        Some(t) =>B(A(SearchFuture::search(socket, options.broadcast_address)
            .and_then(|search| search ).timeout(t).map_err(|e| SearchError::from(e) ))),
        _ =>B(B(SearchFuture::search(socket, options.broadcast_address).and_then(|search| search ))),
    }
}

pub struct SearchFuture {
    socket: UdpSocket,
    pending: HashMap<SocketAddr, SearchState>,
}

enum SearchState {
    Connecting(Box<Future<Item=Bytes, Error=SearchError> + Send>),
    Done(String),
    Error,
}

impl SearchFuture {
    // Create a new search
    fn search(socket: UdpSocket, addr: SocketAddr) -> impl Future<Item=SearchFuture, Error=SearchError> {
        debug!("sending broadcast request to: {} on interface: {:?}", addr, socket.local_addr());

        socket.send_dgram(messages::SEARCH_REQUEST.as_bytes(), &addr)
            .map(|(socket, _n)| SearchFuture{socket, pending: HashMap::new() })
            .map_err(|e| SearchError::from(e) )
    }

    // Handle a UDP response message
    fn handle_broadcast_resp(from: SocketAddr, data: &[u8]) -> Result<(SocketAddr, String), SearchError> {
        debug!("handling broadcast response from: {}", from);

        // Convert response to text
        let text = str::from_utf8(&data)
            .map_err(|e| SearchError::from(e))?;

        // Parse socket address and path
        let (addr, path) = parsing::parse_search_result(text)?;

        Ok((SocketAddr::V4(addr), path))
    }

    // Issue a control URL request over HTTP using the provided
    fn request_control_url(addr: SocketAddr, path: String) -> Result<Box<Future<Item=Bytes, Error=SearchError> + Send>, SearchError> {
        let client = Client::new();

        let uri = match format!("http://{}{}", addr, path).parse() {
            Ok(uri) => uri,
            Err(err) => return Err(SearchError::from(err)),
        };

        debug!("requesting control url from: {}", uri);

        Ok(Box::new(client.get(uri)
            .and_then(|resp| resp.into_body().concat2() )
            .map(|chunk| chunk.into_bytes() )
            .map_err(|e| SearchError::from(e) )
        ))
    }

    // Process a control response to extract the control URL
    fn handle_control_resp(addr: SocketAddr, resp: Bytes) -> Result<Vec<String>, SearchError> {
        debug!("handling control response from: {}", addr);

        // Create a cursor over the response data
        let c = std::io::Cursor::new(&resp);

        // Parse control URL out of body
        let url = parsing::parse_control_url(c)?;

        Ok(url)
    }
}

impl Future for SearchFuture {
    type Item=Gateway;
    type Error=SearchError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {

        // Poll for (and handle) incoming messages
        let mut buff = [0u8; MAX_RESPONSE_SIZE];
        if let Async::Ready((n, from)) = self.socket.poll_recv_from(&mut buff)? {
            // Try handle response messages
            if let Ok((addr, path)) = Self::handle_broadcast_resp(from, &buff[0..n]) {
                if !self.pending.contains_key(&addr) {
                    debug!("received broadcast response from: {}", from);

                    // Issue control request
                    let req = Self::request_control_url(addr, path)?;
                    // Store pending requests
                    self.pending.insert(addr, SearchState::Connecting(req));
                } else {
                    debug!("received duplicate broadcast response from: {}, dropping", from);
                }
            }
        }

        // Poll on any outstanding control requests
        for (addr, state) in &mut self.pending {
            // Poll if we're in the connecting state
            let resp = {
                let c = match state {
                    SearchState::Connecting(c) => c,
                    _ => continue,
                };

                match c.poll()? {
                    Async::Ready(resp) => resp,
                    _ => continue,
                }
            };

            // Handle any responses
            if let Ok(url) = Self::handle_control_resp(*addr, resp) {
                debug!("received control url from: {} (url: {})", addr, url);
                *state = SearchState::Done(url.clone());

                match addr {
                    SocketAddr::V4(a) => {
                        let g = Gateway::new(*a, url);
                        return Ok(Async::Ready(g));
                    }
                    _ => warn!("unsupported IPv6 gateway response from addr: {}", addr),
                }

            } else {
                *state = SearchState::Error;
            }
        }

        Ok(Async::NotReady)
    }
}
<|endoftext|>


<commit_before>use std::convert::From;
use std::iter::{FromIterator, IntoIterator, Iterator};

use binding::array;
use types::{Value, ValueType};

use {AnyObject, RString, Object, VerifiedObject};

/// `Array`
#[derive(Debug, PartialEq)]
pub struct Array {
    value: Value,
}

impl Array {
    /// Creates a new instance of empty `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, VM};
    /// # VM::init();
    ///
    /// Array::new();
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// []
    /// ```
    pub fn new() -> Self {
        Self::from(array::new())
    }

    /// Retrieves the length of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.length(), 1);
    ///
    /// array.push(Fixnum::new(2));
    ///
    /// assert_eq!(array.length(), 2);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.length == 1
    ///
    /// array << 2
    /// array.length == 2
    /// ```
    pub fn length(&self) -> usize {
        array::len(self.value()) as usize
    }

    /// Retrieves an `AnyObject` from the element at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array[0] == 1
    /// ```
    pub fn at(&self, index: i64) -> AnyObject {
        let result = array::entry(self.value(), index);

        AnyObject::from(result)
    }

    /// Joins all elements of `Array` to Ruby `String`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, RString, VM};
    /// # VM::init();
    ///
    /// let array = Array::new()
    ///     .push(RString::new("Hello"))
    ///     .push(RString::new("World!"));
    ///
    /// let joined_string = array.join(RString::new(", ")).to_string();
    ///
    /// assert_eq!(joined_string, "Hello, World!".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = ['Hello', 'World!']
    ///
    /// joined_string = array.join(', ')
    ///
    /// joined_string == 'Hello, World!'
    /// ```
    pub fn join(&self, separator: RString) -> RString {
        let result = array::join(self.value(), separator.value());

        RString::from(result)
    }

    /// Pushes an object to `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new();
    ///
    /// array.push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = []
    /// array << 1
    ///
    /// array[0] == 1
    /// ```
    pub fn push<T: Object>(&mut self, item: T) -> Self {
        let result = array::push(self.value(), item.value());

        Array::from(result)
    }

    /// Stores an object at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.store(0, Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array[0] = 2
    ///
    /// array[0] == 2
    /// ```
    pub fn store<T: Object>(&mut self, index: i64, item: T) -> AnyObject {
        let result = array::store(self.value(), index, item.value());

        AnyObject::from(result)
    }

    /// Removes and returns the last element of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.pop().try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array.pop == 1
    /// ```
    pub fn pop(&mut self) -> AnyObject {
        let result = array::pop(self.value());

        AnyObject::from(result)
    }

    /// Inserts `item` at the beggining of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.unshift(Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.unshift(2)
    ///
    /// array[0] == 2
    /// ```
    pub fn unshift<T: Object>(&mut self, item: T) -> AnyObject {
        let result = array::unshift(self.value(), item.value());

        AnyObject::from(result)
    }

    /// Removes the first item of the array and returns it.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// let item = array.shift();
    ///
    /// assert_eq!(item.try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// item = array.shift
    ///
    /// item == 1
    /// array[0] == 2
    /// ```
    pub fn shift(&mut self) -> AnyObject {
        let result = array::shift(self.value());

        AnyObject::from(result)
    }

    /// Creates a copy of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let copy = array.dup();
    ///
    /// assert_eq!(array.at(0), copy.at(0));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// copy = array.dup
    ///
    /// array[0] == copy[0]
    /// ```
    pub fn dup(&self) -> Array {
        let result = array::dup(self.value());

        Array::from(result)
    }

    /// Creates a string representation of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// assert_eq!(array.to_s().to_string(), "[1, 2]".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// array.to_s == "[1, 2]"
    /// ```
    pub fn to_s(&mut self) -> RString {
        let result = array::to_s(self.value());

        RString::from(result)
    }

    /// Returns a new array containing array's elements in reverse order.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// array.reverse();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    /// array.reverse!
    ///
    /// array[0] == 2
    /// array[1] == 1
    /// ```
    pub fn reverse(&mut self) -> Array {
        let result = array::reverse(self.value());
        Array::from(result)
    }

    /// Appends the elements of `other` array to `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    /// let other = Array::new().push(Fixnum::new(2));
    ///
    /// array.concat(other);
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// other = [2]
    ///
    /// array.concat(other)
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn concat(&mut self, other: Array) -> Array {
        let result = array::concat(self.value(), other.value());

        Array::from(result)
    }

    /// Returns a new array created by sorting `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// let sorted_array = array.sort();
    ///
    /// assert_eq!(sorted_array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(sorted_array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// sorted_array = array.sort
    ///
    /// sorted_array[0] == 1
    /// sorted_array[1] == 2
    /// ```
    pub fn sort(&mut self) -> Array {
        let result = array::sort(self.value());
        Array::from(result)
    }

    /// Sorts the array in place.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// array.sort_bang();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// array.sort!
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn sort_bang(&mut self) -> Array {
        let result = array::sort_bang(self.value());
        Array::from(result)
    }
}

impl From<Value> for Array {
    fn from(value: Value) -> Self {
        Array { value: value }
    }
}

impl Object for Array {
    #[inline]
    fn value(&self) -> Value {
        self.value
    }
}

impl VerifiedObject for Array {
    fn is_correct_type<T: Object>(object: &T) -> bool {
        object.value().ty() == ValueType::Array
    }

    fn error_message() -> &'static str {
        "Error converting to Boolean"
    }
}

pub struct ArrayIterator {
    array: Array,
    current_index: i64,
}

impl ArrayIterator {
    fn new(array: Array) -> ArrayIterator {
        ArrayIterator {
            array: array,
            current_index: 0,
        }
    }
}

impl Iterator for ArrayIterator {
    type Item = AnyObject;

    fn next(&mut self) -> Option<AnyObject> {
        let item = if (self.current_index as usize) < self.len() {
            Some(self.array.at(self.current_index))
        } else {
            None
        };

        self.current_index += 1;

        item
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let total = self.len() as usize;
        (total, Some(total))
    }
}

impl ExactSizeIterator for ArrayIterator {
    fn len(&self) -> usize {
        self.array.length() as usize
    }
}

/// Allows Arrays to be iterable in Rust.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let mut array = Array::new()
///     .push(Fixnum::new(1))
///     .push(Fixnum::new(2))
///     .push(Fixnum::new(3));
///
/// let mut sum: i64 = 0;
///
/// for item in array.into_iter() {
///     sum += item.try_convert_to::<Fixnum>().unwrap().to_i64();
/// }
///
/// assert_eq!(sum, 6);
/// ```
impl IntoIterator for Array {
    type Item = AnyObject;
    type IntoIter = ArrayIterator;

    fn into_iter(self) -> Self::IntoIter {
        ArrayIterator::new(self)
    }
}

/// Converts an iterator into `Array`.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let array: Array = (1..6)
///     .map(|num| num * 2)
///     .map(|num| Fixnum::new(num).to_any_object())
///     .collect();
///
/// assert_eq!(array.length(), 5);
///
/// for i in 0..5 {
///     let expected_number = (i + 1) * 2;
///
///     assert_eq!(array.at(i).try_convert_to::<Fixnum>().unwrap().to_i64(), expected_number);
/// }
/// ```
impl FromIterator<AnyObject> for Array {
    fn from_iter<I: IntoIterator<Item = AnyObject>>(iter: I) -> Self {
        let mut array = Array::new();

        for i in iter {
            array.push(i);
        }

        array
    }
}
<commit_msg>Change Array::to_s() to receive &self<commit_after>use std::convert::From;
use std::iter::{FromIterator, IntoIterator, Iterator};

use binding::array;
use types::{Value, ValueType};

use {AnyObject, RString, Object, VerifiedObject};

/// `Array`
#[derive(Debug, PartialEq)]
pub struct Array {
    value: Value,
}

impl Array {
    /// Creates a new instance of empty `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, VM};
    /// # VM::init();
    ///
    /// Array::new();
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// []
    /// ```
    pub fn new() -> Self {
        Self::from(array::new())
    }

    /// Retrieves the length of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.length(), 1);
    ///
    /// array.push(Fixnum::new(2));
    ///
    /// assert_eq!(array.length(), 2);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.length == 1
    ///
    /// array << 2
    /// array.length == 2
    /// ```
    pub fn length(&self) -> usize {
        array::len(self.value()) as usize
    }

    /// Retrieves an `AnyObject` from the element at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array[0] == 1
    /// ```
    pub fn at(&self, index: i64) -> AnyObject {
        let result = array::entry(self.value(), index);

        AnyObject::from(result)
    }

    /// Joins all elements of `Array` to Ruby `String`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, RString, VM};
    /// # VM::init();
    ///
    /// let array = Array::new()
    ///     .push(RString::new("Hello"))
    ///     .push(RString::new("World!"));
    ///
    /// let joined_string = array.join(RString::new(", ")).to_string();
    ///
    /// assert_eq!(joined_string, "Hello, World!".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = ['Hello', 'World!']
    ///
    /// joined_string = array.join(', ')
    ///
    /// joined_string == 'Hello, World!'
    /// ```
    pub fn join(&self, separator: RString) -> RString {
        let result = array::join(self.value(), separator.value());

        RString::from(result)
    }

    /// Pushes an object to `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new();
    ///
    /// array.push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = []
    /// array << 1
    ///
    /// array[0] == 1
    /// ```
    pub fn push<T: Object>(&mut self, item: T) -> Self {
        let result = array::push(self.value(), item.value());

        Array::from(result)
    }

    /// Stores an object at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.store(0, Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array[0] = 2
    ///
    /// array[0] == 2
    /// ```
    pub fn store<T: Object>(&mut self, index: i64, item: T) -> AnyObject {
        let result = array::store(self.value(), index, item.value());

        AnyObject::from(result)
    }

    /// Removes and returns the last element of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.pop().try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array.pop == 1
    /// ```
    pub fn pop(&mut self) -> AnyObject {
        let result = array::pop(self.value());

        AnyObject::from(result)
    }

    /// Inserts `item` at the beggining of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.unshift(Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.unshift(2)
    ///
    /// array[0] == 2
    /// ```
    pub fn unshift<T: Object>(&mut self, item: T) -> AnyObject {
        let result = array::unshift(self.value(), item.value());

        AnyObject::from(result)
    }

    /// Removes the first item of the array and returns it.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// let item = array.shift();
    ///
    /// assert_eq!(item.try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// item = array.shift
    ///
    /// item == 1
    /// array[0] == 2
    /// ```
    pub fn shift(&mut self) -> AnyObject {
        let result = array::shift(self.value());

        AnyObject::from(result)
    }

    /// Creates a copy of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let copy = array.dup();
    ///
    /// assert_eq!(array.at(0), copy.at(0));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// copy = array.dup
    ///
    /// array[0] == copy[0]
    /// ```
    pub fn dup(&self) -> Array {
        let result = array::dup(self.value());

        Array::from(result)
    }

    /// Creates a string representation of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// assert_eq!(array.to_s().to_string(), "[1, 2]".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// array.to_s == "[1, 2]"
    /// ```
    pub fn to_s(&self) -> RString {
        let result = array::to_s(self.value());

        RString::from(result)
    }

    /// Returns a new array containing array's elements in reverse order.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// array.reverse();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    /// array.reverse!
    ///
    /// array[0] == 2
    /// array[1] == 1
    /// ```
    pub fn reverse(&mut self) -> Array {
        let result = array::reverse(self.value());
        Array::from(result)
    }

    /// Appends the elements of `other` array to `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    /// let other = Array::new().push(Fixnum::new(2));
    ///
    /// array.concat(other);
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// other = [2]
    ///
    /// array.concat(other)
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn concat(&mut self, other: Array) -> Array {
        let result = array::concat(self.value(), other.value());

        Array::from(result)
    }

    /// Returns a new array created by sorting `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// let sorted_array = array.sort();
    ///
    /// assert_eq!(sorted_array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(sorted_array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// sorted_array = array.sort
    ///
    /// sorted_array[0] == 1
    /// sorted_array[1] == 2
    /// ```
    pub fn sort(&mut self) -> Array {
        let result = array::sort(self.value());
        Array::from(result)
    }

    /// Sorts the array in place.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// array.sort_bang();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// array.sort!
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn sort_bang(&mut self) -> Array {
        let result = array::sort_bang(self.value());
        Array::from(result)
    }
}

impl From<Value> for Array {
    fn from(value: Value) -> Self {
        Array { value: value }
    }
}

impl Object for Array {
    #[inline]
    fn value(&self) -> Value {
        self.value
    }
}

impl VerifiedObject for Array {
    fn is_correct_type<T: Object>(object: &T) -> bool {
        object.value().ty() == ValueType::Array
    }

    fn error_message() -> &'static str {
        "Error converting to Boolean"
    }
}

pub struct ArrayIterator {
    array: Array,
    current_index: i64,
}

impl ArrayIterator {
    fn new(array: Array) -> ArrayIterator {
        ArrayIterator {
            array: array,
            current_index: 0,
        }
    }
}

impl Iterator for ArrayIterator {
    type Item = AnyObject;

    fn next(&mut self) -> Option<AnyObject> {
        let item = if (self.current_index as usize) < self.len() {
            Some(self.array.at(self.current_index))
        } else {
            None
        };

        self.current_index += 1;

        item
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let total = self.len() as usize;
        (total, Some(total))
    }
}

impl ExactSizeIterator for ArrayIterator {
    fn len(&self) -> usize {
        self.array.length() as usize
    }
}

/// Allows Arrays to be iterable in Rust.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let mut array = Array::new()
///     .push(Fixnum::new(1))
///     .push(Fixnum::new(2))
///     .push(Fixnum::new(3));
///
/// let mut sum: i64 = 0;
///
/// for item in array.into_iter() {
///     sum += item.try_convert_to::<Fixnum>().unwrap().to_i64();
/// }
///
/// assert_eq!(sum, 6);
/// ```
impl IntoIterator for Array {
    type Item = AnyObject;
    type IntoIter = ArrayIterator;

    fn into_iter(self) -> Self::IntoIter {
        ArrayIterator::new(self)
    }
}

/// Converts an iterator into `Array`.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let array: Array = (1..6)
///     .map(|num| num * 2)
///     .map(|num| Fixnum::new(num).to_any_object())
///     .collect();
///
/// assert_eq!(array.length(), 5);
///
/// for i in 0..5 {
///     let expected_number = (i + 1) * 2;
///
///     assert_eq!(array.at(i).try_convert_to::<Fixnum>().unwrap().to_i64(), expected_number);
/// }
/// ```
impl FromIterator<AnyObject> for Array {
    fn from_iter<I: IntoIterator<Item = AnyObject>>(iter: I) -> Self {
        let mut array = Array::new();

        for i in iter {
            array.push(i);
        }

        array
    }
}
<|endoftext|>


<commit_before>use nom::multispace;
use std::str;

use common::{integer_literal, sql_identifier, Literal};
use column::Column;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ArithmeticOperator {
    Add,
    Subtract,
    Multiply,
    Divide,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ArithmeticBase {
    Column(Column),
    Scalar(Literal),
}

#[derive(Debug, Clone, PartialEq)]
pub struct ArithmeticExpression {
    op: ArithmeticOperator,
    left: ArithmeticBase,
    right: ArithmeticBase,
}

impl ArithmeticExpression {
    pub fn new(op: ArithmeticOperator, left: ArithmeticBase, right: ArithmeticBase) -> Self {
        Self {
            op: op,
            left: left,
            right: right,
        }
    }
}

/// Parse standard math operators.
named!(pub arithmetic_operator<&[u8], ArithmeticOperator>,
    alt_complete!(
          map!(tag!("+"), |_| ArithmeticOperator::Add)
        | map!(tag!("-"), |_| ArithmeticOperator::Subtract)
        | map!(tag!("*"), |_| ArithmeticOperator::Multiply)
        | map!(tag!("/"), |_| ArithmeticOperator::Divide)
    )
);

/// Base case for nested arithmetic expressions: column name or literal.
named!(pub arithmetic_base<&[u8], ArithmeticBase>,
    alt_complete!(
          map!(integer_literal, |il| ArithmeticBase::Scalar(il))
        | map!(sql_identifier, |si| {
              let c = Column::from(str::from_utf8(si).unwrap());
              ArithmeticBase::Column(c)
          })
    )
);

/// Parse simple arithmetic expressions combining literals, and columns and literals.
named!(pub arithmetic_expression<&[u8], ArithmeticExpression>,
    complete!(chain!(
        left: arithmetic_base ~
        multispace? ~
        op: arithmetic_operator ~
        multispace? ~
        right: arithmetic_base,
        || {
            ArithmeticExpression {
                op: op,
                left: left,
                right: right
            }
        }
    ))
);

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

    #[test]
    fn it_parses_arithmetic_expressions() {
        use super::ArithmeticOperator::*;
        use super::ArithmeticBase::*;

        let lit_ae = ["5 + 42", "5+42", "5 * 42", "5 - 42", "5 / 42"];
        let col_lit_ae = ["foo+5", "foo + 5", "5 + foo"];

        let expected_lit_ae = [
            ArithmeticExpression::new(Add, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Add, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Multiply, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Subtract, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Divide, Scalar(5.into()), Scalar(42.into())),
        ];
        let expected_col_lit_ae = [
            ArithmeticExpression::new(Add, Column("foo".into()), Scalar(5.into())),
            ArithmeticExpression::new(Add, Column("foo".into()), Scalar(5.into())),
            ArithmeticExpression::new(Add, Scalar(5.into()), Column("foo".into())),
        ];

        for (i, e) in lit_ae.iter().enumerate() {
            let res = arithmetic_expression(e.as_bytes());
            assert!(res.is_done());
            assert_eq!(res.unwrap().1, expected_lit_ae[i]);
        }

        for (i, e) in col_lit_ae.iter().enumerate() {
            let res = arithmetic_expression(e.as_bytes());
            assert!(res.is_done());
            assert_eq!(res.unwrap().1, expected_col_lit_ae[i]);
        }

    }
}
<commit_msg>TODO notes<commit_after>use nom::multispace;
use std::str;

use common::{integer_literal, sql_identifier, Literal};
use column::Column;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ArithmeticOperator {
    Add,
    Subtract,
    Multiply,
    Divide,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ArithmeticBase {
    Column(Column),
    Scalar(Literal),
}

#[derive(Debug, Clone, PartialEq)]
pub struct ArithmeticExpression {
    op: ArithmeticOperator,
    left: ArithmeticBase,
    right: ArithmeticBase,
}

impl ArithmeticExpression {
    pub fn new(op: ArithmeticOperator, left: ArithmeticBase, right: ArithmeticBase) -> Self {
        Self {
            op: op,
            left: left,
            right: right,
        }
    }
}

/// Parse standard math operators.
/// TODO(malte): this doesn't currently observe operator precedence.
named!(pub arithmetic_operator<&[u8], ArithmeticOperator>,
    alt_complete!(
          map!(tag!("+"), |_| ArithmeticOperator::Add)
        | map!(tag!("-"), |_| ArithmeticOperator::Subtract)
        | map!(tag!("*"), |_| ArithmeticOperator::Multiply)
        | map!(tag!("/"), |_| ArithmeticOperator::Divide)
    )
);

/// Base case for nested arithmetic expressions: column name or literal.
named!(pub arithmetic_base<&[u8], ArithmeticBase>,
    alt_complete!(
          map!(integer_literal, |il| ArithmeticBase::Scalar(il))
        | map!(sql_identifier, |si| {
              let c = Column::from(str::from_utf8(si).unwrap());
              ArithmeticBase::Column(c)
          })
    )
);

/// Parse simple arithmetic expressions combining literals, and columns and literals.
/// TODO(malte): this doesn't currently support nested expressions.
named!(pub arithmetic_expression<&[u8], ArithmeticExpression>,
    complete!(chain!(
        left: arithmetic_base ~
        multispace? ~
        op: arithmetic_operator ~
        multispace? ~
        right: arithmetic_base,
        || {
            ArithmeticExpression {
                op: op,
                left: left,
                right: right
            }
        }
    ))
);

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

    #[test]
    fn it_parses_arithmetic_expressions() {
        use super::ArithmeticOperator::*;
        use super::ArithmeticBase::*;

        let lit_ae = ["5 + 42", "5+42", "5 * 42", "5 - 42", "5 / 42"];
        let col_lit_ae = ["foo+5", "foo + 5", "5 + foo"];

        let expected_lit_ae = [
            ArithmeticExpression::new(Add, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Add, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Multiply, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Subtract, Scalar(5.into()), Scalar(42.into())),
            ArithmeticExpression::new(Divide, Scalar(5.into()), Scalar(42.into())),
        ];
        let expected_col_lit_ae = [
            ArithmeticExpression::new(Add, Column("foo".into()), Scalar(5.into())),
            ArithmeticExpression::new(Add, Column("foo".into()), Scalar(5.into())),
            ArithmeticExpression::new(Add, Scalar(5.into()), Column("foo".into())),
        ];

        for (i, e) in lit_ae.iter().enumerate() {
            let res = arithmetic_expression(e.as_bytes());
            assert!(res.is_done());
            assert_eq!(res.unwrap().1, expected_lit_ae[i]);
        }

        for (i, e) in col_lit_ae.iter().enumerate() {
            let res = arithmetic_expression(e.as_bytes());
            assert!(res.is_done());
            assert_eq!(res.unwrap().1, expected_col_lit_ae[i]);
        }

    }
}
<|endoftext|>