<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 private::capability::ClientHook;
use private::units::*;
use message;
use Word;

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

pub type SegmentId = u32;

pub struct SegmentReader {
    pub arena : ArenaPtr,
    pub ptr : *const Word,
    pub size : WordCount32,
    pub read_limiter : ::std::rc::Rc<ReadLimiter>,
}

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 &&
            self.read_limiter.can_read((to as usize - from as usize) as u64 / BYTES_PER_WORD as u64);
    }
}

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,
               limiter : ::std::rc::Rc<ReadLimiter>,
               id : SegmentId,
               ptr : *mut Word,
               size : WordCount32) -> SegmentBuilder {
        SegmentBuilder {
            reader : SegmentReader {
                arena : ArenaPtr::Builder(arena),
                ptr : unsafe {::std::mem::transmute(ptr)},
                size : size,
                read_limiter: limiter,
            },
            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 {
        ((self.pos as usize - self.reader.ptr as usize) / BYTES_PER_WORD) 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 fn currently_allocated<'a>(&'a self) -> &'a [Word] {
        unsafe { ::std::slice::from_raw_parts(self.get_ptr_unchecked(0), self.current_size() as usize) }
    }
}

pub struct ReadLimiter {
    pub limit : ::std::cell::RefCell<u64>,
}

impl ReadLimiter {
    pub fn new(limit : u64) -> ReadLimiter {
        ReadLimiter { limit : ::std::cell::RefCell::new(limit) }
    }

    #[inline]
    pub fn can_read(&self, amount : u64) -> bool {
        let current = *self.limit.borrow();
        if amount > current {
            // TODO arena->reportReadLimitReached()
            return false;
        } else {
            *self.limit.borrow_mut() = current - amount;
            return true;
        }
    }
}

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 read_limiter : ::std::rc::Rc<ReadLimiter>,

    pub fail_fast : bool,
}

impl ReaderArena {
    pub fn new(segments : &[&[Word]], options : message::ReaderOptions) -> Box<ReaderArena> {
        assert!(segments.len() > 0);
        let limiter = ::std::rc::Rc::new(ReadLimiter::new(options.traversal_limit_in_words));
        let mut arena = Box::new(ReaderArena {
            segment0 : SegmentReader {
                arena : ArenaPtr::Null,
                ptr : unsafe { segments[0].get_unchecked(0) },
                size : segments[0].len() as u32,
                read_limiter : limiter.clone(),
            },
            more_segments : Vec::new(),
            cap_table : Vec::new(),
            read_limiter : limiter.clone(),
            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,
                    read_limiter : limiter.clone(),
                };
                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 segment0_for_output : &'static [Word],
    pub more_segments : Vec<Box<SegmentBuilder>>,
    pub for_output : Vec<&'static[Word]>,
    pub allocation_strategy : message::AllocationStrategy,
    pub owned_memory : Vec<(*mut Word, usize)>,
    pub next_size : u32,
    pub cap_table : Vec<Option<Box<ClientHook+Send>>>,
    pub dummy_limiter : ::std::rc::Rc<ReadLimiter>,
    pub fail_fast : bool,
}

impl Drop for BuilderArena {
    fn drop(&mut self) {
        for &(ptr, size) in self.owned_memory.iter() {
            unsafe {
                ::std::rt::heap::deallocate(::std::mem::transmute(ptr),
                                            BYTES_PER_WORD * size,
                                            BYTES_PER_WORD);
            }
        }
    }
}

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 limiter = ::std::rc::Rc::new(ReadLimiter::new(<u64 as ::std::num::Int>::max_value()));

        let (first_segment, num_words, owned_memory) : (*mut Word, u32, Vec<(*mut Word, usize)>) = unsafe {
            match first_segment {
                NumWords(n) => {
                    let ptr : *mut Word = ::std::mem::transmute(
                        ::std::rt::heap::allocate(BYTES_PER_WORD * n as usize,
                                                  ::std::mem::min_align_of::<Word>()));
                    if ptr.is_null() {panic!("could not allocate segment")}
                    ::std::ptr::write_bytes(ptr, 0, n as usize);
                    (ptr, n, vec![(ptr, n as usize)])
                }
                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,
                    read_limiter : limiter.clone()},
                id : 0,
                pos : first_segment,
            },
            segment0_for_output : &[],
            more_segments : Vec::new(),
            for_output : Vec::new(),
            allocation_strategy : allocation_strategy,
            owned_memory : owned_memory,
            next_size : num_words,
            cap_table : Vec::new(),
            dummy_limiter : limiter,
            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(::std::rt::heap::allocate(BYTES_PER_WORD * size as usize,
                                                            ::std::mem::min_align_of::<Word>())) };
        if new_words.is_null() { panic!("could not allocate a new segment.") }
        unsafe { ::std::ptr::write_bytes(new_words, 0, size as usize) };

        self.owned_memory.push((new_words, size as usize));

        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, self.dummy_limiter.clone(),
                                                               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<'a>(&'a mut self) -> &'a [&'a [Word]] {
        unsafe {
            if self.more_segments.len() == 0 {
                self.segment0_for_output = ::std::mem::transmute(self.segment0.currently_allocated());
                ::std::slice::ref_slice(&self.segment0_for_output)
            } else {
                self.for_output = Vec::new();
                self.for_output.push(::std::slice::from_raw_parts(self.segment0.reader.ptr,
                                                                  self.segment0.reader.size as usize));

                for seg in self.more_segments.iter() {
                    self.for_output.push(::std::slice::from_raw_parts(seg.reader.ptr,
                                                                      seg.current_size() as usize))
                }

                self.for_output.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>unsafe impl Send for ReaderArena<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 private::capability::ClientHook;
use private::units::*;
use message;
use Word;

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

pub type SegmentId = u32;

pub struct SegmentReader {
    pub arena : ArenaPtr,
    pub ptr : *const Word,
    pub size : WordCount32,
    pub read_limiter : ::std::rc::Rc<ReadLimiter>,
}

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 &&
            self.read_limiter.can_read((to as usize - from as usize) as u64 / BYTES_PER_WORD as u64);
    }
}

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,
               limiter : ::std::rc::Rc<ReadLimiter>,
               id : SegmentId,
               ptr : *mut Word,
               size : WordCount32) -> SegmentBuilder {
        SegmentBuilder {
            reader : SegmentReader {
                arena : ArenaPtr::Builder(arena),
                ptr : unsafe {::std::mem::transmute(ptr)},
                size : size,
                read_limiter: limiter,
            },
            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 {
        ((self.pos as usize - self.reader.ptr as usize) / BYTES_PER_WORD) 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 fn currently_allocated<'a>(&'a self) -> &'a [Word] {
        unsafe { ::std::slice::from_raw_parts(self.get_ptr_unchecked(0), self.current_size() as usize) }
    }
}

pub struct ReadLimiter {
    pub limit : ::std::cell::RefCell<u64>,
}

impl ReadLimiter {
    pub fn new(limit : u64) -> ReadLimiter {
        ReadLimiter { limit : ::std::cell::RefCell::new(limit) }
    }

    #[inline]
    pub fn can_read(&self, amount : u64) -> bool {
        let current = *self.limit.borrow();
        if amount > current {
            // TODO arena->reportReadLimitReached()
            return false;
        } else {
            *self.limit.borrow_mut() = current - amount;
            return true;
        }
    }
}

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 read_limiter : ::std::rc::Rc<ReadLimiter>,

    pub fail_fast : bool,
}

unsafe impl Send for ReaderArena {}

