<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

pub type BitCount0 = uint; // `BitCount` clashes with a standard trait
pub type BitCount8 = u8;
pub type BitCount16 = u16;
pub type BitCount32 = u32;
pub type BitCount64 = u64;

pub type ByteCount = uint;
pub type ByteCount8 = u8;
pub type ByteCount16 = u16;
pub type ByteCount32 = u32;
pub type ByteCount64 = u64;

pub type WordCount = uint;
pub type WordCount8 = u8;
pub type WordCount16 = u16;
pub type WordCount32 = u32;
pub type WordCount64 = u64;

pub type ElementCount = uint;
pub type ElementCount8 = u8;
pub type ElementCount16 = u16;
pub type ElementCount32 = u32;
pub type ElementCount64 = u64;

pub type WirePointerCount = uint;
pub type WirePointerCount8 = u8;
pub type WirePointerCount16 = u16;
pub type WirePointerCount32 = u32;
pub type WirePointerCount64 = u64;

#[deriving(Copy)]
pub struct Word {_x : u64}

pub const BITS_PER_BYTE : BitCount0 = 8;
pub const BITS_PER_WORD : BitCount0 = 64;
pub const BYTES_PER_WORD : ByteCount = 8;

pub const BITS_PER_POINTER : BitCount0 = 64;
pub const BYTES_PER_POINTER : ByteCount = 8;
pub const WORDS_PER_POINTER : WordCount = 1;

pub const POINTER_SIZE_IN_WORDS : WordCount = 1;

pub fn bytes_per_element<T>() -> ByteCount {
    ::std::mem::size_of::<T>()
}

pub fn bits_per_element<T>() -> BitCount0 {
    8 * ::std::mem::size_of::<T>()
}

#[inline]
pub fn allocate_zeroed_words(size : WordCount) -> ::std::vec::Vec<Word> {

//    Do this, but faster:
//    return ::std::vec::Vec::from_elem(size, 0);

    let mut result : ::std::vec::Vec<Word> = ::std::vec::Vec::with_capacity(size);
    unsafe {
        result.set_len(size);
        let p : *mut u8 = ::std::mem::transmute(result.as_mut_slice().as_mut_ptr());
        ::std::ptr::set_memory(p, 0, size * BYTES_PER_WORD);
    }
    return result;
}

#[deriving(Copy)]
pub struct MessageSize {
    //# Size of a message. Every struct type has a method `.total_size()` that returns this.
    pub word_count : u64,
    pub cap_count : u32
}

impl MessageSize {
    pub fn plus_eq(&mut self, other : MessageSize) {
        self.word_count += other.word_count;
        self.cap_count += other.cap_count;
    }
}

#[inline]
pub fn ptr_sub<T, U: ::std::ptr::RawPtr<T>, V: ::std::ptr::RawPtr<T>>(p1 : U, p2 : V) -> uint {
    return (p1.to_uint() - p2.to_uint()) / ::std::mem::size_of::<T>();
}
<commit_msg>Change 'RawPtr' to 'PtrExt' due to updated API in Rust master.<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

pub type BitCount0 = uint; // `BitCount` clashes with a standard trait
pub type BitCount8 = u8;
pub type BitCount16 = u16;
pub type BitCount32 = u32;
pub type BitCount64 = u64;

pub type ByteCount = uint;
pub type ByteCount8 = u8;
pub type ByteCount16 = u16;
pub type ByteCount32 = u32;
pub type ByteCount64 = u64;

pub type WordCount = uint;
pub type WordCount8 = u8;
pub type WordCount16 = u16;
pub type WordCount32 = u32;
pub type WordCount64 = u64;

pub type ElementCount = uint;
pub type ElementCount8 = u8;
pub type ElementCount16 = u16;
pub type ElementCount32 = u32;
pub type ElementCount64 = u64;

pub type WirePointerCount = uint;
pub type WirePointerCount8 = u8;
pub type WirePointerCount16 = u16;
pub type WirePointerCount32 = u32;
pub type WirePointerCount64 = u64;

#[deriving(Copy)]
pub struct Word {_x : u64}

pub const BITS_PER_BYTE : BitCount0 = 8;
pub const BITS_PER_WORD : BitCount0 = 64;
pub const BYTES_PER_WORD : ByteCount = 8;

pub const BITS_PER_POINTER : BitCount0 = 64;
pub const BYTES_PER_POINTER : ByteCount = 8;
pub const WORDS_PER_POINTER : WordCount = 1;

pub const POINTER_SIZE_IN_WORDS : WordCount = 1;

pub fn bytes_per_element<T>() -> ByteCount {
    ::std::mem::size_of::<T>()
}

pub fn bits_per_element<T>() -> BitCount0 {
    8 * ::std::mem::size_of::<T>()
}

#[inline]
pub fn allocate_zeroed_words(size : WordCount) -> ::std::vec::Vec<Word> {

//    Do this, but faster:
//    return ::std::vec::Vec::from_elem(size, 0);

    let mut result : ::std::vec::Vec<Word> = ::std::vec::Vec::with_capacity(size);
    unsafe {
        result.set_len(size);
        let p : *mut u8 = ::std::mem::transmute(result.as_mut_slice().as_mut_ptr());
        ::std::ptr::set_memory(p, 0, size * BYTES_PER_WORD);
    }
    return result;
}

#[deriving(Copy)]
pub struct MessageSize {
    //# Size of a message. Every struct type has a method `.total_size()` that returns this.
    pub word_count : u64,
    pub cap_count : u32
}

impl MessageSize {
    pub fn plus_eq(&mut self, other : MessageSize) {
        self.word_count += other.word_count;
        self.cap_count += other.cap_count;
    }
}

#[inline]
pub fn ptr_sub<T, U: ::std::ptr::PtrExt<T>, V: ::std::ptr::PtrExt<T>>(p1 : U, p2 : V) -> uint {
    return (p1.to_uint() - p2.to_uint()) / ::std::mem::size_of::<T>();
}
<|endoftext|>


<commit_before>pub mod idl;
pub mod ast;

#[test]
fn test_idl()
{
}

fn main()
{
	let test_string =
	"import something

	interface iTest;

	namespace test
	{
		namespace test2
		{
			interface iTest2;
			interface iBlargo : test::test2::iTest2
			{
				interface_id iid('test::test2::iBlargo');
			}
			class_id iBlargoCID('test::test2::iBlargo');

			namespace test3
			{
			}
		}
	}";

	println! ("------------------------------- Parsing IDL.");
	let result = idl::parse_IDL(test_string);
	match result
	{
		Ok(tree) =>
		{
			for node in tree.depth_first()
			{
				println!("{:?}", node);
			}
		},
		Err(e) =>
		{
			println! ("Parsing error: {:?}", e);
		}
	}

	println! ("-------------------------------");
}
<commit_msg>Starting to walk the ast a bit.  Currently not working as desired.<commit_after>pub mod idl;
pub mod ast;

#[test]
fn test_idl()
{
}

fn main()
{
	let test_string =
	"import something

	interface iTest;

	namespace test
	{
		namespace test2
		{
			interface iTest2;
			interface iBlargo : test::test2::iTest2
			{
				interface_id iid('test::test2::iBlargo');
			}
			class_id iBlargoCID('test::test2::iBlargo');

			namespace test3
			{
			}
		}
	}";

	println! ("------------------------------- Parsing IDL.");
	let result = idl::parse_IDL(test_string);
	match result
	{
		Ok(tree) =>
		{
			display_ast(&tree);
			for node in tree.depth_first()
			{
				println!("{:?}", node);
			}
		},
		Err(e) =>
		{
			println! ("Parsing error: {:?}", e);
		}
	}

	println! ("-------------------------------");
}

fn display_ast(tree: &ast::NodeRef<ast::Data>)
{
	println!("------------------------");
	display_siblings(tree, 0);
	println!("------------------------");
}

fn display_siblings(tree: &ast::NodeRef<ast::Data>, indent: usize)
{
	let mut current = tree.clone();
	loop
	{
		display_indented(&current, indent);
		display_children(&current, indent+2);
		let sibling = current.next_sibling();
		if sibling.is_none()
		{
			break
		}
		current = sibling.unwrap().clone();
	}
}

fn display_children(tree: &ast::NodeRef<ast::Data>, indent: usize)
{
	let mut current = tree.clone();
	loop
	{
		let child = current.first_child();
		if child.is_none() {break}
		current = child.unwrap();
		display_siblings(&current, indent);
	}
}

fn display_indented(node: &ast::NodeRef<ast::Data>, indent: usize)
{
	println!("{:indent$}{:?}", "", node, indent=indent);
}
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::fmt;
use std::mem;
use std::io;
use std::ptr;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use futures::stream::Stream;
use futures::{Poll, Async};

use super::err::{SendError, TrySendError, RecvError, TryRecvError};
use nio::{Awakener, Pollable, Poller, Ops, Token};
use reactor::{IntoStream, PollableIo};

struct Inner<T> {
    buf_ptr: *mut T,
    alloc_cap: usize,
    cap: usize,
    idx_mask: usize,
    _padding0: [usize; cache_line_pad!(4)],

    front: AtomicUsize,
    shadow_rear: Cell<usize>,
    _padding1: [usize; cache_line_pad!(1)],

    shadow_front: Cell<usize>,
    rear: AtomicUsize,
}

unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T> Sync for Inner<T> {}

impl<T> Inner<T> {
    #[inline]
    fn with_capacity(capacity: usize) -> Self {
        let n = capacity.next_power_of_two();
        let mut buf = Vec::with_capacity(n);
        let buf_ptr = buf.as_mut_ptr();
        let alloc_cap = buf.capacity();
        mem::forget(buf);
        Inner {
            buf_ptr: buf_ptr,
            alloc_cap: alloc_cap,
            cap: capacity,
            idx_mask: n.wrapping_sub(1),
            _padding0: [0; cache_line_pad!(4)],

            front: AtomicUsize::new(0),
            shadow_rear: Cell::new(0),
            _padding1: [0; cache_line_pad!(1)],

            shadow_front: Cell::new(0),
            rear: AtomicUsize::new(0),
        }
    }

    #[inline]
    fn effective_index(&self, index: usize) -> usize {
        index & self.idx_mask
    }

    fn try_push(&self, t: T) -> Option<T> {
        let rear = self.rear.load(Ordering::Relaxed);
        if self.shadow_front.get() + self.cap <= rear {
            self.shadow_front.set(self.front.load(Ordering::Acquire));
            if self.shadow_front.get() + self.cap <= rear {
                return Some(t);
            }
        }
        let i = self.effective_index(rear) as isize;
        unsafe { ptr::write(self.buf_ptr.offset(i), t) };
        self.rear.store(rear.wrapping_add(1), Ordering::Release);
        None
    }

    fn try_pop(&self) -> Option<T> {
        let front = self.front.load(Ordering::Relaxed);
        if front == self.shadow_rear.get() {
            self.shadow_rear.set(self.rear.load(Ordering::Acquire));
            if front == self.shadow_rear.get() {
                return None;
            }
        }

        let i = self.effective_index(front) as isize;
        let v = unsafe { ptr::read(self.buf_ptr.offset(i)) };
        self.front.store(front.wrapping_add(1), Ordering::Release);
        Some(v)
    }
}

impl<T> fmt::Debug for Inner<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Channel {{ ")?;
        write!(f,
               "cap: {}, front: {:?}, shadow_rear: {}, shadow_front: {}, rear: {:?}",
               self.cap,
               self.front,
               self.shadow_rear.get(),
               self.shadow_front.get(),
               self.rear)?;
        write!(f, " }}")
    }
}

impl<T> Drop for Inner<T> {
    #[inline]
    fn drop(&mut self) {
        while let Some(t) = self.try_pop() {
            drop(t);
        }
        drop(unsafe { Vec::from_raw_parts(self.buf_ptr, 0, self.alloc_cap) });
    }
}

struct SenderAwakener(Arc<Awakener>);

impl Drop for SenderAwakener {
    fn drop(&mut self) {
        if let Err(e) = (&self.0).wakeup() {
            if e.kind() != io::ErrorKind::WouldBlock {
                error!("Failed to wakeup, {:?}: {}", &self.0, e);
            }
        }
    }
}

pub struct SyncSender<T> {
    inner: Arc<Inner<T>>,
    awakener: SenderAwakener,
}

impl<T> SyncSender<T> {
    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        if Arc::strong_count(&self.inner) == 1 {
            return Err(TrySendError::Disconnected(t));
        }
        if let Some(t) = (&self.inner).try_push(t) {
            return Err(TrySendError::Full(t));
        }
        (&self.awakener.0).wakeup()?;
        Ok(())
    }

    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        let mut msg = t;
        loop {
            if Arc::strong_count(&self.inner) == 1 {
                return Err(SendError::Disconnected(msg));
            }
            match (&self.inner).try_push(msg) {
                Some(t) => msg = t,
                None => break,
            }
        }
        (&self.awakener.0).wakeup()?;
        Ok(())
    }
}

struct ReceiverAwakener(Arc<Awakener>);

impl Drop for ReceiverAwakener {
    fn drop(&mut self) {
        if let Err(e) = (&self.0).reset() {
            if e.kind() != io::ErrorKind::WouldBlock {
                error!("Failed to reset, {:?}: {}", &self.0, e);
            }
        }
    }
}

pub struct Receiver<T> {
    inner: Arc<Inner<T>>,
    awakener: ReceiverAwakener,
}

pub struct Receiving<T> {
    io: PollableIo<Receiver<T>>,
    need_reset: bool,
}

impl<T> Receiver<T> {
    pub fn try_recv(&self) -> Result<T, TryRecvError> {
        self.reset()?;
        if let Some(t) = self.try_pop() {
            Ok(t)
        } else if Arc::strong_count(&self.inner) == 1 {
            Err(TryRecvError::Disconnected)
        } else {
            Err(TryRecvError::Empty)
        }
    }

    pub fn recv(&self) -> Result<T, RecvError> {
        loop {
            if let Some(t) = self.try_pop() {
                (&self.awakener.0).reset()?;
                return Ok(t);
            }
            if Arc::strong_count(&self.inner) == 1 {
                return Err(RecvError::Disconnected);
            }
        }
    }

    #[inline]
    fn reset(&self) -> io::Result<()> {
        (&self.awakener.0).reset()
    }

    #[inline]
    fn try_pop(&self) -> Option<T> {
        (&self.inner).try_pop()
    }
}

impl<T> Pollable for Receiver<T> {
    #[inline]
    fn register(&self, poller: &Poller, interested_ops: Ops, token: Token) -> io::Result<()> {
        (&self.awakener.0).register(poller, interested_ops, token)
    }

    #[inline]
    fn reregister(&self, poller: &Poller, interested_ops: Ops, token: Token) -> io::Result<()> {
        (&self.awakener.0).reregister(poller, interested_ops, token)
    }

    #[inline]
    fn deregister(&self, poller: &Poller) -> io::Result<()> {
        (&self.awakener.0).deregister(poller)
    }
}

impl<T> IntoStream for Receiver<T> {
    type Stream = Receiving<T>;

    #[inline]
    fn into_stream(self) -> Self::Stream {
        Receiving {
            io: PollableIo::new(self),
            need_reset: true,
        }
    }
}

impl<T> fmt::Debug for Receiver<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Receiver {{ inner: {:?}, awakener: {:?} }}",
               &self.inner,
               &self.awakener.0)
    }
}

impl<T> Stream for Receiving<T> {
    type Item = T;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        if self.need_reset {
            if let Err(e) = self.io.get_ref().reset() {
                if e.kind() == io::ErrorKind::WouldBlock {
                    self.io.need_read()?;
                    return Ok(Async::NotReady);
                }
                return Err(e);
            }
            self.need_reset = false;
        }
        if let Some(t) = self.io.get_ref().try_pop() {
            Ok(Async::Ready(Some(t)))
        } else if Arc::strong_count(&self.io.get_ref().inner) == 1 {
            self.need_reset = true;
            Ok(Async::Ready(None))
        } else {
            self.need_reset = true;
            self.io.need_read()?;
            Ok(Async::NotReady)
        }
    }
}

pub fn sync_channel<T>(capacity: usize) -> io::Result<(SyncSender<T>, Receiver<T>)> {
    let inner = Arc::new(Inner::with_capacity(capacity));
    let awakener = Arc::new(Awakener::new()?);
    let tx = SyncSender {
        inner: inner.clone(),
        awakener: SenderAwakener(awakener.clone()),
    };
    let rx = Receiver {
        inner: inner,
        awakener: ReceiverAwakener(awakener),
    };
    Ok((tx, rx))
}
<commit_msg>Derive Debug for SyncSender<commit_after>use std::cell::Cell;
use std::fmt;
use std::mem;
use std::io;
use std::ptr;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use futures::stream::Stream;
use futures::{Poll, Async};

use super::err::{SendError, TrySendError, RecvError, TryRecvError};
use nio::{Awakener, Pollable, Poller, Ops, Token};
use reactor::{IntoStream, PollableIo};

struct Inner<T> {
    buf_ptr: *mut T,
    alloc_cap: usize,
    cap: usize,
    idx_mask: usize,
    _padding0: [usize; cache_line_pad!(4)],

    front: AtomicUsize,
    shadow_rear: Cell<usize>,
    _padding1: [usize; cache_line_pad!(1)],

    shadow_front: Cell<usize>,
    rear: AtomicUsize,
}

unsafe impl<T: Send> Send for Inner<T> {}
unsafe impl<T> Sync for Inner<T> {}

impl<T> Inner<T> {
    #[inline]
    fn with_capacity(capacity: usize) -> Self {
        let n = capacity.next_power_of_two();
        let mut buf = Vec::with_capacity(n);
        let buf_ptr = buf.as_mut_ptr();
        let alloc_cap = buf.capacity();
        mem::forget(buf);
        Inner {
            buf_ptr: buf_ptr,
            alloc_cap: alloc_cap,
            cap: capacity,
            idx_mask: n.wrapping_sub(1),
            _padding0: [0; cache_line_pad!(4)],

            front: AtomicUsize::new(0),
            shadow_rear: Cell::new(0),
            _padding1: [0; cache_line_pad!(1)],

            shadow_front: Cell::new(0),
            rear: AtomicUsize::new(0),
        }
    }

    #[inline]
    fn effective_index(&self, index: usize) -> usize {
        index & self.idx_mask
    }

    fn try_push(&self, t: T) -> Option<T> {
        let rear = self.rear.load(Ordering::Relaxed);
        if self.shadow_front.get() + self.cap <= rear {
            self.shadow_front.set(self.front.load(Ordering::Acquire));
            if self.shadow_front.get() + self.cap <= rear {
                return Some(t);
            }
        }
        let i = self.effective_index(rear) as isize;
        unsafe { ptr::write(self.buf_ptr.offset(i), t) };
        self.rear.store(rear.wrapping_add(1), Ordering::Release);
        None
    }

    fn try_pop(&self) -> Option<T> {
        let front = self.front.load(Ordering::Relaxed);
        if front == self.shadow_rear.get() {
            self.shadow_rear.set(self.rear.load(Ordering::Acquire));
            if front == self.shadow_rear.get() {
                return None;
            }
        }

        let i = self.effective_index(front) as isize;
        let v = unsafe { ptr::read(self.buf_ptr.offset(i)) };
        self.front.store(front.wrapping_add(1), Ordering::Release);
        Some(v)
    }
}

impl<T> fmt::Debug for Inner<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Channel {{ ")?;
        write!(f,
               "cap: {}, front: {:?}, shadow_rear: {}, shadow_front: {}, rear: {:?}",
               self.cap,
               self.front,
               self.shadow_rear.get(),
               self.shadow_front.get(),
               self.rear)?;
        write!(f, " }}")
    }
}

impl<T> Drop for Inner<T> {
    #[inline]
    fn drop(&mut self) {
        while let Some(t) = self.try_pop() {
            drop(t);
        }
        drop(unsafe { Vec::from_raw_parts(self.buf_ptr, 0, self.alloc_cap) });
    }
}

#[derive(Debug)]
struct SenderAwakener(Arc<Awakener>);

impl Drop for SenderAwakener {
    fn drop(&mut self) {
        if let Err(e) = (&self.0).wakeup() {
            if e.kind() != io::ErrorKind::WouldBlock {
                error!("Failed to wakeup, {:?}: {}", &self.0, e);
            }
        }
    }
}

#[derive(Debug)]
pub struct SyncSender<T> {
    inner: Arc<Inner<T>>,
    awakener: SenderAwakener,
}

impl<T> SyncSender<T> {
    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        if Arc::strong_count(&self.inner) == 1 {
            return Err(TrySendError::Disconnected(t));
        }
        if let Some(t) = (&self.inner).try_push(t) {
            return Err(TrySendError::Full(t));
        }
        (&self.awakener.0).wakeup()?;
        Ok(())
    }

    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        let mut msg = t;
        loop {
            if Arc::strong_count(&self.inner) == 1 {
                return Err(SendError::Disconnected(msg));
            }
            match (&self.inner).try_push(msg) {
                Some(t) => msg = t,
                None => break,
            }
        }
        (&self.awakener.0).wakeup()?;
        Ok(())
    }
}

struct ReceiverAwakener(Arc<Awakener>);