impl ReaderArena {
    pub fn new(segments : &[&[Word]], options : message::ReaderOptions) -> Box<ReaderArena> {
        assert!(segments.len() > 0);
        let limiter = ::std::rc::Rc::new(ReadLimiter::new(options.traversal_limit_in_words));
        let mut arena = Box::new(ReaderArena {
            segment0 : SegmentReader {
                arena : ArenaPtr::Null,
                ptr : unsafe { segments[0].get_unchecked(0) },
                size : segments[0].len() as u32,
                read_limiter : limiter.clone(),
            },
            more_segments : Vec::new(),
            cap_table : Vec::new(),
            read_limiter : limiter.clone(),
            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,
                    read_limiter : limiter.clone(),
                };
                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 segment0_for_output : &'static [Word],
    pub more_segments : Vec<Box<SegmentBuilder>>,
    pub for_output : Vec<&'static[Word]>,
    pub allocation_strategy : message::AllocationStrategy,
    pub owned_memory : Vec<(*mut Word, usize)>,
    pub next_size : u32,
    pub cap_table : Vec<Option<Box<ClientHook+Send>>>,
    pub dummy_limiter : ::std::rc::Rc<ReadLimiter>,
    pub fail_fast : bool,
}

impl Drop for BuilderArena {
    fn drop(&mut self) {
        for &(ptr, size) in self.owned_memory.iter() {
            unsafe {
                ::std::rt::heap::deallocate(::std::mem::transmute(ptr),
                                            BYTES_PER_WORD * size,
                                            BYTES_PER_WORD);
            }
        }
    }
}

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 limiter = ::std::rc::Rc::new(ReadLimiter::new(<u64 as ::std::num::Int>::max_value()));

        let (first_segment, num_words, owned_memory) : (*mut Word, u32, Vec<(*mut Word, usize)>) = unsafe {
            match first_segment {
                NumWords(n) => {
                    let ptr : *mut Word = ::std::mem::transmute(
                        ::std::rt::heap::allocate(BYTES_PER_WORD * n as usize,
                                                  ::std::mem::min_align_of::<Word>()));
                    if ptr.is_null() {panic!("could not allocate segment")}
                    ::std::ptr::write_bytes(ptr, 0, n as usize);
                    (ptr, n, vec![(ptr, n as usize)])
                }
                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,
                    read_limiter : limiter.clone()},
                id : 0,
                pos : first_segment,
            },
            segment0_for_output : &[],
            more_segments : Vec::new(),
            for_output : Vec::new(),
            allocation_strategy : allocation_strategy,
            owned_memory : owned_memory,
            next_size : num_words,
            cap_table : Vec::new(),
            dummy_limiter : limiter,
            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(::std::rt::heap::allocate(BYTES_PER_WORD * size as usize,
                                                            ::std::mem::min_align_of::<Word>())) };
        if new_words.is_null() { panic!("could not allocate a new segment.") }
        unsafe { ::std::ptr::write_bytes(new_words, 0, size as usize) };

        self.owned_memory.push((new_words, size as usize));

        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, self.dummy_limiter.clone(),
                                                               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<'a>(&'a mut self) -> &'a [&'a [Word]] {
        unsafe {
            if self.more_segments.len() == 0 {
                self.segment0_for_output = ::std::mem::transmute(self.segment0.currently_allocated());
                ::std::slice::ref_slice(&self.segment0_for_output)
            } else {
                self.for_output = Vec::new();
                self.for_output.push(::std::slice::from_raw_parts(self.segment0.reader.ptr,
                                                                  self.segment0.reader.size as usize));

                for seg in self.more_segments.iter() {
                    self.for_output.push(::std::slice::from_raw_parts(seg.reader.ptr,
                                                                      seg.current_size() as usize))
                }

                self.for_output.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><commit_msg>type simplification (part 1)<commit_after><|endoftext|>


<commit_before>use std::fmt;

use base64::{encode as b64encode};

use hyper;
use hyper::{Client};
use hyper::header::{Header, HeaderFormat};

use serde_json;

use B2Error;
use B2AuthHeader;

/// Contains the backblaze id and key needed to authorize access to the backblaze b2 api.
/// This struct derives [Deserialize][1], so a simple way to read this from a file would be:
///
/// ```rust,no_run
///extern crate serde;
///extern crate serde_json;
///use std::fs::File;
///
///# extern crate backblaze_b2;
///# use backblaze_b2::raw::authorize::B2Credentials;
///#
///# fn main() {
///serde_json::from_reader::<_,B2Credentials>(File::open("credentials.txt").unwrap()).unwrap();
///# }
/// ```
///
///  [1]: ../../../serde/trait.Deserialize.html
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct B2Credentials {
    pub id: String,
    pub key: String
}
impl B2Credentials {
    fn id_key(&self) -> String {
        format!("{}:{}", self.id, self.key)
    }
    /// This function returns the value of the Authorization header needed to perform a
    /// b2_authorize_account api call.
    pub fn auth_string(&self) -> String {
        format!("Basic {}", b64encode(&self.id_key()))
    }
    /// This function performs a [b2_authorize_account][1] api call to the backblaze api and returns an
    /// authorization token.
    ///
    /// # Errors
    /// This function returns a [`B2Error`] in case something goes wrong. Besides the standard
    /// non-authorization errors, this function can fail with [`is_credentials_issue`].
    ///
    ///  [1]: https://www.backblaze.com/b2/docs/b2_authorize_account.html
    ///  [`is_credentials_issue`]: ../../enum.B2Error.html#method.is_credentials_issue
    ///  [`B2Error`]: ../../enum.B2Error.html
    pub fn authorize<'a>(&'a self, client: &Client) -> Result<B2Authorization<'a>,B2Error> {
        let resp = try!(client.get("https://api.backblazeb2.com/b2api/v1/b2_authorize_account")
            .header(self.clone())
            .send());
        if resp.status != hyper::status::StatusCode::Ok {
            Err(B2Error::from_response(resp))
        } else {
            Ok(B2Authorization::from(self, try!(serde_json::from_reader(resp))))
        }
    }
}
impl HeaderFormat for B2Credentials {
    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.auth_string().as_str())
    }
}
impl Header for B2Credentials {
    fn header_name() -> &'static str {
        "Authorization"
    }
#[allow(unused_variables)]
    fn parse_header(raw: &[Vec<u8>]) -> hyper::Result<B2Credentials> {
        panic!("we are not the b2 server");
    }
}
#[derive(Serialize,Deserialize)]
#[serde(rename_all = "camelCase")]
struct B2AuthResponse {
    authorization_token: String,
    api_url: String,
    download_url: String,
    recommended_part_size: usize,
    absolute_minimum_part_size: usize
}
/// This struct contains the needed authorization to perform any b2 api call. It is typically
/// created using a [`B2Credentials`].
///
///  [`B2Credentials`]: struct.B2Credentials.html
#[derive(Debug)]
pub struct B2Authorization<'a> {
    pub credentials: &'a B2Credentials,
    pub authorization_token: String,
    pub api_url: String,
    pub download_url: String,
    pub recommended_part_size: usize,
    pub absolute_minimum_part_size: usize
}
impl<'a> B2Authorization<'a> {
    fn from(credentials: &'a B2Credentials, resp: B2AuthResponse) -> B2Authorization<'a> {
        B2Authorization {
            credentials: credentials,
            authorization_token: resp.authorization_token,
            api_url: resp.api_url,
            download_url: resp.download_url,
            recommended_part_size: resp.recommended_part_size,
            absolute_minimum_part_size: resp.absolute_minimum_part_size
        }
    }
    /// Returns a hyper header that correctly authorizes an api call to backblaze.
    pub fn auth_header(&self) -> B2AuthHeader {
        B2AuthHeader(self.authorization_token.clone())
    }
}

<commit_msg>update links in authorize.rs doc<commit_after>//! This module defines various methods and structs used for authenticating on the B2 server.
//!
//! Authentication is usually performed by calling the [`authorize`] method on the
//! [`B2Credentials`] struct, which returns a [`B2Authorization`].
//!
//!  [`authorize`]: struct.B2Credentials.html#method.authorize
//!  [`B2Credentials`]: struct.B2Credentials.html
//!  [`B2Authorization`]: struct.B2Authorization.html

use std::fmt;

use base64::{encode as b64encode};

use hyper;
use hyper::{Client};
use hyper::header::{Header, HeaderFormat};

use serde_json;

use B2Error;
use B2AuthHeader;

/// Contains the backblaze id and key needed to authorize access to the backblaze b2 api.
/// This struct derives [Deserialize][1], so a simple way to read this from a file would be:
///
/// ```rust,no_run
///extern crate serde;
///extern crate serde_json;
///use std::fs::File;
///
///# extern crate backblaze_b2;
///# use backblaze_b2::raw::authorize::B2Credentials;
///#
///# fn main() {
///serde_json::from_reader::<_,B2Credentials>(File::open("credentials.txt").unwrap()).unwrap();
///# }
/// ```
///
///  [1]: ../../../serde/trait.Deserialize.html
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct B2Credentials {
    pub id: String,
    pub key: String
}
impl B2Credentials {
    fn id_key(&self) -> String {
        format!("{}:{}", self.id, self.key)
    }
    /// This function returns the value of the Authorization header needed to perform a
    /// b2_authorize_account api call.
    pub fn auth_string(&self) -> String {
        format!("Basic {}", b64encode(&self.id_key()))
    }
    /// This function performs a [b2_authorize_account][1] api call to the backblaze api and returns an
    /// authorization token.
    ///
    /// # Errors
    /// This function returns a [`B2Error`] in case something goes wrong. Besides the standard
    /// non-authorization errors, this function can fail with [`is_credentials_issue`].
    ///
    ///  [1]: https://www.backblaze.com/b2/docs/b2_authorize_account.html
    ///  [`is_credentials_issue`]: ../../enum.B2Error.html#method.is_credentials_issue
    ///  [`B2Error`]: ../../enum.B2Error.html
    pub fn authorize<'a>(&'a self, client: &Client) -> Result<B2Authorization<'a>,B2Error> {
        let resp = try!(client.get("https://api.backblazeb2.com/b2api/v1/b2_authorize_account")
            .header(self.clone())
            .send());
        if resp.status != hyper::status::StatusCode::Ok {
            Err(B2Error::from_response(resp))
        } else {
            Ok(B2Authorization::from(self, try!(serde_json::from_reader(resp))))
        }
    }
}
impl HeaderFormat for B2Credentials {
    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.auth_string().as_str())
    }
}
impl Header for B2Credentials {
    fn header_name() -> &'static str {
        "Authorization"
    }