impl Drop for ReceiverAwakener {
    fn drop(&mut self) {
        if let Err(e) = (&self.0).reset() {
            if e.kind() != io::ErrorKind::WouldBlock {
                error!("Failed to reset, {:?}: {}", &self.0, e);
            }
        }
    }
}

pub struct Receiver<T> {
    inner: Arc<Inner<T>>,
    awakener: ReceiverAwakener,
}

pub struct Receiving<T> {
    io: PollableIo<Receiver<T>>,
    need_reset: bool,
}

impl<T> Receiver<T> {
    pub fn try_recv(&self) -> Result<T, TryRecvError> {
        self.reset()?;
        if let Some(t) = self.try_pop() {
            Ok(t)
        } else if Arc::strong_count(&self.inner) == 1 {
            Err(TryRecvError::Disconnected)
        } else {
            Err(TryRecvError::Empty)
        }
    }

    pub fn recv(&self) -> Result<T, RecvError> {
        loop {
            if let Some(t) = self.try_pop() {
                (&self.awakener.0).reset()?;
                return Ok(t);
            }
            if Arc::strong_count(&self.inner) == 1 {
                return Err(RecvError::Disconnected);
            }
        }
    }

    #[inline]
    fn reset(&self) -> io::Result<()> {
        (&self.awakener.0).reset()
    }

    #[inline]
    fn try_pop(&self) -> Option<T> {
        (&self.inner).try_pop()
    }
}

impl<T> Pollable for Receiver<T> {
    #[inline]
    fn register(&self, poller: &Poller, interested_ops: Ops, token: Token) -> io::Result<()> {
        (&self.awakener.0).register(poller, interested_ops, token)
    }

    #[inline]
    fn reregister(&self, poller: &Poller, interested_ops: Ops, token: Token) -> io::Result<()> {
        (&self.awakener.0).reregister(poller, interested_ops, token)
    }

    #[inline]
    fn deregister(&self, poller: &Poller) -> io::Result<()> {
        (&self.awakener.0).deregister(poller)
    }
}

impl<T> IntoStream for Receiver<T> {
    type Stream = Receiving<T>;

    #[inline]
    fn into_stream(self) -> Self::Stream {
        Receiving {
            io: PollableIo::new(self),
            need_reset: true,
        }
    }
}

impl<T> fmt::Debug for Receiver<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Receiver {{ inner: {:?}, awakener: {:?} }}",
               &self.inner,
               &self.awakener.0)
    }
}

impl<T> Stream for Receiving<T> {
    type Item = T;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        if self.need_reset {
            if let Err(e) = self.io.get_ref().reset() {
                if e.kind() == io::ErrorKind::WouldBlock {
                    self.io.need_read()?;
                    return Ok(Async::NotReady);
                }
                return Err(e);
            }
            self.need_reset = false;
        }
        if let Some(t) = self.io.get_ref().try_pop() {
            Ok(Async::Ready(Some(t)))
        } else if Arc::strong_count(&self.io.get_ref().inner) == 1 {
            self.need_reset = true;
            Ok(Async::Ready(None))
        } else {
            self.need_reset = true;
            self.io.need_read()?;
            Ok(Async::NotReady)
        }
    }
}

pub fn sync_channel<T>(capacity: usize) -> io::Result<(SyncSender<T>, Receiver<T>)> {
    let inner = Arc::new(Inner::with_capacity(capacity));
    let awakener = Arc::new(Awakener::new()?);
    let tx = SyncSender {
        inner: inner.clone(),
        awakener: SenderAwakener(awakener.clone()),
    };
    let rx = Receiver {
        inner: inner,
        awakener: ReceiverAwakener(awakener),
    };
    Ok((tx, rx))
}
<|endoftext|>


<commit_before>#[link(name = "codegen")];

#[feature(macro_rules)];

use std::io;
use std::io::{File, Truncate, Write, fs};
use std::os;

pub mod branchify;
pub mod status;
pub mod read_method;

fn main() {
    let args = os::args();
    match args.len() {
        0 => {
            println("usage: codegen [read_method|status].rs <output-dir>");
            os::set_exit_status(1);
        },
        3 => {
            let output_dir = Path::init(args[2].as_slice());
            // TODO: maybe not 0777?
            if !output_dir.exists() {
                fs::mkdir(&output_dir, 0b111_111_111);
            }

            match args[1] {
                ~"read_method.rs" => read_method::generate(&output_dir),
                ~"status.rs" => status::generate(&output_dir),
                s => {
                    println!("unknown thing-to-generate '{}'", s);
                    os::set_exit_status(1);
                }
            }
        },
        _ => {
            println!("usage: {} [read_method|status].rs", args[0]);
            os::set_exit_status(1);
        }
    }
}

pub fn get_writer(output_dir: &Path, filename: &str) -> ~Writer {
    let mut output_file = output_dir.clone();
    output_file.push(filename);
    match io::result(|| File::open_mode(&output_file, Truncate, Write)) {
        Ok(writer) => ~writer as ~Writer,
        Err(e) => fail!("Unable to write file: {}", e.desc),
    }
}
<commit_msg>Update for mozilla/rust#10796.<commit_after>#[link(name = "codegen")];

#[feature(macro_rules)];

use std::io;
use std::io::{File, Truncate, Write, fs};
use std::os;

pub mod branchify;
pub mod status;
pub mod read_method;

fn main() {
    let args = os::args();
    match args.len() {
        0 => {
            println("usage: codegen [read_method|status].rs <output-dir>");
            os::set_exit_status(1);
        },
        3 => {
            let output_dir = Path::new(args[2].as_slice());
            // TODO: maybe not 0777?
            if !output_dir.exists() {
                fs::mkdir(&output_dir, 0b111_111_111);
            }

            match args[1] {
                ~"read_method.rs" => read_method::generate(&output_dir),
                ~"status.rs" => status::generate(&output_dir),
                s => {
                    println!("unknown thing-to-generate '{}'", s);
                    os::set_exit_status(1);
                }
            }
        },
        _ => {
            println!("usage: {} [read_method|status].rs", args[0]);
            os::set_exit_status(1);
        }
    }
}

pub fn get_writer(output_dir: &Path, filename: &str) -> ~Writer {
    let mut output_file = output_dir.clone();
    output_file.push(filename);
    match io::result(|| File::open_mode(&output_file, Truncate, Write)) {
        Ok(writer) => ~writer as ~Writer,
        Err(e) => fail!("Unable to write file: {}", e.desc),
    }
}
<|endoftext|>


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

use std::fs::File;
use std::env;
use super::super::color::Color;
use super::super::password;
use super::super::password::ScrubMemory;
use super::super::rpassword::read_password;

pub fn callback(args: &[String], file: &mut File) {
    let ref app_name = args[2];

    // We print this to STDERR instead of STDOUT so that the output of the
    // command contains *only* the password. This makes it easy to pipe it
    // to something like "xclip" which would save the password in the clipboard.
    print_stderr!("Type your master password: ");
    match read_password() {
        Ok(ref mut master_password) => {
            match password::get_password(master_password, app_name, file) {
                Ok(ref mut password) => {
                    println!("{}", password.password);
                    password.scrub_memory();
                },
                Err(err) => {
                    errln!("I couldn't find a password for this app ({:?}).", err);
                    env::set_exit_status(1);
                }
            }
            master_password.scrub_memory();
        },
        Err(err) => {
            errln!("\nI couldn't read the master password ({:?}).", err);
            env::set_exit_status(1);
        }
    }
}
<commit_msg>check if output of "get" is piped, in which case dont print a \n<commit_after>// Copyright 2014 The Peevee Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fs::File;
use std::env;
use super::super::color::Color;
use super::super::password;
use super::super::password::ScrubMemory;
use super::super::rpassword::read_password;
use std::old_io::stdio;

fn stdout_is_piped() -> bool {
    true
}

pub fn callback(args: &[String], file: &mut File) {
    let ref app_name = args[2];

    // We print this to STDERR instead of STDOUT so that the output of the
    // command contains *only* the password. This makes it easy to pipe it
    // to something like "xclip" which would save the password in the clipboard.
    print_stderr!("Type your master password: ");
    match read_password() {
        Ok(ref mut master_password) => {
            match password::get_password(master_password, app_name, file) {
                Ok(ref mut password) => {
                    if stdout_is_piped() {
                        print!("{}", password.password);
                        stdio::flush();
                    } else {
                        println!("{}", password.password);
                    }
                    password.scrub_memory();
                },
                Err(err) => {
                    errln!("I couldn't find a password for this app ({:?}).", err);
                    env::set_exit_status(1);
                }
            }
            master_password.scrub_memory();
        },
        Err(err) => {
            errln!("\nI couldn't read the master password ({:?}).", err);
            env::set_exit_status(1);
        }
    }
}
<|endoftext|>


<commit_before>use std;
use std::collections::HashMap;
use std::sync::Arc;
use std::thread;
use std::sync::atomic::{AtomicU64, Ordering};
use parking_lot::{RwLock, RwLockWriteGuard};
use serde;

use bifrost_hasher::{hash_str, hash_bytes};
use membership::client::{ObserverClient as MembershipClient, Member};
use conshash::weights::DEFAULT_SERVICE_ID;
use conshash::weights::client::{SMClient as WeightSMClient};
use raft::client::{RaftClient, SubscriptionError, SubscriptionReceipt};
use raft::state_machine::master::ExecError;
use utils::bincode::{serialize};
use rand;

use futures::prelude::*;

pub mod weights;

pub static DEFAULT_NODE_LIST_SIZE: f64 = 2048f64;

#[derive(Debug)]
pub enum Action {
    Joined,
    Left,
}

#[derive(Debug)]
pub enum InitTableError {
    GroupNotExisted,
    NoWeightService,
    NoWeightGroup,
    NoWeightInfo,
    Unknown,
}

#[derive(Debug)]
pub enum CHError {
    WatchError(Result<Result<SubscriptionReceipt, SubscriptionError>, ExecError>),
    InitTableError(InitTableError),
}

#[derive(Clone)]
struct Node {
    start: u64,
    server: u64,
}

struct LookupTables {
    nodes: Vec<Node>,
    addrs: HashMap<u64, String>
}

pub struct ConsistentHashing {
    tables: RwLock<LookupTables>,
    membership: Arc<MembershipClient>,
    weight_sm_client: WeightSMClient,
    group_name: String,
    watchers: RwLock<Vec<Box<Fn(&Member, &Action, &LookupTables, &Vec<Node>) + Send + Sync>>>,
    version: AtomicU64
}