#[allow(unused_variables)]
    fn parse_header(raw: &[Vec<u8>]) -> hyper::Result<B2Credentials> {
        panic!("we are not the b2 server");
    }
}
#[derive(Serialize,Deserialize)]
#[serde(rename_all = "camelCase")]
struct B2AuthResponse {
    authorization_token: String,
    api_url: String,
    download_url: String,
    recommended_part_size: usize,
    absolute_minimum_part_size: usize
}
/// This struct contains the needed authorization to perform any b2 api call. It is typically
/// created using the [`authorize`] method on [`B2Credentials`].
///
///  [`authorize`]: struct.B2Credentials.html#method.authorize
///  [`B2Credentials`]: struct.B2Credentials.html
#[derive(Debug)]
pub struct B2Authorization<'a> {
    pub credentials: &'a B2Credentials,
    pub authorization_token: String,
    pub api_url: String,
    pub download_url: String,
    pub recommended_part_size: usize,
    pub absolute_minimum_part_size: usize
}
impl<'a> B2Authorization<'a> {
    fn from(credentials: &'a B2Credentials, resp: B2AuthResponse) -> B2Authorization<'a> {
        B2Authorization {
            credentials: credentials,
            authorization_token: resp.authorization_token,
            api_url: resp.api_url,
            download_url: resp.download_url,
            recommended_part_size: resp.recommended_part_size,
            absolute_minimum_part_size: resp.absolute_minimum_part_size
        }
    }
    /// Returns a hyper header that correctly authorizes an api call to backblaze.
    pub fn auth_header(&self) -> B2AuthHeader {
        B2AuthHeader(self.authorization_token.clone())
    }
}

<|endoftext|>


<commit_before>//! Postfix completion for `format`-like strings.
//!
//! `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`.
//!
//! The following postfix snippets are available:
//!
//! - `format` -> `format!(...)`
//! - `println` -> `println!(...)`
//! - `log`:
//!   + `logd` -> `log::debug!(...)`
//!   + `logt` -> `log::trace!(...)`
//!   + `logi` -> `log::info!(...)`
//!   + `logw` -> `log::warn!(...)`
//!   + `loge` -> `log::error!(...)`

use super::postfix_snippet;
use crate::completion::{
    completion_config::SnippetCap, completion_context::CompletionContext,
    completion_item::Completions,
};
use syntax::ast;

pub(super) fn add_format_like_completions(
    acc: &mut Completions,
    ctx: &CompletionContext,
    dot_receiver: &ast::Expr,
    cap: SnippetCap,
    receiver_text: &str,
) {
    if !is_string_literal(receiver_text) {
        // It's not a string literal, do not parse input.
        return;
    }

    let input = &receiver_text[1..receiver_text.len() - 1];

    let mut parser = FormatStrParser::new(input);

    if parser.parse().is_ok() {
        for kind in PostfixKind::all_suggestions() {
            let snippet = parser.into_suggestion(*kind);
            let (label, detail) = kind.into_description();

            postfix_snippet(ctx, cap, &dot_receiver, label, detail, &snippet).add_to(acc);
        }
    }
}

/// Checks whether provided item is a string literal.
fn is_string_literal(item: &str) -> bool {
    if item.len() < 2 {
        return false;
    }
    item.starts_with("\"") && item.ends_with("\"")
}

/// Parser for a format-like string. It is more allowing in terms of string contents,
/// as we expect variable placeholders to be filled with expressions.
#[derive(Debug)]
pub struct FormatStrParser {
    input: String,
    output: String,
    extracted_expressions: Vec<String>,
    state: State,
    parsed: bool,
}

#[derive(Debug, Clone, Copy)]
pub enum PostfixKind {
    Format,
    Panic,
    Println,
    LogDebug,
    LogTrace,
    LogInfo,
    LogWarn,
    LogError,
}

impl PostfixKind {
    pub fn all_suggestions() -> &'static [PostfixKind] {
        &[
            Self::Format,
            Self::Panic,
            Self::Println,
            Self::LogDebug,
            Self::LogTrace,
            Self::LogInfo,
            Self::LogWarn,
            Self::LogError,
        ]
    }

    pub fn into_description(self) -> (&'static str, &'static str) {
        match self {
            Self::Format => ("fmt", "format!"),
            Self::Panic => ("panic", "panic!"),
            Self::Println => ("println", "println!"),
            Self::LogDebug => ("logd", "log::debug!"),
            Self::LogTrace => ("logt", "log::trace!"),
            Self::LogInfo => ("logi", "log::info!"),
            Self::LogWarn => ("logw", "log::warn!"),
            Self::LogError => ("loge", "log::error!"),
        }
    }

    pub fn into_macro_name(self) -> &'static str {
        match self {
            Self::Format => "format!",
            Self::Panic => "panic!",
            Self::Println => "println!",
            Self::LogDebug => "log::debug!",
            Self::LogTrace => "log::trace!",
            Self::LogInfo => "log::info!",
            Self::LogWarn => "log::warn!",
            Self::LogError => "log::error!",
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
enum State {
    NotExpr,
    MaybeExpr,
    Expr,
    MaybeIncorrect,
    FormatOpts,
}

impl FormatStrParser {
    pub fn new(input: impl Into<String>) -> Self {
        Self {
            input: input.into(),
            output: String::new(),
            extracted_expressions: Vec::new(),
            state: State::NotExpr,
            parsed: false,
        }
    }

    pub fn parse(&mut self) -> Result<(), ()> {
        let mut current_expr = String::new();

        let mut placeholder_id = 1;

        // Count of open braces inside of an expression.
        // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
        // "{MyStruct { val_a: 0, val_b: 1 }}".
        let mut inexpr_open_count = 0;

        for chr in self.input.chars() {
            match (self.state, chr) {
                (State::NotExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::MaybeExpr;
                }
                (State::NotExpr, '}') => {
                    self.output.push(chr);
                    self.state = State::MaybeIncorrect;
                }
                (State::NotExpr, _) => {
                    self.output.push(chr);
                }
                (State::MaybeIncorrect, '}') => {
                    // It's okay, we met "}}".
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeIncorrect, _) => {
                    // Error in the string.
                    return Err(());
                }
                (State::MaybeExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, '}') => {
                    // This is an empty sequence '{}'. Replace it with placeholder.
                    self.output.push(chr);
                    self.extracted_expressions.push(format!("${}", placeholder_id));
                    placeholder_id += 1;
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, _) => {
                    current_expr.push(chr);
                    self.state = State::Expr;
                }
                (State::Expr, '}') => {
                    if inexpr_open_count == 0 {
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::NotExpr;
                    } else {
                        // We're closing one brace met before inside of the expression.
                        current_expr.push(chr);
                        inexpr_open_count -= 1;
                    }
                }
                (State::Expr, ':') => {
                    if inexpr_open_count == 0 {
                        // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}"
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::FormatOpts;
                    } else {
                        // We're inside of braced expression, assume that it's a struct field name/value delimeter.
                        current_expr.push(chr);
                    }
                }
                (State::Expr, '{') => {
                    current_expr.push(chr);
                    inexpr_open_count += 1;
                }
                (State::Expr, _) => {
                    current_expr.push(chr);
                }
                (State::FormatOpts, '}') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::FormatOpts, _) => {
                    self.output.push(chr);
                }
            }
        }

        if self.state != State::NotExpr {
            return Err(());
        }

        self.parsed = true;
        Ok(())
    }

    pub fn into_suggestion(&self, kind: PostfixKind) -> String {
        assert!(self.parsed, "Attempt to get a suggestion from not parsed expression");

        let mut output = format!(r#"{}("{}""#, kind.into_macro_name(), self.output);
        for expr in &self.extracted_expressions {
            output += ", ";
            output += expr;
        }
        output.push(')');

        output
    }
}

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

    #[test]
    fn format_str_parser() {
        let test_vector = &[
            ("no expressions", Some(("no expressions", vec![]))),
            ("{expr} is {2 + 2}", Some(("{} is {}", vec!["expr", "2 + 2"]))),
            ("{expr:?}", Some(("{:?}", vec!["expr"]))),
            ("{malformed", None),
            ("malformed}", None),
            ("{{correct", Some(("{{correct", vec![]))),
            ("correct}}", Some(("correct}}", vec![]))),
            ("{correct}}}", Some(("{}}}", vec!["correct"]))),
            ("{correct}}}}}", Some(("{}}}}}", vec!["correct"]))),
            ("{incorrect}}", None),
            ("placeholders {} {}", Some(("placeholders {} {}", vec!["$1", "$2"]))),
            ("mixed {} {2 + 2} {}", Some(("mixed {} {} {}", vec!["$1", "2 + 2", "$2"]))),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }}",
                Some(("{}", vec!["SomeStruct { val_a: 0, val_b: 1 }"])),
            ),
            ("{expr:?} is {2.32f64:.5}", Some(("{:?} is {:.5}", vec!["expr", "2.32f64"]))),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }:?}",
                Some(("{:?}", vec!["SomeStruct { val_a: 0, val_b: 1 }"])),
            ),
            ("{     2 + 2        }", Some(("{}", vec!["2 + 2"]))),
        ];

        for (input, output) in test_vector {
            let mut parser = FormatStrParser::new(*input);
            let outcome = parser.parse();

            if let Some((result_str, result_args)) = output {
                assert!(
                    outcome.is_ok(),
                    "Outcome is error for input: {}, but the expected outcome is {:?}",
                    input,
                    output
                );
                assert_eq!(parser.output, *result_str);
                assert_eq!(&parser.extracted_expressions, result_args);
            } else {
                assert!(
                    outcome.is_err(),
                    "Outcome is OK for input: {}, but the expected outcome is error",
                    input
                );
            }
        }
    }

    #[test]
    fn test_into_suggestion() {
        let test_vector = &[
            (PostfixKind::Println, "{}", r#"println!("{}", $1)"#),
            (
                PostfixKind::LogInfo,
                "{} {expr} {} {2 + 2}",
                r#"log::info!("{} {} {} {}", $1, expr, $2, 2 + 2)"#,
            ),
            (PostfixKind::Format, "{expr:?}", r#"format!("{:?}", expr)"#),
        ];

        for (kind, input, output) in test_vector {
            let mut parser = FormatStrParser::new(*input);
            parser.parse().expect("Parsing must succeed");

            assert_eq!(&parser.into_suggestion(*kind), output);
        }
    }
}
<commit_msg>Add missing entry to doc-comment<commit_after>//! Postfix completion for `format`-like strings.
//!
//! `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`.
//!
//! The following postfix snippets are available:
//!
//! - `format` -> `format!(...)`
//! - `panic` -> `panic!(...)`
//! - `println` -> `println!(...)`
//! - `log`:
//!   + `logd` -> `log::debug!(...)`
//!   + `logt` -> `log::trace!(...)`
//!   + `logi` -> `log::info!(...)`
//!   + `logw` -> `log::warn!(...)`
//!   + `loge` -> `log::error!(...)`

use super::postfix_snippet;
use crate::completion::{
    completion_config::SnippetCap, completion_context::CompletionContext,
    completion_item::Completions,
};
use syntax::ast;

pub(super) fn add_format_like_completions(
    acc: &mut Completions,
    ctx: &CompletionContext,
    dot_receiver: &ast::Expr,
    cap: SnippetCap,
    receiver_text: &str,
) {
    if !is_string_literal(receiver_text) {
        // It's not a string literal, do not parse input.
        return;
    }

    let input = &receiver_text[1..receiver_text.len() - 1];

    let mut parser = FormatStrParser::new(input);

    if parser.parse().is_ok() {
        for kind in PostfixKind::all_suggestions() {
            let snippet = parser.into_suggestion(*kind);
            let (label, detail) = kind.into_description();

            postfix_snippet(ctx, cap, &dot_receiver, label, detail, &snippet).add_to(acc);
        }
    }
}

/// Checks whether provided item is a string literal.
fn is_string_literal(item: &str) -> bool {
    if item.len() < 2 {
        return false;
    }
    item.starts_with("\"") && item.ends_with("\"")
}

/// Parser for a format-like string. It is more allowing in terms of string contents,
/// as we expect variable placeholders to be filled with expressions.
#[derive(Debug)]
pub struct FormatStrParser {
    input: String,
    output: String,
    extracted_expressions: Vec<String>,
    state: State,
    parsed: bool,
}

#[derive(Debug, Clone, Copy)]
pub enum PostfixKind {
    Format,
    Panic,
    Println,
    LogDebug,
    LogTrace,
    LogInfo,
    LogWarn,
    LogError,
}

impl PostfixKind {
    pub fn all_suggestions() -> &'static [PostfixKind] {
        &[
            Self::Format,
            Self::Panic,
            Self::Println,
            Self::LogDebug,
            Self::LogTrace,
            Self::LogInfo,
            Self::LogWarn,
            Self::LogError,
        ]
    }

    pub fn into_description(self) -> (&'static str, &'static str) {
        match self {
            Self::Format => ("fmt", "format!"),
            Self::Panic => ("panic", "panic!"),
            Self::Println => ("println", "println!"),
            Self::LogDebug => ("logd", "log::debug!"),
            Self::LogTrace => ("logt", "log::trace!"),
            Self::LogInfo => ("logi", "log::info!"),
            Self::LogWarn => ("logw", "log::warn!"),
            Self::LogError => ("loge", "log::error!"),
        }
    }

    pub fn into_macro_name(self) -> &'static str {
        match self {
            Self::Format => "format!",
            Self::Panic => "panic!",
            Self::Println => "println!",
            Self::LogDebug => "log::debug!",
            Self::LogTrace => "log::trace!",
            Self::LogInfo => "log::info!",
            Self::LogWarn => "log::warn!",
            Self::LogError => "log::error!",
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
enum State {
    NotExpr,
    MaybeExpr,
    Expr,
    MaybeIncorrect,
    FormatOpts,
}

impl FormatStrParser {
    pub fn new(input: impl Into<String>) -> Self {
        Self {
            input: input.into(),
            output: String::new(),
            extracted_expressions: Vec::new(),
            state: State::NotExpr,
            parsed: false,
        }
    }

    pub fn parse(&mut self) -> Result<(), ()> {
        let mut current_expr = String::new();

        let mut placeholder_id = 1;

        // Count of open braces inside of an expression.
        // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
        // "{MyStruct { val_a: 0, val_b: 1 }}".
        let mut inexpr_open_count = 0;

        for chr in self.input.chars() {
            match (self.state, chr) {
                (State::NotExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::MaybeExpr;
                }
                (State::NotExpr, '}') => {
                    self.output.push(chr);
                    self.state = State::MaybeIncorrect;
                }
                (State::NotExpr, _) => {
                    self.output.push(chr);
                }
                (State::MaybeIncorrect, '}') => {
                    // It's okay, we met "}}".
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeIncorrect, _) => {
                    // Error in the string.
                    return Err(());
                }
                (State::MaybeExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, '}') => {
                    // This is an empty sequence '{}'. Replace it with placeholder.
                    self.output.push(chr);
                    self.extracted_expressions.push(format!("${}", placeholder_id));
                    placeholder_id += 1;
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, _) => {
                    current_expr.push(chr);
                    self.state = State::Expr;
                }
                (State::Expr, '}') => {
                    if inexpr_open_count == 0 {
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::NotExpr;
                    } else {
                        // We're closing one brace met before inside of the expression.
                        current_expr.push(chr);
                        inexpr_open_count -= 1;
                    }
                }
                (State::Expr, ':') => {
                    if inexpr_open_count == 0 {
                        // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}"
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::FormatOpts;
                    } else {
                        // We're inside of braced expression, assume that it's a struct field name/value delimeter.
                        current_expr.push(chr);
                    }
                }
                (State::Expr, '{') => {
                    current_expr.push(chr);
                    inexpr_open_count += 1;
                }
                (State::Expr, _) => {
                    current_expr.push(chr);
                }
                (State::FormatOpts, '}') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::FormatOpts, _) => {
                    self.output.push(chr);
                }
            }
        }

        if self.state != State::NotExpr {
            return Err(());
        }

        self.parsed = true;
        Ok(())
    }

    pub fn into_suggestion(&self, kind: PostfixKind) -> String {
        assert!(self.parsed, "Attempt to get a suggestion from not parsed expression");

        let mut output = format!(r#"{}("{}""#, kind.into_macro_name(), self.output);
        for expr in &self.extracted_expressions {
            output += ", ";
            output += expr;
        }
        output.push(')');

        output
    }
}

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

    #[test]
    fn format_str_parser() {
        let test_vector = &[
            ("no expressions", Some(("no expressions", vec![]))),
            ("{expr} is {2 + 2}", Some(("{} is {}", vec!["expr", "2 + 2"]))),
            ("{expr:?}", Some(("{:?}", vec!["expr"]))),
            ("{malformed", None),
            ("malformed}", None),
            ("{{correct", Some(("{{correct", vec![]))),
            ("correct}}", Some(("correct}}", vec![]))),
            ("{correct}}}", Some(("{}}}", vec!["correct"]))),
            ("{correct}}}}}", Some(("{}}}}}", vec!["correct"]))),
            ("{incorrect}}", None),
            ("placeholders {} {}", Some(("placeholders {} {}", vec!["$1", "$2"]))),
            ("mixed {} {2 + 2} {}", Some(("mixed {} {} {}", vec!["$1", "2 + 2", "$2"]))),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }}",
                Some(("{}", vec!["SomeStruct { val_a: 0, val_b: 1 }"])),
            ),
            ("{expr:?} is {2.32f64:.5}", Some(("{:?} is {:.5}", vec!["expr", "2.32f64"]))),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }:?}",
                Some(("{:?}", vec!["SomeStruct { val_a: 0, val_b: 1 }"])),
            ),
            ("{     2 + 2        }", Some(("{}", vec!["2 + 2"]))),
        ];

        for (input, output) in test_vector {
            let mut parser = FormatStrParser::new(*input);
            let outcome = parser.parse();

            if let Some((result_str, result_args)) = output {
                assert!(
                    outcome.is_ok(),
                    "Outcome is error for input: {}, but the expected outcome is {:?}",
                    input,
                    output
                );
                assert_eq!(parser.output, *result_str);
                assert_eq!(&parser.extracted_expressions, result_args);
            } else {
                assert!(
                    outcome.is_err(),
                    "Outcome is OK for input: {}, but the expected outcome is error",
                    input
                );
            }
        }
    }

    #[test]
    fn test_into_suggestion() {
        let test_vector = &[
            (PostfixKind::Println, "{}", r#"println!("{}", $1)"#),
            (
                PostfixKind::LogInfo,
                "{} {expr} {} {2 + 2}",
                r#"log::info!("{} {} {} {}", $1, expr, $2, 2 + 2)"#,
            ),
            (PostfixKind::Format, "{expr:?}", r#"format!("{:?}", expr)"#),
        ];

        for (kind, input, output) in test_vector {
            let mut parser = FormatStrParser::new(*input);
            parser.parse().expect("Parsing must succeed");

            assert_eq!(&parser.into_suggestion(*kind), output);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Refactor: Array-Brackets removal into fn<commit_after><|endoftext|>


<commit_before>use failure::format_err;
use rusqlite::types::ToSql;
use rusqlite::Transaction;

use crate::db;
use crate::db::migrations::Migration;
use crate::errors::*;

pub struct MigrationReposJiras {}

impl Migration for MigrationReposJiras {
    fn run(&self, tx: &Transaction) -> Result<()> {
        let mut stmt = tx.prepare(r#"SELECT * FROM repos"#)?;
        let cols = db::Columns::from_stmt(&stmt)?;
        let mut rows = stmt.query(rusqlite::NO_PARAMS)?;

        while let Ok(Some(row)) = rows.next() {
            let id = cols.get::<i32>(row, "id")?;
            let jiras = db::to_string_vec(cols.get(row, "jira_projects")?);
            let version_script = cols.get::<String>(row, "version_script")?;

            for jira in &jiras {
                tx.execute(
                    r#"INSERT INTO repos_jiras (repo_id, jira, version_script, release_branch_pattern, channel)
                    VALUES (?1, ?2, ?3, '', '')"#,
                    &[
                        &id,
                        jira as &dyn ToSql,
                        &version_script,
                    ],
                )
                .map_err(|e| format_err!("Error inserting jira repo {} - {}: {}", id, jira, e))?;
            }
        }

        Ok(())
    }
}
<commit_msg>Fix column name (#262)<commit_after>use failure::format_err;
use rusqlite::types::ToSql;
use rusqlite::Transaction;

use crate::db;
use crate::db::migrations::Migration;
use crate::errors::*;

pub struct MigrationReposJiras {}

impl Migration for MigrationReposJiras {
    fn run(&self, tx: &Transaction) -> Result<()> {
        let mut stmt = tx.prepare(r#"SELECT * FROM repos"#)?;
        let cols = db::Columns::from_stmt(&stmt)?;
        let mut rows = stmt.query(rusqlite::NO_PARAMS)?;

        while let Ok(Some(row)) = rows.next() {
            let id = cols.get::<i32>(row, "id")?;
            let jiras = db::to_string_vec(cols.get(row, "jira_projects")?);
            let version_script = cols.get::<String>(row, "version_script")?;

            for jira in &jiras {
                tx.execute(
                    r#"INSERT INTO repos_jiras (repo_id, jira, version_script, release_branch_regex, channel)
                    VALUES (?1, ?2, ?3, '', '')"#,
                    &[
                        &id,
                        jira as &dyn ToSql,
                        &version_script,
                    ],
                )
                .map_err(|e| format_err!("Error inserting jira repo {} - {}: {}", id, jira, e))?;
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::hash:: { Hash, Hasher };
use std::cmp:: { Eq, PartialEq };
use std::fmt:: { Display, Formatter, Result };
use std::ops::AddAssign;
use std::collections::hash_map:: { Iter };
use std::convert::AsRef;
use lcov_parser:: { BranchData };
use result::summary:: { LineNumber, AggregateResult, Summary, ExecutionCount };
use result::summary::counter:: { HitFoundCounter, FoundCounter, HitCounter };

/// Units of the branch
///
/// # Examples
///
/// ```
/// use lcov_merge::BranchUnit;
///
/// let branch1 = BranchUnit::new(1, 1);
/// let branch2 = BranchUnit::new(1, 1);
///
/// assert!(branch1 == branch2);
///
/// let not_eq_branch1 = BranchUnit::new(1, 1);
/// let not_eq_branch2 = BranchUnit::new(1, 2);
///
/// assert!(not_eq_branch1 != not_eq_branch2);
/// ```
#[derive(Debug, Eq, Clone)]
pub struct BranchUnit(u32, u32);

impl BranchUnit {
    pub fn new(block: u32, branch: u32) -> BranchUnit {
        BranchUnit(block, branch)
    }
    pub fn block(&self) -> u32 {
        self.0
    }
    pub fn branch(&self) -> u32 {
        self.1
    }
}

impl PartialEq for BranchUnit {
    fn eq(&self, other: &Self) -> bool {
        self.0 == other.0 && self.1 == other.1
    }
}

impl Hash for BranchUnit {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.hash(state);
        self.1.hash(state);
    }
}

impl Display for BranchUnit {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}-{}", self.0, self.1)
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct BranchBlocks {
    blocks: AggregateResult<BranchUnit, ExecutionCount>
}

impl BranchBlocks {
    pub fn new() -> Self {
        BranchBlocks {
            blocks: AggregateResult::new()
        }
    }
}

impl AsRef<AggregateResult<BranchUnit, ExecutionCount>> for BranchBlocks {
    fn as_ref(&self) -> &AggregateResult<BranchUnit, ExecutionCount> {
        &self.blocks
    }
}

impl Summary<BranchUnit, ExecutionCount> for BranchBlocks {
    fn iter(&self) -> Iter<BranchUnit, ExecutionCount> {
        self.blocks.iter()
    }
    fn contains_key(&self, key: &BranchUnit) -> bool {
        self.blocks.contains_key(key)
    }
    fn get(&self, key: &BranchUnit) -> Option<&ExecutionCount> {
        self.blocks.get(key)
    }
}

impl HitCounter for BranchBlocks {
    fn hit_count(&self) -> usize {
        self.iter()
            .filter(|&(_, taken)| *taken > 0)
            .count()
    }
}

impl FoundCounter for BranchBlocks {
    fn found_count(&self) -> usize {
        self.blocks.len()
    }
}

impl HitFoundCounter for BranchBlocks {}

impl AddAssign for BranchBlocks {
    fn add_assign(&mut self, other: BranchBlocks) {
        self.blocks += other.as_ref();
    }
}

impl<'a> AddAssign<&'a BranchData> for BranchBlocks {
    fn add_assign(&mut self, data: &'a BranchData) {
        let unit = BranchUnit::new(data.block, data.branch);
        let mut block_count = self.blocks.entry(unit)
            .or_insert(0);
        *block_count += data.taken;
    }
}

impl<'a> AddAssign<&'a BranchBlocks> for BranchBlocks {
    fn add_assign(&mut self, other: &'a BranchBlocks) {
        self.blocks += other.as_ref();
    }
}

#[derive(Debug, Clone)]
pub struct Branches {
    branches: AggregateResult<LineNumber, BranchBlocks>
}

impl Branches {
    pub fn new() -> Self {
        Branches {
            branches: AggregateResult::new()
        }
    }
}

impl AsRef<AggregateResult<LineNumber, BranchBlocks>> for Branches {
    fn as_ref(&self) -> &AggregateResult<LineNumber, BranchBlocks> {
        &self.branches
    }
}

impl HitCounter for Branches {
    fn hit_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.hit_count() )
            .fold(0, |p, n| p + n)
    }
}

impl FoundCounter for Branches {
    fn found_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.found_count() )
            .fold(0, |p, n| p + n)
    }
}

impl HitFoundCounter for Branches {}

impl Summary<LineNumber, BranchBlocks> for Branches {
    fn iter(&self) -> Iter<LineNumber, BranchBlocks> {
        self.branches.iter()
    }
    fn contains_key(&self, key: &LineNumber) -> bool {
        self.branches.contains_key(key)
    }
    fn get(&self, key: &LineNumber) -> Option<&BranchBlocks> {
        self.branches.get(key)
    }
}

impl<'a> AddAssign<&'a Branches> for Branches {
    fn add_assign(&mut self, other: &'a Branches) {
        self.branches += other.as_ref();
    }
}

impl<'a> AddAssign<&'a BranchData> for Branches {
    fn add_assign(&mut self, other: &'a BranchData) {
        let mut blocks = self.branches.entry(other.line)
            .or_insert(BranchBlocks::new());
        *blocks += other;
    }
}

#[cfg(test)]
mod tests {
    use std::collections:: { HashMap };
    use lcov_parser:: { BranchData };
    use result::branch:: { BranchUnit, Branches, BranchBlocks };
    use result::summary:: { Summary };
    use result::summary::counter:: { FoundCounter, HitCounter };

    #[test]
    fn branch_unit() {
        let branch1 = BranchUnit(1, 1);
        let branch2 = BranchUnit(1, 2);

        assert!(branch1 != branch2);

        let same_branch1 = BranchUnit(1, 1);
        let same_branch2 = BranchUnit(1, 1);

        assert_eq!(same_branch1, same_branch2);
    }

    #[test]
    fn branch_unit_as_hash_key() {
        let mut container = HashMap::new();
        container.insert(BranchUnit(1, 1), 1);

        assert!( container.contains_key(&BranchUnit(1, 1)) );
    }

    #[test]
    fn add_branch_data() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches += b1;
        branches += b2;

        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&2));
    }

    #[test]
    fn append_branches() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches += b1;
        branches += b2;

        let cloned_branches = branches.clone();

        branches += &cloned_branches;

        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&4));
    }

    #[test]
    fn branch_blocks_hit_count_and_found_count() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 2, taken: 0 };

        branches += b1;
        branches += b2;

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }

    #[test]
    fn branches_hit_count_and_found_count() {
        let mut branches = Branches::new();
        branches += &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        branches += &BranchData { line: 1, block: 0, branch: 2, taken: 0 };

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }
}
<commit_msg>impl Ord, PartialOrd<commit_after>use std::fmt:: { Display, Formatter, Result };
use std::ops::AddAssign;
use std::collections::hash_map:: { Iter };
use std::convert::AsRef;
use lcov_parser:: { BranchData };
use result::summary:: { LineNumber, AggregateResult, Summary, ExecutionCount };
use result::summary::counter:: { HitFoundCounter, FoundCounter, HitCounter };