impl ConsistentHashing {
    pub fn new_with_id<'a>(id: u64, group: &'a str, raft_client: &Arc<RaftClient>) -> Result<Arc<ConsistentHashing>, CHError> {
        let membership = Arc::new(MembershipClient::new(raft_client));
        let ch = Arc::new(ConsistentHashing {
            tables: RwLock::new(LookupTables {
                nodes: Vec::new(),
                addrs: HashMap::new()
            }),
            membership: membership.clone(),
            weight_sm_client: WeightSMClient::new(id, &raft_client),
            group_name: group.to_string(),
            watchers: RwLock::new(Vec::new()),
            version: AtomicU64::new(0)
        });
        {
            let ch = ch.clone();
            let res = membership.on_group_member_joined(move |r| {
                if let Ok((member, version)) = r { server_joined(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        {
            let ch = ch.clone();
            let res = membership.on_group_member_online(move |r| {
                if let Ok((member, version)) = r { server_joined(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        {
            let ch = ch.clone();
            let res = membership.on_group_member_left(move |r| {
                if let Ok((member, version)) = r { server_left(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        {
            let ch = ch.clone();
            let res = membership.on_group_member_offline(move |r| {
                if let Ok((member, version)) = r { server_left(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        Ok(ch)
    }
    pub fn new<'a>(group: &'a str, raft_client: &Arc<RaftClient>) -> Result<Arc<ConsistentHashing>, CHError> {
        Self::new_with_id(DEFAULT_SERVICE_ID, group, raft_client)
    }
    pub fn new_client<'a>(group: &'a str, raft_client: &Arc<RaftClient>) -> Result<Arc<ConsistentHashing>, CHError> {
        match ConsistentHashing::new(group, raft_client) {
            Err(e) => Err(e),
            Ok(ch) => {
                match ch.init_table() {
                    Err(e) => Err(CHError::InitTableError(e)),
                    Ok(_) =>  Ok(ch.clone())
                }
            },
        }
    }
    pub fn init_table(&self) -> Result<(), InitTableError> {
        let mut table = &mut self.tables.write();
        self.init_table_(&mut table)
    }
    pub fn to_server_name(&self, server_id: Option<u64>) -> Option<String> {
        let lookup_table = self.tables.read();
        match server_id {
            Some(id) => Some(lookup_table.addrs.get(&id).unwrap().clone()),
            None => None
        }
    }
    pub fn get_server_id(&self, hash: u64) -> Option<u64> {
        let lookup_table = self.tables.read();
        let nodes = &lookup_table.nodes;
        let len = nodes.len();
        if len == 0 {return None;}
        let first_node = nodes.first().unwrap();
        let last_node = nodes.last().unwrap();
        if hash < first_node.start {return Some(first_node.server)}
        if hash >= last_node.start {return Some(last_node.server)}
        let mut low = 0;
        let mut high = len - 1;
        while low <= high {
            let mid = low + (high - low) / 2;
            let curr_node = &nodes[mid];
            let next_node = &nodes[mid + 1];
            if hash >= curr_node.start && hash < next_node.start {
                return Some(curr_node.server);
            } else if hash < curr_node.start {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        None
    }
    pub fn get_server(&self, hash: u64) -> Option<String> {
        self.to_server_name(self.get_server_id(hash))
    }
    pub fn get_server_by_string(&self, string: &String) -> Option<String> {
        self.get_server(hash_str(string))
    }
    pub fn get_server_by<T>(&self, obj: &T) -> Option<String> where T: serde::Serialize {
        self.get_server(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn get_server_id_by_string(&self, string: &String) -> Option<u64> {
        self.get_server_id(hash_str(string))
    }
    pub fn get_server_id_by<T>(&self, obj: &T) -> Option<u64> where T: serde::Serialize {
        self.get_server_id(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn rand_server(&self) -> Option<String> {
        let rand = rand::random::<u64>();
        self.get_server(rand)
    }
    pub fn nodes_count(&self) -> usize {
        let lookup_table = self.tables.read();
        return lookup_table.nodes.len();
    }
    pub fn set_weight(&self, server_name: &String, weight: u64) -> impl Future<Item = bool, Error = ExecError> {
        let group_id = hash_str(&self.group_name);
        let server_id = hash_str(server_name);
        self.weight_sm_client.set_weight(&group_id, &server_id, &weight)
            .map(|res| if let Ok(_) = res { true } else { false })
    }
    pub fn watch_all_actions<F>(&self, f: F)
        where F: Fn(&Member, &Action, &LookupTables, &Vec<Node>) + 'static + Send + Sync {
        let mut watchers = self.watchers.write();
        watchers.push(Box::new(f));
    }
    pub fn watch_server_nodes_range_changed<F>(&self, server: &String, f: F)
        // return ranges [...,...)
        where F: Fn(Vec<(u64, u64)>) + 'static + Send + Sync {
        let server_id = hash_str(server);
        let wrapper = move |
            _: &Member,_: &Action,
            lookup_table: &LookupTables, _: &Vec<Node>| {
            let nodes = &lookup_table.nodes;
            let node_len = nodes.len();
            let mut ranges: Vec<(u64, u64)> = Vec::new();
            for ni in 0..node_len {
                let node = &nodes[ni];
                if node.server == server_id {
                    ranges.push((node.start, if ni == node_len - 1 {
                        std::u64::MAX
                    } else {
                        nodes[ni + 1].start
                    }));
                }
            }
            if !ranges.is_empty() {f(ranges);}
        };
        self.watch_all_actions(wrapper);
    }

    fn init_table_(&self, lookup_table: &mut RwLockWriteGuard<LookupTables>) -> Result<(), InitTableError> {
        if let Ok(Ok((members, version))) = self.membership.group_members(&self.group_name, true).wait() {
            let group_id = hash_str(&self.group_name);
            match self.weight_sm_client.get_weights(&group_id).wait() {
                Ok(Ok(Some(weights))) =>  {
                    if let Some(min_weight) = weights.values().min() {
                        lookup_table.nodes.clear(); // refresh nodes
                        let mut factors: HashMap<u64, f64> = HashMap::new();
                        let min_weight = *min_weight as f64;
                        for member in members.iter() {
                            let k = member.id;
                            let w = match weights.get(&k) {
                                Some(w) => *w as f64,
                                None => min_weight,
                            };
                            factors.insert(k, w / min_weight);
                        }
                        let factor_sum: f64 = factors.values().sum();
                        let nodes_size = if factor_sum > DEFAULT_NODE_LIST_SIZE {factor_sum} else {DEFAULT_NODE_LIST_SIZE};
                        let factor_scale = nodes_size / factor_sum;
                        for member in members.iter() {lookup_table.addrs.insert(member.id, member.address.clone());}
                        for (k, f) in factors.iter() {
                            let weight = (*f * factor_scale) as u64;
                            for i in 0..weight {
                                let node_key = format!("{}_{}", k, i);
                                let hash = hash_str(&node_key);
                                lookup_table.nodes.push(Node{
                                    start: hash, server: *k
                                });
                            }
                        };
                        lookup_table.nodes.sort_by(|n1, n2| n1.start.cmp(&n2.start));
                        self.version.store(version, Ordering::Relaxed);
                        Ok(())
                    } else {
                        Err(InitTableError::NoWeightInfo)
                    }
                },
                Err(_) => Err(InitTableError::NoWeightService),
                Ok(Ok(None)) => Err(InitTableError::NoWeightGroup),
                _ => Err(InitTableError::Unknown)

            }
        } else {
            Err(InitTableError::GroupNotExisted)
        }
    }
}

fn server_joined(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Joined, version);
}
fn server_left(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Left, version);
}
fn server_changed(ch: &Arc<ConsistentHashing>, member: Member, action: Action, version: u64) {
    let ch_version = ch.version.load(Ordering::Relaxed);
    if ch_version < version {
        let ch = ch.clone();
        thread::spawn(move || {
            let mut lookup_table = ch.tables.write();
            let watchers = ch.watchers.read();
            let ch_version = ch.version.load(Ordering::Relaxed);
            if ch_version >= version {return;}
            let old_nodes = lookup_table.nodes.clone();
            ch.init_table_(&mut lookup_table);
            for watch in watchers.iter() {
                watch(&member, &action, &*lookup_table, &old_nodes);
            }
        });
    }
}<commit_msg>export exec error on consistant hashing<commit_after>use std;
use std::collections::HashMap;
use std::sync::Arc;
use std::thread;
use std::sync::atomic::{AtomicU64, Ordering};
use parking_lot::{RwLock, RwLockWriteGuard};
use serde;

use bifrost_hasher::{hash_str, hash_bytes};
use membership::client::{ObserverClient as MembershipClient, Member};
use conshash::weights::DEFAULT_SERVICE_ID;
use conshash::weights::client::{SMClient as WeightSMClient};
use raft::client::{RaftClient, SubscriptionError, SubscriptionReceipt};
use raft::state_machine::master::ExecError;
use utils::bincode::{serialize};
use rand;

use futures::prelude::*;

pub mod weights;

pub static DEFAULT_NODE_LIST_SIZE: f64 = 2048f64;

#[derive(Debug)]
pub enum Action {
    Joined,
    Left,
}

#[derive(Debug)]
pub enum InitTableError {
    GroupNotExisted,
    NoWeightService(ExecError),
    NoWeightGroup,
    NoWeightInfo,
    Unknown,
}

#[derive(Debug)]
pub enum CHError {
    WatchError(Result<Result<SubscriptionReceipt, SubscriptionError>, ExecError>),
    InitTableError(InitTableError),
}

#[derive(Clone)]
struct Node {
    start: u64,
    server: u64,
}

struct LookupTables {
    nodes: Vec<Node>,
    addrs: HashMap<u64, String>
}

pub struct ConsistentHashing {
    tables: RwLock<LookupTables>,
    membership: Arc<MembershipClient>,
    weight_sm_client: WeightSMClient,
    group_name: String,
    watchers: RwLock<Vec<Box<Fn(&Member, &Action, &LookupTables, &Vec<Node>) + Send + Sync>>>,
    version: AtomicU64
}

impl ConsistentHashing {
    pub fn new_with_id<'a>(id: u64, group: &'a str, raft_client: &Arc<RaftClient>) -> Result<Arc<ConsistentHashing>, CHError> {
        let membership = Arc::new(MembershipClient::new(raft_client));
        let ch = Arc::new(ConsistentHashing {
            tables: RwLock::new(LookupTables {
                nodes: Vec::new(),
                addrs: HashMap::new()
            }),
            membership: membership.clone(),
            weight_sm_client: WeightSMClient::new(id, &raft_client),
            group_name: group.to_string(),
            watchers: RwLock::new(Vec::new()),
            version: AtomicU64::new(0)
        });
        {
            let ch = ch.clone();
            let res = membership.on_group_member_joined(move |r| {
                if let Ok((member, version)) = r { server_joined(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        {
            let ch = ch.clone();
            let res = membership.on_group_member_online(move |r| {
                if let Ok((member, version)) = r { server_joined(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        {
            let ch = ch.clone();
            let res = membership.on_group_member_left(move |r| {
                if let Ok((member, version)) = r { server_left(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        {
            let ch = ch.clone();
            let res = membership.on_group_member_offline(move |r| {
                if let Ok((member, version)) = r { server_left(&ch, member, version); }
            }, group).wait();
            if let Ok(Ok(_)) = res {} else {return Err(CHError::WatchError(res));}
        }
        Ok(ch)
    }
    pub fn new<'a>(group: &'a str, raft_client: &Arc<RaftClient>) -> Result<Arc<ConsistentHashing>, CHError> {
        Self::new_with_id(DEFAULT_SERVICE_ID, group, raft_client)
    }
    pub fn new_client<'a>(group: &'a str, raft_client: &Arc<RaftClient>) -> Result<Arc<ConsistentHashing>, CHError> {
        match ConsistentHashing::new(group, raft_client) {
            Err(e) => Err(e),
            Ok(ch) => {
                match ch.init_table() {
                    Err(e) => Err(CHError::InitTableError(e)),
                    Ok(_) =>  Ok(ch.clone())
                }
            },
        }
    }
    pub fn init_table(&self) -> Result<(), InitTableError> {
        let mut table = &mut self.tables.write();
        self.init_table_(&mut table)
    }
    pub fn to_server_name(&self, server_id: Option<u64>) -> Option<String> {
        let lookup_table = self.tables.read();
        match server_id {
            Some(id) => Some(lookup_table.addrs.get(&id).unwrap().clone()),
            None => None
        }
    }
    pub fn get_server_id(&self, hash: u64) -> Option<u64> {
        let lookup_table = self.tables.read();
        let nodes = &lookup_table.nodes;
        let len = nodes.len();
        if len == 0 {return None;}
        let first_node = nodes.first().unwrap();
        let last_node = nodes.last().unwrap();
        if hash < first_node.start {return Some(first_node.server)}
        if hash >= last_node.start {return Some(last_node.server)}
        let mut low = 0;
        let mut high = len - 1;
        while low <= high {
            let mid = low + (high - low) / 2;
            let curr_node = &nodes[mid];
            let next_node = &nodes[mid + 1];
            if hash >= curr_node.start && hash < next_node.start {
                return Some(curr_node.server);
            } else if hash < curr_node.start {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        None
    }
    pub fn get_server(&self, hash: u64) -> Option<String> {
        self.to_server_name(self.get_server_id(hash))
    }
    pub fn get_server_by_string(&self, string: &String) -> Option<String> {
        self.get_server(hash_str(string))
    }
    pub fn get_server_by<T>(&self, obj: &T) -> Option<String> where T: serde::Serialize {
        self.get_server(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn get_server_id_by_string(&self, string: &String) -> Option<u64> {
        self.get_server_id(hash_str(string))
    }
    pub fn get_server_id_by<T>(&self, obj: &T) -> Option<u64> where T: serde::Serialize {
        self.get_server_id(hash_bytes(serialize(obj).as_slice()))
    }
    pub fn rand_server(&self) -> Option<String> {
        let rand = rand::random::<u64>();
        self.get_server(rand)
    }
    pub fn nodes_count(&self) -> usize {
        let lookup_table = self.tables.read();
        return lookup_table.nodes.len();
    }
    pub fn set_weight(&self, server_name: &String, weight: u64) -> impl Future<Item = bool, Error = ExecError> {
        let group_id = hash_str(&self.group_name);
        let server_id = hash_str(server_name);
        self.weight_sm_client.set_weight(&group_id, &server_id, &weight)
            .map(|res| if let Ok(_) = res { true } else { false })
    }
    pub fn watch_all_actions<F>(&self, f: F)
        where F: Fn(&Member, &Action, &LookupTables, &Vec<Node>) + 'static + Send + Sync {
        let mut watchers = self.watchers.write();
        watchers.push(Box::new(f));
    }
    pub fn watch_server_nodes_range_changed<F>(&self, server: &String, f: F)
        // return ranges [...,...)
        where F: Fn(Vec<(u64, u64)>) + 'static + Send + Sync {
        let server_id = hash_str(server);
        let wrapper = move |
            _: &Member,_: &Action,
            lookup_table: &LookupTables, _: &Vec<Node>| {
            let nodes = &lookup_table.nodes;
            let node_len = nodes.len();
            let mut ranges: Vec<(u64, u64)> = Vec::new();
            for ni in 0..node_len {
                let node = &nodes[ni];
                if node.server == server_id {
                    ranges.push((node.start, if ni == node_len - 1 {
                        std::u64::MAX
                    } else {
                        nodes[ni + 1].start
                    }));
                }
            }
            if !ranges.is_empty() {f(ranges);}
        };
        self.watch_all_actions(wrapper);
    }

    fn init_table_(&self, lookup_table: &mut RwLockWriteGuard<LookupTables>) -> Result<(), InitTableError> {
        if let Ok(Ok((members, version))) = self.membership.group_members(&self.group_name, true).wait() {
            let group_id = hash_str(&self.group_name);
            match self.weight_sm_client.get_weights(&group_id).wait() {
                Ok(Ok(Some(weights))) =>  {
                    if let Some(min_weight) = weights.values().min() {
                        lookup_table.nodes.clear(); // refresh nodes
                        let mut factors: HashMap<u64, f64> = HashMap::new();
                        let min_weight = *min_weight as f64;
                        for member in members.iter() {
                            let k = member.id;
                            let w = match weights.get(&k) {
                                Some(w) => *w as f64,
                                None => min_weight,
                            };
                            factors.insert(k, w / min_weight);
                        }
                        let factor_sum: f64 = factors.values().sum();
                        let nodes_size = if factor_sum > DEFAULT_NODE_LIST_SIZE {factor_sum} else {DEFAULT_NODE_LIST_SIZE};
                        let factor_scale = nodes_size / factor_sum;
                        for member in members.iter() {lookup_table.addrs.insert(member.id, member.address.clone());}
                        for (k, f) in factors.iter() {
                            let weight = (*f * factor_scale) as u64;
                            for i in 0..weight {
                                let node_key = format!("{}_{}", k, i);
                                let hash = hash_str(&node_key);
                                lookup_table.nodes.push(Node{
                                    start: hash, server: *k
                                });
                            }
                        };
                        lookup_table.nodes.sort_by(|n1, n2| n1.start.cmp(&n2.start));
                        self.version.store(version, Ordering::Relaxed);
                        Ok(())
                    } else {
                        Err(InitTableError::NoWeightInfo)
                    }
                },
                Err(e) => Err(InitTableError::NoWeightService(e)),
                Ok(Ok(None)) => Err(InitTableError::NoWeightGroup),
                _ => Err(InitTableError::Unknown)

            }
        } else {
            Err(InitTableError::GroupNotExisted)
        }
    }
}

fn server_joined(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Joined, version);
}
fn server_left(ch: &Arc<ConsistentHashing>, member: Member, version: u64) {
    server_changed(ch, member, Action::Left, version);
}
fn server_changed(ch: &Arc<ConsistentHashing>, member: Member, action: Action, version: u64) {
    let ch_version = ch.version.load(Ordering::Relaxed);
    if ch_version < version {
        let ch = ch.clone();
        thread::spawn(move || {
            let mut lookup_table = ch.tables.write();
            let watchers = ch.watchers.read();
            let ch_version = ch.version.load(Ordering::Relaxed);
            if ch_version >= version {return;}
            let old_nodes = lookup_table.nodes.clone();
            ch.init_table_(&mut lookup_table);
            for watch in watchers.iter() {
                watch(&member, &action, &*lookup_table, &old_nodes);
            }
        });
    }
}<|endoftext|>


<commit_before>use std::collections::{BTreeSet};
use automata::{M, StateSet, State};

pub type RelationMatrixRow = Vec<bool>;
pub type RelationMatrix = Vec<RelationMatrixRow>;

pub fn get_relation_matrix(m: &M) -> RelationMatrix {
    let mut matrix: RelationMatrix = Vec::new();

    for qi in m.k.iter() {
        let mut row: RelationMatrixRow = Vec::new();
        for qj in m.k.iter() {
            let mut i_relation_j = false;

            for a in m.alphabet.iter() {
                if m.get_next_states(qi, &a).contains(qj) {
                    i_relation_j = true
                }
            }

            row.push(i_relation_j);
        }
        matrix.push(row);
    }

    matrix
}

pub fn warshall(matrix: &RelationMatrix) -> RelationMatrix {
    let n = matrix.len();
    let mut r = matrix.clone();

    for k in 0..n {
        for i in 0..n {
            for j in 0..n {
                r[i][j] = r[i][j] || ( r[i][k] && r[k][j] )
            }
        }
    }

    r
}

pub fn get_reachable_states(m: &M, r: &RelationMatrix) -> StateSet {
    let states: Vec<State> = m.k.iter().cloned().collect();
    let q0_index = m.k.iter().position(|s| *s == m.q0).unwrap();
    let ref reachable_state_row = r[q0_index];
    let reachable_states = {
        let mut res: StateSet = BTreeSet::new();
        for (i, &reachable) in reachable_state_row.iter().enumerate() {
            if reachable {
                res.insert(states[i].clone());
            }
        }
        res
    };

    reachable_states
}

pub fn remove_unreachable_states(mut m: M, reachable_states: StateSet) -> M {
    for u in m.k.difference(&reachable_states) {
        let _ = m.delta.remove(u);
    }

    m.k = reachable_states;

    m
}

#[cfg(test)]
mod tests {
    #[test]
    fn get_relation_matrix_test() {
        use super::get_relation_matrix;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let rm = get_relation_matrix(&m);
        //for i in rm {
            //println!("{:?}", i);
        //}

        let rm_expected = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        assert!(rm == rm_expected);
    }

    #[test]
    fn warshall_test() {
        use super::warshall;

        let rm = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        let r = warshall(&rm);
        let r_expected = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        //for i in &r {
            //println!("{:?}", i);
        //}

        assert!(r == r_expected);
    }

    #[test]
    fn get_reachable_states_test() {
        use super::get_reachable_states;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let r = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        let states = get_reachable_states(&m, &r);
        let states_expected = stateset!("q0", "q1", "q2");

        //for i in &states {
            //println!("{:?}", i);
        //}

        assert!(states == states_expected);
    }

    #[test]
    fn remove_unreachable_states_test() {
        use super::remove_unreachable_states;
        use automata::{M, to_delta_inner};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let reachable_states = stateset!("q0", "q1", "q2");

        let m_new = remove_unreachable_states(m, reachable_states.clone());

        let delta_expected = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2")
        );

        let delta_expected = to_delta_inner(delta_expected);

        assert!(m_new.k == reachable_states);
        assert!(m_new.delta == delta_expected);
    }
}
<commit_msg>first working draft of get_quotient<commit_after>use std::collections::{BTreeSet};
use automata::{M, StateSet, State};

pub type RelationMatrixRow = Vec<bool>;
pub type RelationMatrix = Vec<RelationMatrixRow>;

pub fn get_relation_matrix(m: &M) -> RelationMatrix {
    let mut matrix: RelationMatrix = Vec::new();

    for qi in m.k.iter() {
        let mut row: RelationMatrixRow = Vec::new();
        for qj in m.k.iter() {
            let mut i_relation_j = false;

            for a in m.alphabet.iter() {
                if m.get_next_states(qi, &a).contains(qj) {
                    i_relation_j = true
                }
            }

            row.push(i_relation_j);
        }
        matrix.push(row);
    }

    matrix
}

pub fn warshall(matrix: &RelationMatrix) -> RelationMatrix {
    let n = matrix.len();
    let mut r = matrix.clone();

    for k in 0..n {
        for i in 0..n {
            for j in 0..n {
                r[i][j] = r[i][j] || ( r[i][k] && r[k][j] )
            }
        }
    }

    r
}

pub fn get_reachable_states(m: &M, r: &RelationMatrix) -> StateSet {
    let states: Vec<State> = m.k.iter().cloned().collect();
    let q0_index = m.k.iter().position(|s| *s == m.q0).unwrap();
    let ref reachable_state_row = r[q0_index];
    let reachable_states = {
        let mut res: StateSet = BTreeSet::new();
        for (i, &reachable) in reachable_state_row.iter().enumerate() {
            if reachable {
                res.insert(states[i].clone());
            }
        }
        res
    };

    reachable_states
}

pub fn remove_unreachable_states(mut m: M, reachable_states: StateSet) -> M {
    for u in m.k.difference(&reachable_states) {
        let _ = m.delta.remove(u);
    }

    m.k = reachable_states;

    m
}

pub type EquivalenceClass = StateSet;
pub type Quotient = BTreeSet<EquivalenceClass>;

pub fn get_equivalence_class(states: &StateSet, quotient: &Quotient) -> EquivalenceClass {
    for eq_class in quotient.iter() {
        if states.is_subset(&eq_class) {
            return eq_class.clone();
        }
    }

    stateset!()
}

pub fn get_quotient(m: &M) -> Quotient {
    let k_f: EquivalenceClass = m.k.difference(&m.f).cloned().collect();
    let f: EquivalenceClass = m.f.clone();

    let mut quotient: Quotient = {
        let mut q = BTreeSet::new();
        q.insert(k_f);
        q.insert(f);
        q
    };

    let mut fin = false;

    while !fin {
        let mut next_quotient: Quotient = BTreeSet::new();
        for x in &quotient {
            let mut x_marked: EquivalenceClass = BTreeSet::new();

            while x != &x_marked {
                for state in x {
                    if x_marked.contains(state) { continue }
                    println!("STATE {:?}", state);
                    let mut x1: EquivalenceClass = stateset!(state);

                    x_marked.insert(state.clone());

                    for other_state in x {
                        if x_marked.contains(other_state) { continue }
                        println!("OTHER_STATE {:?}", other_state);
                        let mut flag = true;
                        for a in &m.alphabet {
                            let state_eq_class = get_equivalence_class(&m.get_next_states(&state, &a), &quotient);
                            let other_state_eq_class = get_equivalence_class(&m.get_next_states(&other_state, &a), &quotient);
                            if  state_eq_class == other_state_eq_class  {
                                flag = flag && true
                            } else {
                                flag = flag && false
                            }
                        }
                        if flag {
                            println!("SAME CLASS {:?}, {:?}", state, other_state);
                            x1.insert(other_state.clone());
                            x_marked.insert(other_state.clone());
                        }
                    }

                    next_quotient.insert(x1);
                }
            }
        }

        println!("     QUOTIENT {:?}", quotient);
        println!("Next QUOTIENT {:?}", next_quotient);
        if next_quotient != quotient {
            quotient = next_quotient;
            fin = false;
        } else {
            fin = true;
        }
    }

    quotient
}

#[cfg(test)]
mod tests {
    #[test]
    fn get_relation_matrix_test() {
        use super::get_relation_matrix;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let rm = get_relation_matrix(&m);
        //for i in rm {
            //println!("{:?}", i);
        //}

        let rm_expected = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        assert!(rm == rm_expected);
    }

    #[test]
    fn warshall_test() {
        use super::warshall;

        let rm = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        let r = warshall(&rm);
        let r_expected = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        //for i in &r {
            //println!("{:?}", i);
        //}

        assert!(r == r_expected);
    }

    #[test]
    fn get_reachable_states_test() {
        use super::get_reachable_states;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let r = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        let states = get_reachable_states(&m, &r);
        let states_expected = stateset!("q0", "q1", "q2");

        //for i in &states {
            //println!("{:?}", i);
        //}

        assert!(states == states_expected);
    }

    #[test]
    fn remove_unreachable_states_test() {
        use super::remove_unreachable_states;
        use automata::{M, to_delta_inner};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let reachable_states = stateset!("q0", "q1", "q2");

        let m_new = remove_unreachable_states(m, reachable_states.clone());

        let delta_expected = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2")
        );

        let delta_expected = to_delta_inner(delta_expected);

        assert!(m_new.k == reachable_states);
        assert!(m_new.delta == delta_expected);
    }

    #[test]
    fn get_quotient_test() {
        use std::collections::{BTreeSet};
        use super::{Quotient, get_quotient};
        use automata::{M};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q3");
        let delta = delta!(
            ("q0", 'a', "q1"),
            ("q0", 'b', "q2"),
            ("q1", 'a', "q3"),
            ("q2", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let quotient: Quotient = get_quotient(&m);
        let quotient_expected: Quotient = {
            let mut q = BTreeSet::new();
            q.insert(stateset!("q0"));
            q.insert(stateset!("q1", "q2"));
            q.insert(stateset!("q3"));
            q
        };

        assert_eq!(quotient, quotient_expected);
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeSet};
use automata::{M, StateSet, State};
use automata_operators::stateset_name;

pub type RelationMatrixRow = Vec<bool>;
pub type RelationMatrix = Vec<RelationMatrixRow>;

pub fn get_relation_matrix(m: &M) -> RelationMatrix {
    let mut matrix: RelationMatrix = Vec::new();

    for qi in m.k.iter() {
        let mut row: RelationMatrixRow = Vec::new();
        for qj in m.k.iter() {
            let mut i_relation_j = false;

            for a in m.alphabet.iter() {
                if m.get_next_states(qi, &a).contains(qj) {
                    i_relation_j = true
                }
            }

            row.push(i_relation_j);
        }
        matrix.push(row);
    }

    matrix
}

pub fn warshall(matrix: &RelationMatrix) -> RelationMatrix {
    let n = matrix.len();
    let mut r = matrix.clone();

    for k in 0..n {
        for i in 0..n {
            for j in 0..n {
                r[i][j] = r[i][j] || ( r[i][k] && r[k][j] )
            }
        }
    }

    r
}

pub fn get_reachable_states(m: &M, r: &RelationMatrix) -> StateSet {
    let states: Vec<State> = m.k.iter().cloned().collect();
    let q0_index = m.k.iter().position(|s| *s == m.q0).unwrap();
    let ref reachable_state_row = r[q0_index];
    let reachable_states = {
        let mut res: StateSet = BTreeSet::new();
        for (i, &reachable) in reachable_state_row.iter().enumerate() {
            if reachable {
                res.insert(states[i].clone());
            }
        }
        res
    };

    reachable_states
}

pub fn remove_unreachable_states_with_params(m: &M, reachable_states: StateSet) -> M {
    let mut m: M = (*m).clone();
    for u in m.k.difference(&reachable_states) {
        let _ = m.delta.remove(u);
    }

    m.k = reachable_states;

    m
}

pub type EquivalenceClass = StateSet;
pub type Quotient = BTreeSet<EquivalenceClass>;

pub fn get_equivalence_class(states: &StateSet, quotient: &Quotient) -> EquivalenceClass {
    for eq_class in quotient.iter() {
        if states.is_subset(&eq_class) {
            return eq_class.clone();
        }
    }

    stateset!()
}

pub fn get_quotient(m: &M) -> Quotient {
    let k_f: EquivalenceClass = m.k.difference(&m.f).cloned().collect();
    let f: EquivalenceClass = m.f.clone();

    let mut quotient: Quotient = {
        let mut q = BTreeSet::new();
        q.insert(k_f);
        q.insert(f);
        q
    };

    let mut fin = false;

    while !fin {
        let mut next_quotient: Quotient = BTreeSet::new();
        for x in &quotient {
            let mut x_marked: EquivalenceClass = BTreeSet::new();

            while x != &x_marked {
                for state in x {
                    if x_marked.contains(state) { continue }
                    println!("STATE {:?}", state);
                    let mut x1: EquivalenceClass = stateset!(state);

                    x_marked.insert(state.clone());

                    for other_state in x {
                        if x_marked.contains(other_state) { continue }
                        println!("OTHER_STATE {:?}", other_state);
                        let mut flag = true;
                        for a in &m.alphabet {
                            let state_eq_class = get_equivalence_class(&m.get_next_states(&state, &a), &quotient);
                            let other_state_eq_class = get_equivalence_class(&m.get_next_states(&other_state, &a), &quotient);
                            if  state_eq_class == other_state_eq_class  {
                                flag = flag && true
                            } else {
                                flag = flag && false
                            }
                        }
                        if flag {
                            println!("SAME CLASS {:?}, {:?}", state, other_state);
                            x1.insert(other_state.clone());
                            x_marked.insert(other_state.clone());
                        }
                    }

                    next_quotient.insert(x1);
                }
            }
        }

        println!("     QUOTIENT {:?}", quotient);
        println!("Next QUOTIENT {:?}", next_quotient);
        if next_quotient != quotient {
            quotient = next_quotient;
            fin = false;
        } else {
            fin = true;
        }
    }

    quotient
}

pub fn apply_quotient(m: &M, quotient: &Quotient) -> M {
    let states: StateSet = quotient.iter().map(|eq_class| stateset_name(eq_class)).collect();

    let q0 = stateset_name(&get_equivalence_class(&stateset!(m.q0), quotient));
    let mut f = stateset!();
    for state in &m.f {
        let final_state = stateset_name(&get_equivalence_class(&stateset!(state), quotient));
        f.insert(final_state);
    }

    let mut delta = delta!();
    for (state, delta_value) in &m.delta {
        for (a, next_states) in delta_value {
            for next_state in next_states {
                let s = stateset_name(&get_equivalence_class(&stateset!(state), quotient));
                let ns = stateset_name(&get_equivalence_class(&stateset!(next_state), quotient));
                delta.insert( (s, a.clone(), ns) );
            }
        }
    }

    M::new(
        states,
        m.alphabet.clone(),
        q0,
        f,
        delta
    )
}

//TODO: test
pub fn remove_unreachable_states(m: &M) -> M {
    let relation_matrix: RelationMatrix = get_relation_matrix(&m);
    let r_star: RelationMatrix = warshall(&relation_matrix);
    let reachable_states: StateSet = get_reachable_states(&m, &r_star);
    let m: M = remove_unreachable_states_with_params(&m, reachable_states);

    m
}

//TODO: test
pub fn minify(m: &M) -> M {
    let quotient: Quotient = get_quotient(&m);
    let m: M = apply_quotient(&m, &quotient);

    m
}

//TODO: test
// Remove unreachable states and minify the states
pub fn get_min_automata(m: &M) -> M {
    let m: M = remove_unreachable_states(m);
    let m: M = minify(&m);

    m
}

#[cfg(test)]
mod tests {
    #[test]
    fn get_relation_matrix_test() {
        use super::get_relation_matrix;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let rm = get_relation_matrix(&m);
        let rm_expected = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        assert_eq!(rm, rm_expected);
    }

    #[test]
    fn warshall_test() {
        use super::warshall;

        let rm = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        let r = warshall(&rm);
        let r_expected = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        assert_eq!(r, r_expected);
    }

    #[test]
    fn get_reachable_states_test() {
        use super::get_reachable_states;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let r = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        let states = get_reachable_states(&m, &r);
        let states_expected = stateset!("q0", "q1", "q2");

        assert_eq!(states, states_expected);
    }

    #[test]
    fn remove_unreachable_states_with_params_test() {
        use super::remove_unreachable_states_with_params;
        use automata::{M, to_delta_inner};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let reachable_states = stateset!("q0", "q1", "q2");

        let m_new = remove_unreachable_states_with_params(&m, reachable_states.clone());

        let delta_expected = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2")
        );

        let delta_expected = to_delta_inner(delta_expected);

        assert_eq!(m_new.k, reachable_states);
        assert_eq!(m_new.delta, delta_expected);
    }

    #[test]
    fn get_quotient_test() {
        use std::collections::{BTreeSet};
        use super::{Quotient, get_quotient};
        use automata::{M};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q3");
        let delta = delta!(
            ("q0", 'a', "q1"),
            ("q0", 'b', "q2"),
            ("q1", 'a', "q3"),
            ("q2", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let quotient: Quotient = get_quotient(&m);
        let quotient_expected: Quotient = {
            let mut q = BTreeSet::new();
            q.insert(stateset!("q0"));
            q.insert(stateset!("q1", "q2"));
            q.insert(stateset!("q3"));
            q
        };

        assert_eq!(quotient, quotient_expected);
    }

    #[test]
    fn apply_quotient_test() {
        use std::collections::{BTreeSet};
        use super::{Quotient, apply_quotient};
        use automata::{M, to_delta_inner};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q3");
        let delta = delta!(
            ("q0", 'a', "q1"),
            ("q0", 'b', "q2"),
            ("q1", 'a', "q3"),
            ("q2", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let quotient: Quotient = {
            let mut q = BTreeSet::new();
            q.insert(stateset!("q0"));
            q.insert(stateset!("q1", "q2"));
            q.insert(stateset!("q3"));
            q
        };

        let min_m = apply_quotient(&m, &quotient);

        let delta_expected = delta!(
            ("q0", 'a', "q1q2"),
            ("q0", 'b', "q1q2"),
            ("q1q2", 'a', "q3")
        );

        assert_eq!(min_m.alphabet, m.alphabet);
        assert_eq!(min_m.k, stateset!("q0", "q1q2", "q3"));
        assert_eq!(min_m.q0, "q0");
        assert_eq!(min_m.f, stateset!("q3"));
        assert_eq!(min_m.delta, to_delta_inner(delta_expected));
    }
}
<commit_msg>improve minify interface<commit_after>use std::collections::{BTreeSet};
use automata::{M, StateSet, State};
use automata_operators::stateset_name;

pub type RelationMatrixRow = Vec<bool>;
pub type RelationMatrix = Vec<RelationMatrixRow>;

fn get_relation_matrix(m: &M) -> RelationMatrix {
    let mut matrix: RelationMatrix = Vec::new();

    for qi in m.k.iter() {
        let mut row: RelationMatrixRow = Vec::new();
        for qj in m.k.iter() {
            let mut i_relation_j = false;

            for a in m.alphabet.iter() {
                if m.get_next_states(qi, &a).contains(qj) {
                    i_relation_j = true
                }
            }

            row.push(i_relation_j);
        }
        matrix.push(row);
    }

    matrix
}

fn warshall(matrix: &RelationMatrix) -> RelationMatrix {
    let n = matrix.len();
    let mut r = matrix.clone();

    for k in 0..n {
        for i in 0..n {
            for j in 0..n {
                r[i][j] = r[i][j] || ( r[i][k] && r[k][j] )
            }
        }
    }

    r
}

fn get_reachable_states(m: &M, r: &RelationMatrix) -> StateSet {
    let states: Vec<State> = m.k.iter().cloned().collect();
    let q0_index = m.k.iter().position(|s| *s == m.q0).unwrap();
    let ref reachable_state_row = r[q0_index];
    let reachable_states = {
        let mut res: StateSet = BTreeSet::new();
        for (i, &reachable) in reachable_state_row.iter().enumerate() {
            if reachable {
                res.insert(states[i].clone());
            }
        }
        res
    };

    reachable_states
}

fn remove_unreachable_states_with_params(m: &M, reachable_states: StateSet) -> M {
    let mut m: M = (*m).clone();
    for u in m.k.difference(&reachable_states) {
        let _ = m.delta.remove(u);
    }

    m.k = reachable_states;

    m
}

pub type EquivalenceClass = StateSet;
pub type Quotient = BTreeSet<EquivalenceClass>;

fn get_equivalence_class(states: &StateSet, quotient: &Quotient) -> EquivalenceClass {
    for eq_class in quotient.iter() {
        if states.is_subset(&eq_class) {
            return eq_class.clone();
        }
    }

    stateset!()
}

fn get_quotient(m: &M) -> Quotient {
    let k_f: EquivalenceClass = m.k.difference(&m.f).cloned().collect();
    let f: EquivalenceClass = m.f.clone();

    let mut quotient: Quotient = {
        let mut q = BTreeSet::new();
        q.insert(k_f);
        q.insert(f);
        q
    };

    let mut fin = false;

    while !fin {
        let mut next_quotient: Quotient = BTreeSet::new();
        for x in &quotient {
            let mut x_marked: EquivalenceClass = BTreeSet::new();

            while x != &x_marked {
                for state in x {
                    if x_marked.contains(state) { continue }
                    println!("STATE {:?}", state);
                    let mut x1: EquivalenceClass = stateset!(state);

                    x_marked.insert(state.clone());

                    for other_state in x {
                        if x_marked.contains(other_state) { continue }
                        println!("OTHER_STATE {:?}", other_state);
                        let mut flag = true;
                        for a in &m.alphabet {
                            let state_eq_class = get_equivalence_class(&m.get_next_states(&state, &a), &quotient);
                            let other_state_eq_class = get_equivalence_class(&m.get_next_states(&other_state, &a), &quotient);
                            if  state_eq_class == other_state_eq_class  {
                                flag = flag && true
                            } else {
                                flag = flag && false
                            }
                        }
                        if flag {
                            println!("SAME CLASS {:?}, {:?}", state, other_state);
                            x1.insert(other_state.clone());
                            x_marked.insert(other_state.clone());
                        }
                    }

                    next_quotient.insert(x1);
                }
            }
        }

        println!("     QUOTIENT {:?}", quotient);
        println!("Next QUOTIENT {:?}", next_quotient);
        if next_quotient != quotient {
            quotient = next_quotient;
            fin = false;
        } else {
            fin = true;
        }
    }

    quotient
}

fn apply_quotient(m: &M, quotient: &Quotient) -> M {
    let states: StateSet = quotient.iter().map(|eq_class| stateset_name(eq_class)).collect();

    let q0 = stateset_name(&get_equivalence_class(&stateset!(m.q0), quotient));
    let mut f = stateset!();
    for state in &m.f {
        let final_state = stateset_name(&get_equivalence_class(&stateset!(state), quotient));
        f.insert(final_state);
    }

    let mut delta = delta!();
    for (state, delta_value) in &m.delta {
        for (a, next_states) in delta_value {
            for next_state in next_states {
                let s = stateset_name(&get_equivalence_class(&stateset!(state), quotient));
                let ns = stateset_name(&get_equivalence_class(&stateset!(next_state), quotient));
                delta.insert( (s, a.clone(), ns) );
            }
        }
    }

    M::new(
        states,
        m.alphabet.clone(),
        q0,
        f,
        delta
    )
}

//TODO: test
fn remove_unreachable_states(m: &M) -> M {
    let relation_matrix: RelationMatrix = get_relation_matrix(&m);
    let r_star: RelationMatrix = warshall(&relation_matrix);
    let reachable_states: StateSet = get_reachable_states(&m, &r_star);
    let m: M = remove_unreachable_states_with_params(&m, reachable_states);

    m
}

//TODO: test
pub fn minify(m: &M) -> M {
    let m: M = remove_unreachable_states(m);
    let quotient: Quotient = get_quotient(&m);
    let m: M = apply_quotient(&m, &quotient);

    m
}

#[cfg(test)]
mod tests {
    #[test]
    fn get_relation_matrix_test() {
        use super::get_relation_matrix;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let rm = get_relation_matrix(&m);
        let rm_expected = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        assert_eq!(rm, rm_expected);
    }

    #[test]
    fn warshall_test() {
        use super::warshall;

        let rm = vec![
            vec![true, true, false, false],
            vec![false, true, true, false],
            vec![true, false, true, false],
            vec![false, false, false, true]
        ];

        let r = warshall(&rm);
        let r_expected = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        assert_eq!(r, r_expected);
    }

    #[test]
    fn get_reachable_states_test() {
        use super::get_reachable_states;
        use automata::M;

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let r = vec![
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![true, true, true, false],
            vec![false, false, false, true]
        ];

        let states = get_reachable_states(&m, &r);
        let states_expected = stateset!("q0", "q1", "q2");

        assert_eq!(states, states_expected);
    }

    #[test]
    fn remove_unreachable_states_with_params_test() {
        use super::remove_unreachable_states_with_params;
        use automata::{M, to_delta_inner};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q1");
        let delta = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2"),
            ("q3", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);
        let reachable_states = stateset!("q0", "q1", "q2");

        let m_new = remove_unreachable_states_with_params(&m, reachable_states.clone());

        let delta_expected = delta!(
            ("q0", 'a', "q0"),
            ("q0", 'b', "q1"),
            ("q1", 'a', "q1"),
            ("q1", 'b', "q2"),
            ("q2", 'a', "q0"),
            ("q2", 'b', "q2")
        );

        let delta_expected = to_delta_inner(delta_expected);

        assert_eq!(m_new.k, reachable_states);
        assert_eq!(m_new.delta, delta_expected);
    }

    #[test]
    fn get_quotient_test() {
        use std::collections::{BTreeSet};
        use super::{Quotient, get_quotient};
        use automata::{M};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q3");
        let delta = delta!(
            ("q0", 'a', "q1"),
            ("q0", 'b', "q2"),
            ("q1", 'a', "q3"),
            ("q2", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let quotient: Quotient = get_quotient(&m);
        let quotient_expected: Quotient = {
            let mut q = BTreeSet::new();
            q.insert(stateset!("q0"));
            q.insert(stateset!("q1", "q2"));
            q.insert(stateset!("q3"));
            q
        };

        assert_eq!(quotient, quotient_expected);
    }

    #[test]
    fn apply_quotient_test() {
        use std::collections::{BTreeSet};
        use super::{Quotient, apply_quotient};
        use automata::{M, to_delta_inner};

        let k = stateset!("q0", "q1", "q2", "q3");
        let alphabet = alphabet!('a', 'b');
        let q0 = "q0".to_string();
        let f = stateset!("q3");
        let delta = delta!(
            ("q0", 'a', "q1"),
            ("q0", 'b', "q2"),
            ("q1", 'a', "q3"),
            ("q2", 'a', "q3")
        );

        let m = M::new(k, alphabet, q0, f, delta);

        let quotient: Quotient = {
            let mut q = BTreeSet::new();
            q.insert(stateset!("q0"));
            q.insert(stateset!("q1", "q2"));
            q.insert(stateset!("q3"));
            q
        };

        let min_m = apply_quotient(&m, &quotient);

        let delta_expected = delta!(
            ("q0", 'a', "q1q2"),
            ("q0", 'b', "q1q2"),
            ("q1q2", 'a', "q3")
        );

        assert_eq!(min_m.alphabet, m.alphabet);
        assert_eq!(min_m.k, stateset!("q0", "q1q2", "q3"));
        assert_eq!(min_m.q0, "q0");
        assert_eq!(min_m.f, stateset!("q3"));
        assert_eq!(min_m.delta, to_delta_inner(delta_expected));
    }
}
<|endoftext|>


<commit_before>use std::rc::{Rc};
use std::default::{Default};
use std::u16;
use glium;
use super::{RenderTarget};

pub struct Buffer {
    shader: Rc<glium::Program>,
    texture: Rc<glium::texture::Texture2d>,
    meshes: Vec<Mesh>,
}

impl Buffer {
    /// Create a mesh render buffer with shared shader and texture.
    pub fn new_shared(shader: Rc<glium::Program>, texture: Rc<glium::texture::Texture2d>) -> Buffer {
        Buffer {
            shader: shader,
            texture: texture,
            meshes: vec![Mesh::new()],
        }
    }

    /// Create a mesh render buffer with locally owned shader and texture.
    /// This uses the default sprite shader.
    pub fn new<'a, T>(display: &glium::Display, atlas_image: T) -> Buffer
        where T: glium::texture::Texture2dDataSource<'a> {
        Buffer::new_shared(
            Rc::new(glium::Program::from_source(
                display,
                include_str!("sprite.vert"),
                include_str!("sprite.frag"),
                None).unwrap()),
            Rc::new(glium::texture::Texture2d::new(
                display, atlas_image).unwrap()))
    }

    pub fn flush<S>(&mut self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        let uniforms = glium::uniforms::UniformsStorage::new("tex",
            glium::uniforms::Sampler(&*self.texture, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        let params = glium::DrawParameters {
            backface_culling: glium::BackfaceCullingMode::CullCounterClockWise,
            depth_test: glium::DepthTest::IfLessOrEqual,
            depth_write: true,
            blending_function: Some(glium::BlendingFunction::Addition {
                source: glium::LinearBlendingFactor::SourceAlpha,
                destination: glium::LinearBlendingFactor::OneMinusSourceAlpha }),
            .. Default::default() };

        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        for mesh in self.meshes.iter() {
            let vertices = glium::VertexBuffer::new(display, &mesh.vertices).unwrap();
            let indices = glium::IndexBuffer::new(
                display, glium::index::PrimitiveType::TrianglesList, &mesh.indices).unwrap();
            target.draw(&vertices, &indices, &*self.shader, &uniforms, &params).unwrap();
        }
        self.meshes.clear();
    }
}

impl RenderTarget for Buffer {
    fn add_mesh(&mut self, vertices: Vec<Vertex>, faces: Vec<[u16; 3]>) {
        if self.meshes[self.meshes.len() - 1].is_full() {
            self.meshes.push(Mesh::new());
        }
        let idx = self.meshes.len() - 1;
        self.meshes[idx].push(vertices, faces);
    }

}

struct Mesh {
    pub vertices: Vec<Vertex>,
    pub indices: Vec<u16>,
}

impl Mesh {
    pub fn new() -> Mesh {
        Mesh {
            vertices: Vec::new(),
            indices: Vec::new(),
        }
    }

    pub fn is_full(&self) -> bool {
        // When you're getting within an order of magnitude of the u16 max
        // limit it's time to flush.
        self.vertices.len() > 1<<15
    }

    pub fn push(&mut self, vertices: Vec<Vertex>, faces: Vec<[u16; 3]>) {
        assert!(self.vertices.len() + vertices.len() < u16::MAX as usize);
        let offset = self.vertices.len() as u16;
        for v in vertices.into_iter() { self.vertices.push(v); }

        for face in faces.into_iter() {
            for i in face.into_iter() {
                self.indices.push(i + offset);
            }
        }
    }
}

#[derive(Copy, Clone)]
/// Geometry vertex in on-screen graphics.
pub struct Vertex {
    /// Coordinates on screen
    pub pos: [f32; 3],
    /// Texture coordinates
    pub tex_coord: [f32; 2],
    /// Color for the light parts of the texture
    pub color: [f32; 4],
    /// Color for the dark parts of the texture
    pub back_color: [f32; 4],
}
implement_vertex!(Vertex, pos, tex_coord, color, back_color);
<commit_msg>Fix mesh buffer clearing<commit_after>use std::rc::{Rc};
use std::default::{Default};
use std::u16;
use glium;
use super::{RenderTarget};

pub struct Buffer {
    shader: Rc<glium::Program>,
    texture: Rc<glium::texture::Texture2d>,
    meshes: Vec<Mesh>,
}

impl Buffer {
    /// Create a mesh render buffer with shared shader and texture.
    pub fn new_shared(shader: Rc<glium::Program>, texture: Rc<glium::texture::Texture2d>) -> Buffer {
        Buffer {
            shader: shader,
            texture: texture,
            meshes: vec![Mesh::new()],
        }
    }

    /// Create a mesh render buffer with locally owned shader and texture.
    /// This uses the default sprite shader.
    pub fn new<'a, T>(display: &glium::Display, atlas_image: T) -> Buffer
        where T: glium::texture::Texture2dDataSource<'a> {
        Buffer::new_shared(
            Rc::new(glium::Program::from_source(
                display,
                include_str!("sprite.vert"),
                include_str!("sprite.frag"),
                None).unwrap()),
            Rc::new(glium::texture::Texture2d::new(
                display, atlas_image).unwrap()))
    }

    pub fn flush<S>(&mut self, display: &glium::Display, target: &mut S)
        where S: glium::Surface {
        let uniforms = glium::uniforms::UniformsStorage::new("tex",
            glium::uniforms::Sampler(&*self.texture, glium::uniforms::SamplerBehavior {
                magnify_filter: glium::uniforms::MagnifySamplerFilter::Nearest,
                .. Default::default() }));

        let params = glium::DrawParameters {
            backface_culling: glium::BackfaceCullingMode::CullCounterClockWise,
            depth_test: glium::DepthTest::IfLessOrEqual,
            depth_write: true,
            blending_function: Some(glium::BlendingFunction::Addition {
                source: glium::LinearBlendingFactor::SourceAlpha,
                destination: glium::LinearBlendingFactor::OneMinusSourceAlpha }),
            .. Default::default() };

        // Extract the geometry accumulation buffers and convert into
        // temporary Glium buffers.
        for mesh in self.meshes.iter() {
            let vertices = glium::VertexBuffer::new(display, &mesh.vertices).unwrap();
            let indices = glium::IndexBuffer::new(
                display, glium::index::PrimitiveType::TrianglesList, &mesh.indices).unwrap();
            target.draw(&vertices, &indices, &*self.shader, &uniforms, &params).unwrap();
        }
        self.meshes = vec![Mesh::new()];
    }
}

impl RenderTarget for Buffer {
    fn add_mesh(&mut self, vertices: Vec<Vertex>, faces: Vec<[u16; 3]>) {
        assert!(self.meshes.len() > 0);

        if self.meshes[self.meshes.len() - 1].is_full() {
            self.meshes.push(Mesh::new());
        }
        let idx = self.meshes.len() - 1;
        self.meshes[idx].push(vertices, faces);
    }

}

struct Mesh {
    pub vertices: Vec<Vertex>,
    pub indices: Vec<u16>,
}

impl Mesh {
    pub fn new() -> Mesh {
        Mesh {
            vertices: Vec::new(),
            indices: Vec::new(),
        }
    }

    pub fn is_full(&self) -> bool {
        // When you're getting within an order of magnitude of the u16 max
        // limit it's time to flush.
        self.vertices.len() > 1<<15
    }

    pub fn push(&mut self, vertices: Vec<Vertex>, faces: Vec<[u16; 3]>) {
        assert!(self.vertices.len() + vertices.len() < u16::MAX as usize);
        let offset = self.vertices.len() as u16;
        for v in vertices.into_iter() { self.vertices.push(v); }

        for face in faces.into_iter() {
            for i in face.into_iter() {
                self.indices.push(i + offset);
            }
        }
    }
}

#[derive(Copy, Clone)]
/// Geometry vertex in on-screen graphics.
pub struct Vertex {
    /// Coordinates on screen
    pub pos: [f32; 3],
    /// Texture coordinates
    pub tex_coord: [f32; 2],
    /// Color for the light parts of the texture
    pub color: [f32; 4],
    /// Color for the dark parts of the texture
    pub back_color: [f32; 4],
}
implement_vertex!(Vertex, pos, tex_coord, color, back_color);
<|endoftext|>