/// Units of the branch
///
/// # Examples
///
/// ```
/// use lcov_merge::BranchUnit;
///
/// let branch1 = BranchUnit::new(1, 1);
/// let branch2 = BranchUnit::new(1, 1);
///
/// assert!(branch1 == branch2);
///
/// let not_eq_branch1 = BranchUnit::new(1, 1);
/// let not_eq_branch2 = BranchUnit::new(1, 2);
///
/// assert!(not_eq_branch1 != not_eq_branch2);
/// ```
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone)]
pub struct BranchUnit(u32, u32);

impl BranchUnit {
    pub fn new(block: u32, branch: u32) -> BranchUnit {
        BranchUnit(block, branch)
    }
    pub fn block(&self) -> u32 {
        self.0
    }
    pub fn branch(&self) -> u32 {
        self.1
    }
}

impl Display for BranchUnit {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}-{}", self.0, self.1)
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct BranchBlocks {
    blocks: AggregateResult<BranchUnit, ExecutionCount>
}

impl BranchBlocks {
    pub fn new() -> Self {
        BranchBlocks {
            blocks: AggregateResult::new()
        }
    }
}

impl AsRef<AggregateResult<BranchUnit, ExecutionCount>> for BranchBlocks {
    fn as_ref(&self) -> &AggregateResult<BranchUnit, ExecutionCount> {
        &self.blocks
    }
}

impl Summary<BranchUnit, ExecutionCount> for BranchBlocks {
    fn iter(&self) -> Iter<BranchUnit, ExecutionCount> {
        self.blocks.iter()
    }
    fn contains_key(&self, key: &BranchUnit) -> bool {
        self.blocks.contains_key(key)
    }
    fn get(&self, key: &BranchUnit) -> Option<&ExecutionCount> {
        self.blocks.get(key)
    }
}

impl HitCounter for BranchBlocks {
    fn hit_count(&self) -> usize {
        self.iter()
            .filter(|&(_, taken)| *taken > 0)
            .count()
    }
}

impl FoundCounter for BranchBlocks {
    fn found_count(&self) -> usize {
        self.blocks.len()
    }
}

impl HitFoundCounter for BranchBlocks {}

impl AddAssign for BranchBlocks {
    fn add_assign(&mut self, other: BranchBlocks) {
        self.blocks += other.as_ref();
    }
}

impl<'a> AddAssign<&'a BranchData> for BranchBlocks {
    fn add_assign(&mut self, data: &'a BranchData) {
        let unit = BranchUnit::new(data.block, data.branch);
        let mut block_count = self.blocks.entry(unit)
            .or_insert(0);
        *block_count += data.taken;
    }
}

impl<'a> AddAssign<&'a BranchBlocks> for BranchBlocks {
    fn add_assign(&mut self, other: &'a BranchBlocks) {
        self.blocks += other.as_ref();
    }
}

#[derive(Debug, Clone)]
pub struct Branches {
    branches: AggregateResult<LineNumber, BranchBlocks>
}

impl Branches {
    pub fn new() -> Self {
        Branches {
            branches: AggregateResult::new()
        }
    }
}

impl AsRef<AggregateResult<LineNumber, BranchBlocks>> for Branches {
    fn as_ref(&self) -> &AggregateResult<LineNumber, BranchBlocks> {
        &self.branches
    }
}

impl HitCounter for Branches {
    fn hit_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.hit_count() )
            .fold(0, |p, n| p + n)
    }
}

impl FoundCounter for Branches {
    fn found_count(&self) -> usize {
        self.iter()
            .map(|(_, blocks)| blocks.found_count() )
            .fold(0, |p, n| p + n)
    }
}

impl HitFoundCounter for Branches {}

impl Summary<LineNumber, BranchBlocks> for Branches {
    fn iter(&self) -> Iter<LineNumber, BranchBlocks> {
        self.branches.iter()
    }
    fn contains_key(&self, key: &LineNumber) -> bool {
        self.branches.contains_key(key)
    }
    fn get(&self, key: &LineNumber) -> Option<&BranchBlocks> {
        self.branches.get(key)
    }
}

impl<'a> AddAssign<&'a Branches> for Branches {
    fn add_assign(&mut self, other: &'a Branches) {
        self.branches += other.as_ref();
    }
}

impl<'a> AddAssign<&'a BranchData> for Branches {
    fn add_assign(&mut self, other: &'a BranchData) {
        let mut blocks = self.branches.entry(other.line)
            .or_insert(BranchBlocks::new());
        *blocks += other;
    }
}

#[cfg(test)]
mod tests {
    use std::collections:: { HashMap };
    use lcov_parser:: { BranchData };
    use result::branch:: { BranchUnit, Branches, BranchBlocks };
    use result::summary:: { Summary };
    use result::summary::counter:: { FoundCounter, HitCounter };

    #[test]
    fn branch_unit() {
        let branch1 = BranchUnit(1, 1);
        let branch2 = BranchUnit(1, 2);

        assert!(branch1 != branch2);

        let same_branch1 = BranchUnit(1, 1);
        let same_branch2 = BranchUnit(1, 1);

        assert_eq!(same_branch1, same_branch2);
    }

    #[test]
    fn branch_unit_as_hash_key() {
        let mut container = HashMap::new();
        container.insert(BranchUnit(1, 1), 1);

        assert!( container.contains_key(&BranchUnit(1, 1)) );
    }

    #[test]
    fn add_branch_data() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches += b1;
        branches += b2;

        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&2));
    }

    #[test]
    fn append_branches() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };

        branches += b1;
        branches += b2;

        let cloned_branches = branches.clone();

        branches += &cloned_branches;

        assert_eq!(branches.get(&BranchUnit::new(0, 1)), Some(&4));
    }

    #[test]
    fn branch_blocks_hit_count_and_found_count() {
        let mut branches = BranchBlocks::new();
        let b1 = &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        let b2 = &BranchData { line: 1, block: 0, branch: 2, taken: 0 };

        branches += b1;
        branches += b2;

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }

    #[test]
    fn branches_hit_count_and_found_count() {
        let mut branches = Branches::new();
        branches += &BranchData { line: 1, block: 0, branch: 1, taken: 1 };
        branches += &BranchData { line: 1, block: 0, branch: 2, taken: 0 };

        assert_eq!(branches.hit_count(), 1);
        assert_eq!(branches.found_count(), 2);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::thread;
use std::sync::{mpsc, Arc, Mutex};

use message::Message;
use channel::Channel;
use current_state::{self, CurrentState};
use dispatcher::{self, DispatchType, Subscribe, SubscribeHandle, DispatchMessage, Broadcast, BroadcastHandle};
use view::View;

pub struct DisplayController {
   _input_guard: Option<thread::JoinHandle<()>>,
   _output_guard: Option<thread::JoinHandle<()>>,
   current_state: Arc<Mutex<CurrentState>>,
   subscribe_tx: mpsc::Sender<DispatchMessage>,
   subscribe_rx: Arc<Mutex<mpsc::Receiver<DispatchMessage>>>,
   broadcast_tx: Option<mpsc::Sender<DispatchMessage>>
}

impl DisplayController {
   pub fn new(initial_state: &str) -> DisplayController {
      let initial_state = current_state::new_from_str(&initial_state);
      let (tx, rx) = mpsc::channel::<DispatchMessage>();

      DisplayController {
         _input_guard: None,
         _output_guard: None,
         current_state: Arc::new(Mutex::new(initial_state)),
         subscribe_rx: Arc::new(Mutex::new(rx)),
         subscribe_tx: tx,
         broadcast_tx: None
      }
   }

   pub fn start(&mut self) {
      // output loop
      // Messages that generally result in something
      // being printed
      let state = self.current_state.clone();

      // For blocking on messages
      let rx = self.subscribe_rx.clone();

      // For broadcasting stuff
      let broadcast_tx = self.broadcast_tx.clone().expect("Expected broadcaster to be present in display controller");

      // For sending stuff to be printed to the screen
      let (print_tx, print_rx) = mpsc::channel::<String>();

      let vguard = thread::spawn(move || {
         let mut view = View::new();
         let onInput = Box::new(move |string: String| {
            let message = DispatchMessage { dispatch_type: DispatchType::UserInput, payload: string};
            broadcast_tx.send(message).unwrap();
         });
         view.init(onInput, print_rx);
      });

      let mguard = thread::spawn(move || {
         loop {
            let message = rx.lock().unwrap().recv().unwrap();
            match message.dispatch_type {
               DispatchType::RawIncomingMessage => {
                  let parsed = state.lock().unwrap().parse_incoming_message(&message.payload);
                  print_tx.send(format!("{}", parsed.unwrap())).ok().expect("could not send to view");
               },
               DispatchType::UserInput => {
                  print_tx.send(format!("User input: {}", &message.payload)).ok().expect("could not send to view");
               }
               _ => ()
            }
         }
      });

      // input
      // let iguard = thread::spawn(move || {
      //    let mut stdin = io::stdin();

      //    loop {
      //       let mut input: String = "".to_string();
      //       print!(">> ");
      //       stdin.read_line(&mut input);
      //       tx.send(input).ok().expect("Could not send input");
      //    }
      // });

      // self._output_guard = Some(oguard);
      // self._input_guard = Some(iguard);
   }

   fn print_message(&self, message: Message) -> Result<(), &'static str> {
      println!("{}", message);
      Ok(())
   }
}

impl Subscribe for DisplayController {
   fn subscribe_handle(&self) -> SubscribeHandle {
      self.subscribe_tx.clone()
   }
}

impl Broadcast for DisplayController {
    fn broadcast_handle(&mut self) -> BroadcastHandle {
        let (tx, rx) = mpsc::channel::<DispatchMessage>();
        self.broadcast_tx = Some(tx);
        rx
    }
}

// #[cfg(test)]
// mod test {
//    use super::start;
//    use channel::Channel;

//    fn test_current_channel() {
//       let (mut view, _) = start();
//       assert!(view.current_channel.is_none());

//       let chan = Channel { id: "xyz".to_string(), name: "General".to_string(), is_member: true, members: None };
//       view.current_channel(chan).unwrap();
//       assert_eq!(view.current_channel.unwrap().name, "General");
//    }
// }
<commit_msg>Clean up display controller<commit_after>use std::io;
use std::thread;
use std::sync::{mpsc, Arc, Mutex};

use message::Message;
use channel::Channel;
use current_state::{self, CurrentState};
use dispatcher::{self, DispatchType, Subscribe, SubscribeHandle, DispatchMessage, Broadcast, BroadcastHandle};
use view::View;

pub struct DisplayController {
   _input_guard: Option<thread::JoinHandle<()>>,
   _output_guard: Option<thread::JoinHandle<()>>,
   current_state: Arc<Mutex<CurrentState>>,
   subscribe_tx: mpsc::Sender<DispatchMessage>,
   subscribe_rx: Arc<Mutex<mpsc::Receiver<DispatchMessage>>>,
   broadcast_tx: Option<mpsc::Sender<DispatchMessage>>
}

impl DisplayController {
   pub fn new(initial_state: &str) -> DisplayController {
      let initial_state = current_state::new_from_str(&initial_state);
      let (tx, rx) = mpsc::channel::<DispatchMessage>();

      DisplayController {
         _input_guard: None,
         _output_guard: None,
         current_state: Arc::new(Mutex::new(initial_state)),
         subscribe_rx: Arc::new(Mutex::new(rx)),
         subscribe_tx: tx,
         broadcast_tx: None
      }
   }

   pub fn start(&mut self) {
      // For communicating from and to the view
      let (print_tx, print_rx) = mpsc::channel::<String>();

      self.spawn_view_loop(print_rx);
      self.spawn_print_loop(print_tx);
   }

   fn spawn_view_loop(&self, print_rx: mpsc::Receiver<String>) {
      let broadcast_tx = self.broadcast_tx.clone().expect("Expected broadcaster to be present in display controller");

      thread::spawn(move || {
         let mut view = View::new();
         let onInput = Box::new(move |string: String| {
            let message = DispatchMessage { dispatch_type: DispatchType::UserInput, payload: string};
            broadcast_tx.send(message).unwrap();
         });
         view.init(onInput, print_rx);
      });
   }

   fn spawn_print_loop(&self, print_tx: mpsc::Sender<String>) {
      let rx = self.subscribe_rx.clone();
      let state = self.current_state.clone();
      thread::spawn(move || {
         loop {
            let message = rx.lock().unwrap().recv().unwrap();
            match message.dispatch_type {
               DispatchType::RawIncomingMessage => {
                  let parsed = state.lock().unwrap().parse_incoming_message(&message.payload);
                  print_tx.send(format!("{}", parsed.unwrap())).ok().expect("could not send to view");
               },
               DispatchType::UserInput => {
                  print_tx.send(format!("User input: {}", &message.payload)).ok().expect("could not send to view");
               }
               _ => ()
            }
         }
      });
   }

   fn print_message(&self, message: Message) -> Result<(), &'static str> {
      println!("{}", message);
      Ok(())
   }
}

impl Subscribe for DisplayController {
   fn subscribe_handle(&self) -> SubscribeHandle {
      self.subscribe_tx.clone()
   }
}

impl Broadcast for DisplayController {
    fn broadcast_handle(&mut self) -> BroadcastHandle {
        let (tx, rx) = mpsc::channel::<DispatchMessage>();
        self.broadcast_tx = Some(tx);
        rx
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt;

use event::{Event, React};
use render::MetaRenderer;
use super::application::{Application, Execution};
use super::context::{Context, RenderContextView, UpdateContextView};

pub type BoxActivity<T, R> = Box<Activity<T, R>>;

pub enum Transition<T, R>
    where T: React,
          R: MetaRenderer
{
    None,
    Push(BoxActivity<T, R>),
    Pop,
    Abort,
}

impl<T, R> Transition<T, R>
    where T: React,
          R: MetaRenderer
{
    fn to_execution(&self) -> Execution {
        match *self {
            Transition::None | Transition::Push(..) | Transition::Pop => Execution::Continue,
            Transition::Abort => Execution::Abort,
        }
    }
}

pub trait Activity<T, R>: React
    where T: ActivityState<R>,
          R: MetaRenderer
{
    // TODO: What sort of `Result` (if any) should these functions yield?
    fn update(&mut self, context: &mut UpdateContextView<State = T, Window = R::Window>)
              -> Transition<T, R>;
    fn render(&mut self, context: &mut RenderContextView<R, State = T, Window = R::Window>);

    fn pause(&mut self) {}
    fn resume(&mut self) {}
    fn stop(&mut self) {}
}

pub trait ActivityState<R>: React + Sized
    where R: MetaRenderer
{
    // TODO: This seems like a hacky way to get an initial `Activity` onto the
    //       stack. Is there a better way?
    fn start(context: &mut Context<Self, R>) -> BoxActivity<Self, R>;
}

pub struct ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    stack: Vec<BoxActivity<T, R>>,
}

impl<T, R> ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    fn peek_mut(&mut self) -> Option<&mut Activity<T, R>> {
        if let Some(activity) = self.stack.last_mut() { // Cannot use `map`.
            Some(activity.as_mut())
        }
        else {
            None
        }
    }

    fn push(&mut self, activity: BoxActivity<T, R>) {
        if let Some(activity) = self.peek_mut() {
            activity.pause();
        }
        self.stack.push(activity);
    }

    fn pop(&mut self) -> bool {
        self.stack.pop().map(|mut activity| {
            activity.stop();
            if let Some(activity) = self.peek_mut() {
                activity.resume()
            }
        }).is_some()
    }

    fn abort(&mut self) {
        while self.pop() {}
    }
}

impl<T, R> Application<T, R> for ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    type UpdateError = ActivityStackError;
    type RenderError = ActivityStackError;

    fn start(context: &mut Context<T, R>) -> Self {
        ActivityStack {
            stack: vec![T::start(context)],
        }
    }

    fn update<C>(&mut self, context: &mut C) -> Result<Execution, Self::UpdateError>
        where C: UpdateContextView<State = T, Window = R::Window>
    {
        let transition = if let Some(activity) = self.peek_mut() {
            activity.update(context)
        }
        else {
            Transition::Abort
        };
        let execution = transition.to_execution();
        match transition {
            Transition::None => {}
            Transition::Push(activity) => { self.push(activity); }
            Transition::Pop => { self.pop(); }
            Transition::Abort => { self.abort(); }
        }
        Ok(execution)
    }

    fn render<C>(&mut self, context: &mut C) -> Result<(), Self::RenderError>
        where C: RenderContextView<R, State = T, Window = R::Window>
    {
        if let Some(activity) = self.peek_mut() {
            activity.render(context);
        }
        Ok(())
    }

    fn stop(mut self) {
        self.abort();
    }
}

impl<T, R> React for ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    fn react(&mut self, event: &Event) {
        if let Some(activity) = self.peek_mut() {
            activity.react(event);
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub enum ActivityError {
}

impl fmt::Display for ActivityError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;

        write!(formatter, "{}", self.description())
    }
}

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

#[derive(Clone, Copy, Debug)]
pub enum ActivityStackError {
}

impl fmt::Display for ActivityStackError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;

        write!(formatter, "{}", self.description())
    }
}

impl error::Error for ActivityStackError {
    fn description(&self) -> &str {
        ""
    }
}
<commit_msg>Yield `Result`s from `Activity`s.<commit_after>use std::convert::From;
use std::error;
use std::fmt;

use event::{Event, React};
use render::MetaRenderer;
use super::application::{Application, Execution};
use super::context::{Context, RenderContextView, UpdateContextView};

pub type BoxActivity<T, R> = Box<Activity<T, R>>;

pub enum Transition<T, R>
    where T: React,
          R: MetaRenderer
{
    None,
    Push(BoxActivity<T, R>),
    Pop,
    Abort,
}

impl<T, R> Transition<T, R>
    where T: React,
          R: MetaRenderer
{
    fn to_execution(&self) -> Execution {
        match *self {
            Transition::None | Transition::Push(..) | Transition::Pop => Execution::Continue,
            Transition::Abort => Execution::Abort,
        }
    }
}

pub trait Activity<T, R>: React
    where T: ActivityState<R>,
          R: MetaRenderer
{
    fn update(&mut self, context: &mut UpdateContextView<State = T, Window = R::Window>)
              -> Result<Transition<T, R>, ActivityError>;
    fn render(&mut self, context: &mut RenderContextView<R, State = T, Window = R::Window>)
              -> Result<(), ActivityError>;

    fn pause(&mut self) {}
    fn resume(&mut self) {}
    fn stop(&mut self) {}
}

pub trait ActivityState<R>: React + Sized
    where R: MetaRenderer
{
    // TODO: This seems like a hacky way to get an initial `Activity` onto the
    //       stack. Is there a better way?
    fn start(context: &mut Context<Self, R>) -> BoxActivity<Self, R>;
}

pub struct ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    stack: Vec<BoxActivity<T, R>>,
}

impl<T, R> ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    fn peek_mut(&mut self) -> Option<&mut Activity<T, R>> {
        if let Some(activity) = self.stack.last_mut() { // Cannot use `map`.
            Some(activity.as_mut())
        }
        else {
            None
        }
    }

    fn push(&mut self, activity: BoxActivity<T, R>) {
        if let Some(activity) = self.peek_mut() {
            activity.pause();
        }
        self.stack.push(activity);
    }

    fn pop(&mut self) -> bool {
        self.stack.pop().map(|mut activity| {
            activity.stop();
            if let Some(activity) = self.peek_mut() {
                activity.resume()
            }
        }).is_some()
    }

    fn abort(&mut self) {
        while self.pop() {}
    }
}

impl<T, R> Application<T, R> for ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    type UpdateError = ActivityStackError;
    type RenderError = ActivityStackError;

    fn start(context: &mut Context<T, R>) -> Self {
        ActivityStack {
            stack: vec![T::start(context)],
        }
    }

    fn update<C>(&mut self, context: &mut C) -> Result<Execution, Self::UpdateError>
        where C: UpdateContextView<State = T, Window = R::Window>
    {
        let transition = if let Some(activity) = self.peek_mut() {
            activity.update(context)?
        }
        else {
            Transition::Abort
        };
        let execution = transition.to_execution();
        match transition {
            Transition::None => {}
            Transition::Push(activity) => { self.push(activity); }
            Transition::Pop => { self.pop(); }
            Transition::Abort => { self.abort(); }
        }
        Ok(execution)
    }

    fn render<C>(&mut self, context: &mut C) -> Result<(), Self::RenderError>
        where C: RenderContextView<R, State = T, Window = R::Window>
    {
        self.peek_mut().map_or(Ok(()), |activity| {
            activity.render(context).map_err(|error| error.into())
        })
    }

    fn stop(mut self) {
        self.abort();
    }
}

impl<T, R> React for ActivityStack<T, R>
    where T: ActivityState<R>,
          R: MetaRenderer
{
    fn react(&mut self, event: &Event) {
        if let Some(activity) = self.peek_mut() {
            activity.react(event);
        }
    }
}

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

impl fmt::Display for ActivityError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;

        write!(formatter, "{}", self.description())
    }
}

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

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

impl fmt::Display for ActivityStackError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;

        write!(formatter, "{}", self.description())
    }
}

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

impl From<ActivityError> for ActivityStackError {
    fn from(_: ActivityError) -> Self {
        ActivityStackError
    }
}
<|endoftext|>