<commit_before>use std::ptr::NonNull;

type NodePtr<T> = NonNull<Node<T>>;
type OptNodePtr<T> = Option<NodePtr<T>>;

pub struct LinkedList<T> {
    head: OptNodePtr<T>,
    tail: OptNodePtr<T>,
    len: usize,
    marker: std::marker::PhantomData<Box<T>>, // for dropck
}

pub struct Cursor<'a, T: 'a> {
    list: &'a mut LinkedList<T>,
    node: OptNodePtr<T>,
}

struct Node<T> {
    element: T,
    next: OptNodePtr<T>,
    prev: OptNodePtr<T>,
}

impl<T> Node<T> {
    fn new_linkless(element: T) -> NodePtr<T> {
        Self::allocate(element, None, None)
    }

    fn allocate(element: T, prev: OptNodePtr<T>, next: OptNodePtr<T>) -> NodePtr<T> {
        unsafe {
            NonNull::new_unchecked(Box::into_raw(Box::new(Self {
                element,
                next,
                prev,
            })))
        }
    }
}

trait NodePtrHelper<T> {
    fn get_next(&mut self) -> &mut OptNodePtr<T>;
    fn get_prev(&mut self) -> &mut OptNodePtr<T>;
    fn link(left: NodePtr<T>, right: NodePtr<T>);
    fn insert_between(self, prev: NodePtr<T>, next: NodePtr<T>) -> NodePtr<T>;
    fn insert_new_after(self, element: T) -> NodePtr<T>;
    fn insert_new_before(self, element: T) -> NodePtr<T>;
    fn unlink_next(&mut self) -> OptNodePtr<T>;
    fn unlink_prev(&mut self) -> OptNodePtr<T>;
    fn into_inner(self) -> T;
}

impl<T> NodePtrHelper<T> for NodePtr<T> {
    fn get_next(&mut self)-> &mut OptNodePtr<T> {
        unsafe { &mut self.as_mut().next }
    }

    fn get_prev(&mut self)-> &mut OptNodePtr<T> {
        unsafe { &mut self.as_mut().prev }
    }

    fn link(mut left: NodePtr<T>, mut right: NodePtr<T>) {
        *left.get_next() = Some(right);
        *right.get_prev() = Some(left);
    }

    fn insert_between(self, prev: NodePtr<T>, next: NodePtr<T>) -> Self {
        Self::link(prev, self);
        Self::link(self, next);
        self
    }

    fn insert_new_after(mut self, element: T) -> Self {
        if let Some(next) = *self.get_next() {
            Node::new_linkless(element)
                .insert_between(self, next)
        } else {
            let new_node = Node::new_linkless(element);
            NodePtr::link(self, new_node);
            new_node
        }
    }

    fn insert_new_before(mut self, element: T) -> Self {
        if let Some(prev) = *self.get_prev() {
            Node::new_linkless(element)
                .insert_between(prev, self)
        } else {
            let new_node = Node::new_linkless(element);
            NodePtr::link(new_node, self);
            new_node
        }
    }

    // returns next of self, if it exists
    fn unlink_next(&mut self) -> OptNodePtr<T> {
        self.get_next().map(|mut next| {
            *next.get_prev() = None;
            //self.as_mut().next = None;
            next
        })    }

    // returns prev of self, if it exists
    fn unlink_prev(&mut self) -> OptNodePtr<T> {
        self.get_prev().map(|mut prev| {
            *prev.get_next() = None;
            //self.as_mut().prev = None;
            prev
        })
    }

    // must be unlinked from all others
    fn into_inner(self) -> T {
        unsafe {
            Box::from_raw(self.as_ptr()).element
        }
    }
}

impl<T> LinkedList<T> {
    pub fn new() -> Self {
        LinkedList {
            head: None,
            tail: None,
            len: 0,
            marker: std::marker::PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn push_back(&mut self, element: T) {
        self.cursor_head().insert_after(element);
    }

    pub fn push_front(&mut self, element: T) {
        self.cursor_tail().insert_before(element);
    }

    pub fn pop_back(&mut self) -> Option<T> {
        self.cursor_head().take()
    }

    pub fn pop_front(&mut self) -> Option<T> {
        self.cursor_tail().take()
    }

    pub fn cursor_tail(&mut self) -> Cursor<T> {
        Cursor {
            node: self.tail,
            list: self,
        }
    }

    pub fn cursor_head(&mut self) -> Cursor<T> {
        Cursor {
            node: self.head,
            list: self,
        }
    }

    unsafe fn immutable_cursor_tail(&self) -> Cursor<T> {
        let list = &mut *(self as *const LinkedList<T> as *mut LinkedList<T>);
        list.cursor_tail()
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            first: true,
            cursor: unsafe { self.immutable_cursor_tail() },
        }
    }
}

impl<T> Drop for LinkedList<T> {
    fn drop(&mut self) {
        while let Some(_) = self.pop_back() {}
    }
}

impl<T: Clone> Clone for LinkedList<T> {
    fn clone(&self) -> Self {
        let mut new_list = LinkedList::new();
        for element in self.iter().cloned() {
            new_list.push_back(element);
        }
        new_list
    }
}

pub struct Iter<'a, T: 'a> {
    first: bool,
    cursor: Cursor<'a, T>,
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        // transmuting lifetimes
        // FIXME: obviously remove this
        unsafe {
            if self.first {
                self.first = false;
                std::mem::transmute::<Option<&T>, Option<&T>>(self.cursor.peek())
            } else {
                std::mem::transmute::<Option<&mut T>, Option<&mut T>>(self.cursor.next()).map(|r| &*r)
            }
        }
    }
}

impl<'a, T: 'a> Cursor<'a, T> {
    pub fn peek_mut(&mut self) -> Option<&mut T> {
        unsafe {
            self.node.map(|node| &mut (*node.as_ptr()).element)
        }
    }

    // FIXME: I'm pretty certain this lifetime is UNSOUND
    //        hacked only to get Iter working, temporarily
    pub fn next(&mut self) -> Option<&mut T> {
        self._step(|node| node.next)
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        self._step(|node| node.prev)
    }

    fn _step(
        &mut self,
        get_next: impl Fn(&mut Node<T>) -> OptNodePtr<T>
    ) -> Option<&mut T> {
        unsafe {
            if let Some(new_pos) = get_next(self.node.as_mut()?.as_mut()) {
                self.node = Some(new_pos);
                Some(&mut (*new_pos.as_ptr()).element)
            } else {
                None
            }
        }
    }

    pub fn take(&mut self) -> Option<T> {
        let mut node = self.node?;
        let next = node.unlink_next();
        let prev = node.unlink_prev();

        match (prev, next) {
            (Some(prev), Some(next)) => NodePtr::link(prev, next),
            (Some(_), None) => self.list.head = prev,
            (None, Some(_)) => self.list.tail = next,
            _ => {
                self.list.head = None;
                self.list.tail = None;
            },
        };
        self.list.len -= 1;
        Some(node.into_inner())
    }

    pub fn insert_after(&mut self, element: T) {
        self._insert(element, |list, cursor_node, element| {
            let new_node = cursor_node.insert_new_after(element);
            if list.head == Some(cursor_node) {
                list.head = Some(new_node);
            }
        });
    }

    pub fn insert_before(&mut self, element: T) {
        self._insert(element, |list, cursor_node, element| {
            let new_node = cursor_node.insert_new_before(element);
            if list.tail == Some(cursor_node) {
                list.tail = Some(new_node);
            }
        });
    }

    // put into list, if empty, else do whatever callback says
    fn _insert(&mut self, element: T, callback: impl Fn(&mut LinkedList<T>, NodePtr<T>, T)) {
        let cursor_node = match self.node {
            Some(node) => node,
            None => { // list empty
                self.node = Some(Node::new_linkless(element));
                self.list.head = self.node;
                self.list.tail = self.node;
                self.list.len += 1;
                return
            }
        };
        callback(&mut self.list, cursor_node, element);
        self.list.len += 1;
    }

    fn _insert_list_on_empty_list(&mut self, other: &mut LinkedList<T>) {
        debug_assert!(self.list.len == 0);
        std::mem::swap(self.list, other);
        self.node = self.list.tail;
    }

    fn _insert_list(
        &mut self,
        other: &mut LinkedList<T>,
        callback: impl Fn(NodePtr<T>, NodePtr<T>, NodePtr<T>)
    ) {
        unsafe {
            let cursor_node = match self.node {
                Some(node) => node,
                None => {
                    self._insert_list_on_empty_list(other);
                    return;
                }
            };

            if let LinkedList { head: Some(head), tail: Some(tail), len, .. } = *other {
                debug_assert!(head.as_ref().next.is_none());
                debug_assert!(tail.as_ref().prev.is_none());
                std::ptr::write(other, LinkedList::new()); // empty without dropping

                // link up on the right or left side
                callback(cursor_node, head, tail);
                self.list.len += len; // may overflow
            }
        }
    }

    pub fn insert_list_after(&mut self, other: &mut LinkedList<T>) {
        unsafe {
            self._insert_list(other, |mut cursor_node, head, tail| {
                if let Some(next) = cursor_node.as_mut().next {
                    NodePtr::link(head, next);
                }
                NodePtr::link(cursor_node, tail);
            });
        }
    }

    pub fn insert_list_before(&mut self, other: &mut LinkedList<T>) {
        unsafe {
            self._insert_list(other, |mut cursor_node, head, tail| {
                if let Some(prev) = cursor_node.as_mut().prev {
                    NodePtr::link(prev, tail);
                }
                NodePtr::link(head, cursor_node);
            });
        }
    }
}
<commit_msg>linked-list: remove cursor from iter<commit_after>use std::ptr::NonNull;

type NodePtr<T> = NonNull<Node<T>>;
type OptNodePtr<T> = Option<NodePtr<T>>;

pub struct LinkedList<T> {
    head: OptNodePtr<T>,
    tail: OptNodePtr<T>,
    len: usize,
    marker: std::marker::PhantomData<Box<T>>, // for dropck
}

pub struct Cursor<'a, T: 'a> {
    list: &'a mut LinkedList<T>,
    node: OptNodePtr<T>,
}

struct Node<T> {
    element: T,
    next: OptNodePtr<T>,
    prev: OptNodePtr<T>,
}

impl<T> Node<T> {
    fn new_linkless(element: T) -> NodePtr<T> {
        Self::allocate(element, None, None)
    }

    fn allocate(element: T, prev: OptNodePtr<T>, next: OptNodePtr<T>) -> NodePtr<T> {
        unsafe {
            NonNull::new_unchecked(Box::into_raw(Box::new(Self {
                element,
                next,
                prev,
            })))
        }
    }
}

trait NodePtrHelper<T> {
    fn get_next(&mut self) -> &mut OptNodePtr<T>;
    fn get_prev(&mut self) -> &mut OptNodePtr<T>;
    fn link(left: NodePtr<T>, right: NodePtr<T>);
    fn insert_between(self, prev: NodePtr<T>, next: NodePtr<T>) -> NodePtr<T>;
    fn insert_new_after(self, element: T) -> NodePtr<T>;
    fn insert_new_before(self, element: T) -> NodePtr<T>;
    fn unlink_next(&mut self) -> OptNodePtr<T>;
    fn unlink_prev(&mut self) -> OptNodePtr<T>;
    fn into_inner(self) -> T;
}

impl<T> NodePtrHelper<T> for NodePtr<T> {
    fn get_next(&mut self)-> &mut OptNodePtr<T> {
        unsafe { &mut self.as_mut().next }
    }

    fn get_prev(&mut self)-> &mut OptNodePtr<T> {
        unsafe { &mut self.as_mut().prev }
    }

    fn link(mut left: NodePtr<T>, mut right: NodePtr<T>) {
        *left.get_next() = Some(right);
        *right.get_prev() = Some(left);
    }

    fn insert_between(self, prev: NodePtr<T>, next: NodePtr<T>) -> Self {
        Self::link(prev, self);
        Self::link(self, next);
        self
    }

    fn insert_new_after(mut self, element: T) -> Self {
        if let Some(next) = *self.get_next() {
            Node::new_linkless(element)
                .insert_between(self, next)
        } else {
            let new_node = Node::new_linkless(element);
            NodePtr::link(self, new_node);
            new_node
        }
    }

    fn insert_new_before(mut self, element: T) -> Self {
        if let Some(prev) = *self.get_prev() {
            Node::new_linkless(element)
                .insert_between(prev, self)
        } else {
            let new_node = Node::new_linkless(element);
            NodePtr::link(new_node, self);
            new_node
        }
    }

    // returns next of self, if it exists
    fn unlink_next(&mut self) -> OptNodePtr<T> {
        self.get_next().map(|mut next| {
            *next.get_prev() = None;
            //self.as_mut().next = None;
            next
        })    }

    // returns prev of self, if it exists
    fn unlink_prev(&mut self) -> OptNodePtr<T> {
        self.get_prev().map(|mut prev| {
            *prev.get_next() = None;
            //self.as_mut().prev = None;
            prev
        })
    }

    // must be unlinked from all others
    fn into_inner(self) -> T {
        unsafe {
            Box::from_raw(self.as_ptr()).element
        }
    }
}

impl<T> LinkedList<T> {
    pub fn new() -> Self {
        LinkedList {
            head: None,
            tail: None,
            len: 0,
            marker: std::marker::PhantomData,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn push_back(&mut self, element: T) {
        self.cursor_head().insert_after(element);
    }

    pub fn push_front(&mut self, element: T) {
        self.cursor_tail().insert_before(element);
    }

    pub fn pop_back(&mut self) -> Option<T> {
        self.cursor_head().take()
    }

    pub fn pop_front(&mut self) -> Option<T> {
        self.cursor_tail().take()
    }

    pub fn cursor_tail(&mut self) -> Cursor<T> {
        Cursor {
            node: self.tail,
            list: self,
        }
    }

    pub fn cursor_head(&mut self) -> Cursor<T> {
        Cursor {
            node: self.head,
            list: self,
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            next_node: self.tail,
            marker: std::marker::PhantomData,
        }
    }
}

impl<T> Drop for LinkedList<T> {
    fn drop(&mut self) {
        while let Some(_) = self.pop_back() {}
    }
}

impl<T: Clone> Clone for LinkedList<T> {
    fn clone(&self) -> Self {
        let mut new_list = LinkedList::new();
        for element in self.iter().cloned() {
            new_list.push_back(element);
        }
        new_list
    }
}

pub struct Iter<'a, T: 'a> {
    next_node: OptNodePtr<T>,
    marker: std::marker::PhantomData<&'a LinkedList<T>>,
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        let node_ptr = self.next_node?;
        unsafe {
            let current_node = &*node_ptr.as_ptr();
            self.next_node = current_node.next;
            Some(&current_node.element)
        }
    }
}

impl<'a, T: 'a> Cursor<'a, T> {
    pub fn peek_mut(&mut self) -> Option<&mut T> {
        unsafe {
            self.node.map(|node| &mut (*node.as_ptr()).element)
        }
    }

    // FIXME: I'm pretty certain this lifetime is UNSOUND
    //        hacked only to get Iter working, temporarily
    pub fn next(&mut self) -> Option<&mut T> {
        self._step(|node| node.next)
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        self._step(|node| node.prev)
    }

    fn _step(
        &mut self,
        get_next: impl Fn(&mut Node<T>) -> OptNodePtr<T>
    ) -> Option<&mut T> {
        unsafe {
            if let Some(new_pos) = get_next(self.node.as_mut()?.as_mut()) {
                self.node = Some(new_pos);
                Some(&mut (*new_pos.as_ptr()).element)
            } else {
                None
            }
        }
    }

    pub fn take(&mut self) -> Option<T> {
        let mut node = self.node?;
        let next = node.unlink_next();
        let prev = node.unlink_prev();

        match (prev, next) {
            (Some(prev), Some(next)) => NodePtr::link(prev, next),
            (Some(_), None) => self.list.head = prev,
            (None, Some(_)) => self.list.tail = next,
            _ => {
                self.list.head = None;
                self.list.tail = None;
            },
        };
        self.list.len -= 1;
        Some(node.into_inner())
    }

    pub fn insert_after(&mut self, element: T) {
        self._insert(element, |list, cursor_node, element| {
            let new_node = cursor_node.insert_new_after(element);
            if list.head == Some(cursor_node) {
                list.head = Some(new_node);
            }
        });
    }

    pub fn insert_before(&mut self, element: T) {
        self._insert(element, |list, cursor_node, element| {
            let new_node = cursor_node.insert_new_before(element);
            if list.tail == Some(cursor_node) {
                list.tail = Some(new_node);
            }
        });
    }

    // put into list, if empty, else do whatever callback says
    fn _insert(&mut self, element: T, callback: impl Fn(&mut LinkedList<T>, NodePtr<T>, T)) {
        let cursor_node = match self.node {
            Some(node) => node,
            None => { // list empty
                self.node = Some(Node::new_linkless(element));
                self.list.head = self.node;
                self.list.tail = self.node;
                self.list.len += 1;
                return
            }
        };
        callback(&mut self.list, cursor_node, element);
        self.list.len += 1;
    }

    fn _insert_list_on_empty_list(&mut self, other: &mut LinkedList<T>) {
        debug_assert!(self.list.len == 0);
        std::mem::swap(self.list, other);
        self.node = self.list.tail;
    }

    fn _insert_list(
        &mut self,
        other: &mut LinkedList<T>,
        callback: impl Fn(NodePtr<T>, NodePtr<T>, NodePtr<T>)
    ) {
        unsafe {
            let cursor_node = match self.node {
                Some(node) => node,
                None => {
                    self._insert_list_on_empty_list(other);
                    return;
                }
            };

            if let LinkedList { head: Some(head), tail: Some(tail), len, .. } = *other {
                debug_assert!(head.as_ref().next.is_none());
                debug_assert!(tail.as_ref().prev.is_none());
                std::ptr::write(other, LinkedList::new()); // empty without dropping

                // link up on the right or left side
                callback(cursor_node, head, tail);
                self.list.len += len; // may overflow
            }
        }
    }

    pub fn insert_list_after(&mut self, other: &mut LinkedList<T>) {
        unsafe {
            self._insert_list(other, |mut cursor_node, head, tail| {
                if let Some(next) = cursor_node.as_mut().next {
                    NodePtr::link(head, next);
                }
                NodePtr::link(cursor_node, tail);
            });
        }
    }

    pub fn insert_list_before(&mut self, other: &mut LinkedList<T>) {
        unsafe {
            self._insert_list(other, |mut cursor_node, head, tail| {
                if let Some(prev) = cursor_node.as_mut().prev {
                    NodePtr::link(prev, tail);
                }
                NodePtr::link(head, cursor_node);
            });
        }
    }
}
<|endoftext|>


<commit_before>//! Matrix identifiers for places where a room ID or room alias ID are used interchangeably.

use std::{convert::TryFrom, fmt, hint::unreachable_unchecked, num::NonZeroU8};

use crate::{server_name::ServerName, RoomAliasId, RoomId};

/// A Matrix room ID or a Matrix room alias ID.
///
/// `RoomIdOrAliasId` is useful for APIs that accept either kind of room identifier. It is converted
/// from a string slice, and can be converted back into a string as needed. When converted from a
/// string slice, the variant is determined by the leading sigil character.
///
/// ```
/// # use std::convert::TryFrom;
/// # use ruma_identifiers::RoomIdOrAliasId;
/// assert_eq!(
///     RoomIdOrAliasId::try_from("#ruma:example.com").unwrap().as_ref(),
///     "#ruma:example.com"
/// );
///
/// assert_eq!(
///     RoomIdOrAliasId::try_from("!n8f893n9:example.com").unwrap().as_ref(),
///     "!n8f893n9:example.com"
/// );
/// ```
#[derive(Clone)]
pub struct RoomIdOrAliasId {
    full_id: Box<str>,
    colon_idx: NonZeroU8,
}

impl fmt::Debug for RoomIdOrAliasId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.full_id)
    }
}

impl RoomIdOrAliasId {
    /// Returns the local part (everything after the `!` or `#` and before the first colon).
    pub fn localpart(&self) -> &str {
        &self.full_id[1..self.colon_idx.get() as usize]
    }

    /// Returns the server name of the room (alias) ID.
    pub fn server_name(&self) -> &ServerName {
        <&ServerName>::try_from(&self.full_id[self.colon_idx.get() as usize + 1..]).unwrap()
    }

    /// Whether this is a room id (starts with `'!'`)
    pub fn is_room_id(&self) -> bool {
        self.variant() == Variant::RoomId
    }

    /// Whether this is a room alias id (starts with `'#'`)
    pub fn is_room_alias_id(&self) -> bool {
        self.variant() == Variant::RoomAliasId
    }

    /// Turn this `RoomIdOrAliasId` into `Either<RoomId, RoomAliasId>`
    #[cfg(feature = "either")]
    #[cfg_attr(docsrs, doc(cfg(feature = "either")))]
    pub fn into_either(self) -> either::Either<RoomId, RoomAliasId> {
        match self.variant() {
            Variant::RoomId => {
                either::Either::Left(RoomId { full_id: self.full_id, colon_idx: self.colon_idx })
            }
            Variant::RoomAliasId => either::Either::Right(RoomAliasId {
                full_id: self.full_id,
                colon_idx: self.colon_idx,
            }),
        }
    }

    fn variant(&self) -> Variant {
        match self.full_id.bytes().next() {
            Some(b'!') => Variant::RoomId,
            Some(b'#') => Variant::RoomAliasId,
            _ => unsafe { unreachable_unchecked() },
        }
    }
}

#[derive(PartialEq)]
enum Variant {
    RoomId,
    RoomAliasId,
}

/// Attempts to create a new Matrix room ID or a room alias ID from a string representation.
///
/// The string must either include the leading ! sigil, the localpart, a literal colon, and a
/// valid homeserver host or include the leading # sigil, the alias, a literal colon, and a
/// valid homeserver host.
fn try_from<S>(room_id_or_alias_id: S) -> Result<RoomIdOrAliasId, crate::Error>
where
    S: AsRef<str> + Into<Box<str>>,
{
    let colon_idx =
        ruma_identifiers_validation::room_id_or_alias_id::validate(room_id_or_alias_id.as_ref())?;
    Ok(RoomIdOrAliasId { full_id: room_id_or_alias_id.into(), colon_idx })
}

common_impls!(RoomIdOrAliasId, try_from, "a Matrix room ID or room alias ID");

impl From<RoomId> for RoomIdOrAliasId {
    fn from(RoomId { full_id, colon_idx }: RoomId) -> Self {
        Self { full_id, colon_idx }
    }
}

impl From<RoomAliasId> for RoomIdOrAliasId {
    fn from(RoomAliasId { full_id, colon_idx }: RoomAliasId) -> Self {
        Self { full_id, colon_idx }
    }
}

impl TryFrom<RoomIdOrAliasId> for RoomId {
    type Error = RoomAliasId;

    fn try_from(id: RoomIdOrAliasId) -> Result<RoomId, RoomAliasId> {
        match id.variant() {
            Variant::RoomId => Ok(RoomId { full_id: id.full_id, colon_idx: id.colon_idx }),
            Variant::RoomAliasId => {
                Err(RoomAliasId { full_id: id.full_id, colon_idx: id.colon_idx })
            }
        }
    }
}

impl TryFrom<RoomIdOrAliasId> for RoomAliasId {
    type Error = RoomId;

    fn try_from(id: RoomIdOrAliasId) -> Result<RoomAliasId, RoomId> {
        match id.variant() {
            Variant::RoomAliasId => {
                Ok(RoomAliasId { full_id: id.full_id, colon_idx: id.colon_idx })
            }
            Variant::RoomId => Err(RoomId { full_id: id.full_id, colon_idx: id.colon_idx }),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use super::RoomIdOrAliasId;
    use crate::Error;

    #[test]
    fn valid_room_id_or_alias_id_with_a_room_alias_id() {
        assert_eq!(
            RoomIdOrAliasId::try_from("#ruma:example.com")
                .expect("Failed to create RoomAliasId.")
                .as_ref(),
            "#ruma:example.com"
        );
    }

    #[test]
    fn valid_room_id_or_alias_id_with_a_room_id() {
        assert_eq!(
            RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
                .expect("Failed to create RoomId.")
                .as_ref(),
            "!29fhd83h92h0:example.com"
        );
    }

    #[test]
    fn missing_sigil_for_room_id_or_alias_id() {
        assert_eq!(
            RoomIdOrAliasId::try_from("ruma:example.com").unwrap_err(),
            Error::MissingLeadingSigil
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn serialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
        assert_eq!(
            serde_json::to_string(
                &RoomIdOrAliasId::try_from("#ruma:example.com")
                    .expect("Failed to create RoomAliasId.")
            )
            .expect("Failed to convert RoomAliasId to JSON."),
            r##""#ruma:example.com""##
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn serialize_valid_room_id_or_alias_id_with_a_room_id() {
        assert_eq!(
            serde_json::to_string(
                &RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
                    .expect("Failed to create RoomId.")
            )
            .expect("Failed to convert RoomId to JSON."),
            r#""!29fhd83h92h0:example.com""#
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn deserialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
        assert_eq!(
            serde_json::from_str::<RoomIdOrAliasId>(r##""#ruma:example.com""##)
                .expect("Failed to convert JSON to RoomAliasId"),
            RoomIdOrAliasId::try_from("#ruma:example.com").expect("Failed to create RoomAliasId.")
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn deserialize_valid_room_id_or_alias_id_with_a_room_id() {
        assert_eq!(
            serde_json::from_str::<RoomIdOrAliasId>(r##""!29fhd83h92h0:example.com""##)
                .expect("Failed to convert JSON to RoomId"),
            RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
                .expect("Failed to create RoomAliasId.")
        );
    }
}
<commit_msg>identifiers: Improve readability of one more method<commit_after>//! Matrix identifiers for places where a room ID or room alias ID are used interchangeably.

use std::{
    convert::{TryFrom, TryInto},
    fmt,
    hint::unreachable_unchecked,
    num::NonZeroU8,
};

use crate::{server_name::ServerName, RoomAliasId, RoomId};

/// A Matrix room ID or a Matrix room alias ID.
///
/// `RoomIdOrAliasId` is useful for APIs that accept either kind of room identifier. It is converted
/// from a string slice, and can be converted back into a string as needed. When converted from a
/// string slice, the variant is determined by the leading sigil character.
///
/// ```
/// # use std::convert::TryFrom;
/// # use ruma_identifiers::RoomIdOrAliasId;
/// assert_eq!(
///     RoomIdOrAliasId::try_from("#ruma:example.com").unwrap().as_ref(),
///     "#ruma:example.com"
/// );
///
/// assert_eq!(
///     RoomIdOrAliasId::try_from("!n8f893n9:example.com").unwrap().as_ref(),
///     "!n8f893n9:example.com"
/// );
/// ```
#[derive(Clone)]
pub struct RoomIdOrAliasId {
    full_id: Box<str>,
    colon_idx: NonZeroU8,
}

impl fmt::Debug for RoomIdOrAliasId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.full_id)
    }
}

impl RoomIdOrAliasId {
    /// Returns the local part (everything after the `!` or `#` and before the first colon).
    pub fn localpart(&self) -> &str {
        &self.full_id[1..self.colon_idx.get() as usize]
    }

    /// Returns the server name of the room (alias) ID.
    pub fn server_name(&self) -> &ServerName {
        self.full_id[self.colon_idx.get() as usize + 1..].try_into().unwrap()
    }

    /// Whether this is a room id (starts with `'!'`)
    pub fn is_room_id(&self) -> bool {
        self.variant() == Variant::RoomId
    }

    /// Whether this is a room alias id (starts with `'#'`)
    pub fn is_room_alias_id(&self) -> bool {
        self.variant() == Variant::RoomAliasId
    }

    /// Turn this `RoomIdOrAliasId` into `Either<RoomId, RoomAliasId>`
    #[cfg(feature = "either")]
    #[cfg_attr(docsrs, doc(cfg(feature = "either")))]
    pub fn into_either(self) -> either::Either<RoomId, RoomAliasId> {
        match self.variant() {
            Variant::RoomId => {
                either::Either::Left(RoomId { full_id: self.full_id, colon_idx: self.colon_idx })
            }
            Variant::RoomAliasId => either::Either::Right(RoomAliasId {
                full_id: self.full_id,
                colon_idx: self.colon_idx,
            }),
        }
    }

    fn variant(&self) -> Variant {
        match self.full_id.bytes().next() {
            Some(b'!') => Variant::RoomId,
            Some(b'#') => Variant::RoomAliasId,
            _ => unsafe { unreachable_unchecked() },
        }
    }
}

#[derive(PartialEq)]
enum Variant {
    RoomId,
    RoomAliasId,
}

/// Attempts to create a new Matrix room ID or a room alias ID from a string representation.
///
/// The string must either include the leading ! sigil, the localpart, a literal colon, and a
/// valid homeserver host or include the leading # sigil, the alias, a literal colon, and a
/// valid homeserver host.
fn try_from<S>(room_id_or_alias_id: S) -> Result<RoomIdOrAliasId, crate::Error>
where
    S: AsRef<str> + Into<Box<str>>,
{
    let colon_idx =
        ruma_identifiers_validation::room_id_or_alias_id::validate(room_id_or_alias_id.as_ref())?;
    Ok(RoomIdOrAliasId { full_id: room_id_or_alias_id.into(), colon_idx })
}

common_impls!(RoomIdOrAliasId, try_from, "a Matrix room ID or room alias ID");

impl From<RoomId> for RoomIdOrAliasId {
    fn from(RoomId { full_id, colon_idx }: RoomId) -> Self {
        Self { full_id, colon_idx }
    }
}

impl From<RoomAliasId> for RoomIdOrAliasId {
    fn from(RoomAliasId { full_id, colon_idx }: RoomAliasId) -> Self {
        Self { full_id, colon_idx }
    }
}

impl TryFrom<RoomIdOrAliasId> for RoomId {
    type Error = RoomAliasId;

    fn try_from(id: RoomIdOrAliasId) -> Result<RoomId, RoomAliasId> {
        match id.variant() {
            Variant::RoomId => Ok(RoomId { full_id: id.full_id, colon_idx: id.colon_idx }),
            Variant::RoomAliasId => {
                Err(RoomAliasId { full_id: id.full_id, colon_idx: id.colon_idx })
            }
        }
    }
}

impl TryFrom<RoomIdOrAliasId> for RoomAliasId {
    type Error = RoomId;

    fn try_from(id: RoomIdOrAliasId) -> Result<RoomAliasId, RoomId> {
        match id.variant() {
            Variant::RoomAliasId => {
                Ok(RoomAliasId { full_id: id.full_id, colon_idx: id.colon_idx })
            }
            Variant::RoomId => Err(RoomId { full_id: id.full_id, colon_idx: id.colon_idx }),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::convert::TryFrom;

    use super::RoomIdOrAliasId;
    use crate::Error;

    #[test]
    fn valid_room_id_or_alias_id_with_a_room_alias_id() {
        assert_eq!(
            RoomIdOrAliasId::try_from("#ruma:example.com")
                .expect("Failed to create RoomAliasId.")
                .as_ref(),
            "#ruma:example.com"
        );
    }

    #[test]
    fn valid_room_id_or_alias_id_with_a_room_id() {
        assert_eq!(
            RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
                .expect("Failed to create RoomId.")
                .as_ref(),
            "!29fhd83h92h0:example.com"
        );
    }

    #[test]
    fn missing_sigil_for_room_id_or_alias_id() {
        assert_eq!(
            RoomIdOrAliasId::try_from("ruma:example.com").unwrap_err(),
            Error::MissingLeadingSigil
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn serialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
        assert_eq!(
            serde_json::to_string(
                &RoomIdOrAliasId::try_from("#ruma:example.com")
                    .expect("Failed to create RoomAliasId.")
            )
            .expect("Failed to convert RoomAliasId to JSON."),
            r##""#ruma:example.com""##
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn serialize_valid_room_id_or_alias_id_with_a_room_id() {
        assert_eq!(
            serde_json::to_string(
                &RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
                    .expect("Failed to create RoomId.")
            )
            .expect("Failed to convert RoomId to JSON."),
            r#""!29fhd83h92h0:example.com""#
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn deserialize_valid_room_id_or_alias_id_with_a_room_alias_id() {
        assert_eq!(
            serde_json::from_str::<RoomIdOrAliasId>(r##""#ruma:example.com""##)
                .expect("Failed to convert JSON to RoomAliasId"),
            RoomIdOrAliasId::try_from("#ruma:example.com").expect("Failed to create RoomAliasId.")
        );
    }

    #[cfg(feature = "serde")]
    #[test]
    fn deserialize_valid_room_id_or_alias_id_with_a_room_id() {
        assert_eq!(
            serde_json::from_str::<RoomIdOrAliasId>(r##""!29fhd83h92h0:example.com""##)
                .expect("Failed to convert JSON to RoomId"),
            RoomIdOrAliasId::try_from("!29fhd83h92h0:example.com")
                .expect("Failed to create RoomAliasId.")
        );
    }
}
<|endoftext|>


<commit_before>use std::io::{Read};
use std::io;
use std::env;
use std::string::{String};
use std::fs::File;
use std::vec;
use std::collections::HashMap;

const CHUNK: usize = 4192;

fn get_pushed_data(data: Vec<u8>, length: usize) -> HashMap<String, String>
{
	let mut buf = data;
	let mut i = 0;
	let mut parameters = HashMap::new();

	while i < length
	{
		let mut name: String = String::new();
		let mut data: String = String::new();

		while buf[i] as char != '='
		{
			name.push(buf[i] as char);
			i += 1;
		}

		i += 1;

		while i < length && buf[i] as char != '&'
		{
			data.push(buf[i] as char);
			i += 1;
		}
		i += 1;
		parameters.insert(name, data);
	}

	return parameters;
}

fn get_http_request() -> HashMap<String,String> {
	let mut method = env::var("REQUEST_METHOD").unwrap();
	let mut contents: Vec<u8> = Vec::new();
	let mut length = 0;

	match method.as_ref()
	{
		"POST" =>
		{
			method = env::var("CONTENT_LENGTH").unwrap();
			let mut total: usize = method.trim().parse().unwrap();
			let mut buf = [0u8; CHUNK];

			let mut current = 0;

			let mut stream = io::stdin(); //File::open("/dev/stdin").unwrap();
			while current < total
			{
				let bytes = stream.read(&mut buf[0..CHUNK]).unwrap();
				current += bytes;

				for byte in buf.iter() {
					contents.push(*byte);
					length += 1;
				}
			}

			println!("
");
			for i in contents.iter()
			{
				print!("{}", *i as char);
			}
			println!("
		{
			let query_string = env::var("QUERY_STRING").unwrap();

			for byte in query_string.as_bytes()
			{
				contents.push(*byte);
				length += 1;
			}

		}

		_ =>
		{

		}
	}

	get_pushed_data(contents, length)
}

fn main() {
	println!("Content-Type: text/html\r\n\r\n");
 	println!("
hi
");

	let mut params: HashMap<String,String> = get_http_request();
	for (name, value) in params.iter()
	{
		println!("
{} and {}
", name, value);
	}
	println!("
DONE!
");
}
<commit_msg>too fucking late at night!!<commit_after>/*
	Start of basic CGI for Rust.
	Author: Al Poole <netstar@gmail.com>

	TODO: Everything!!!

*/

use std::io::{Read};
use std::io;
use std::env;
use std::string::{String};
use std::fs::File;
use std::vec;
use std::collections::HashMap;

const CHUNK: usize = 4192;

struct CGI {
        params: HashMap<String,String>,
}

impl CGI {

pub fn new(&self) -> CGI
{
       self.params = self.get_http_request();
}

fn get_pushed_data(self, data: Vec<u8>, length: usize) -> HashMap<String, String>
{
	let mut buf = data;
	let mut i = 0;
	let mut parameters = HashMap::new();

	while i < length
	{
		let mut name: String = String::new();
		let mut data: String = String::new();

		while buf[i] as char != '='
		{
			name.push(buf[i] as char);
			i += 1;
		}

		i += 1;

		while i < length && buf[i] as char != '&'
		{
			data.push(buf[i] as char);
			i += 1;
		}
		i += 1;
		parameters.insert(name, data);
	}

	return parameters;
}

fn get_http_request(self) -> HashMap<String,String> {
	let mut method = env::var("REQUEST_METHOD").unwrap();
	let mut contents: Vec<u8> = Vec::new();
	let mut length = 0;

	match method.as_ref()
	{
		"POST" =>
		{
			method = env::var("CONTENT_LENGTH").unwrap();
			let mut total: usize = method.trim().parse().unwrap();
			let mut buf = [0u8; CHUNK];

			let mut current = 0;

			let mut stream = io::stdin(); //File::open("/dev/stdin").unwrap();
			while current < total
			{
				let bytes = stream.read(&mut buf[0..CHUNK]).unwrap();
				current += bytes;

				for byte in buf.iter() {
					contents.push(*byte);
					length += 1;
				}
			}

			println!("
");
			for i in contents.iter()
			{
				print!("{}", *i as char);
			}
			println!("
		{
			let query_string = env::var("QUERY_STRING").unwrap();

			for byte in query_string.as_bytes()
			{
				contents.push(*byte);
				length += 1;
			}

		}

		_ =>
		{

		}
	}

	self.get_pushed_data(contents, length)
}

pub fn param(&self, key: String) -> String
{
	let result = String::new();

	for (name, value) in self.params.iter()
	{
		if name == key
		{
			result.push_str(value);
			return result;
	.	}

	}
}

}

fn main() {
	println!("Content-Type: text/html\r\n\r\n");
 	println!("
hi
");

	let mut cgi = CGI::new();

	let value = cgi.param("name".to_string());

	println!("
value is {}
", value);

	println!("
DONE!
");
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::io::Read;

macro_rules! error {
    ($fmt:expr) => (writeln!(&mut std::io::stderr(), $fmt));
    ($fmt:expr,$($x:tt)*) => (writeln!(&mut std::io::stderr(), $fmt, $( $x )*));
}
/*
fn compile_number(mut n: u32) {
    for i in io::stdin().bytes() {
        let b = i.unwrap();
        let c = char::from(b);
        if c.is_whitespace() {
            break;
        }
        if false == c.is_numeric() {
            panic!();
        }
        n = n * 10 + c.to_digit(10).unwrap();
    }

    println!("\t.text\n\t\
            .global _intfn\n\
            _intfn:\n\t\
            mov ${}, %rax\n\t\
            ret", n);
}

fn compile_string() {
    let mut is_escape = false;
    let mut buf = String::new();

    for i in io::stdin().bytes() {
        let b = i.unwrap();
        let c = char::from(b);

        if false == is_escape {
            if c == '"' {
                break;
            }

            if c == '\\' {
                is_escape = true;
                continue;
            }
        }

        buf.push(c);
    }

    buf.push('\0');

    println!("\t.text\n\t\
            .mydata:\n\t\
            .string \"{}\"\n\t\
            .text\n\t\
            .global _stringfn\n\
            _stringfn:\n\t\
            lea .mydata(%rip), %rax\n\t\
            ret", buf);
}
*/

fn compile_number(mut n: u32) {
    for i in io::stdin().bytes() {
        let b = i.unwrap();
        let c = char::from(b);
        if c.is_whitespace() {
            break;
        }
        if false == c.is_numeric() {
            panic!();
        }
        n = n * 10 + c.to_digit(10).unwrap();
    }

    println!("\t.text\n\t\
            .global intfn\n\
            intfn:\n\t\
            mov ${}, %rax\n\t\
            ret", n);
}

fn compile_string() {
    let mut is_escape = false;
    let mut buf = String::new();

    for i in io::stdin().bytes() {
        let b = i.unwrap();
        let c = char::from(b);

        if false == is_escape {
            if c == '"' {
                break;
            }

            if c == '\\' {
                is_escape = true;
                continue;
            }
        }

        buf.push(c);
    }

    buf.push('\0');

    println!("\t.text\n\t\
            .mydata:\n\t\
            .string \"{}\"\n\t\
            .text\n\t\
            .global stringfn\n\
            stringfn:\n\t\
            lea .mydata(%rip), %rax\n\t\
            ret", buf);
}

fn compile() {
    let c =  char::from(io::stdin().bytes().next().and_then(|r| r.ok()).unwrap());

    if c.is_digit(10) {
        return compile_number(c.to_digit(10).unwrap());
    } else if c == '"' {
        return compile_string();
    }
    let _ = error!("error");
}

fn main() {
    compile();
}

/*
fn main() {
    let mut input = String::new();

    io::stdin().read_line(&mut input)
        .expect("Failed to read line");

    let val = input.trim();

    error!("{}{}\n", val, val);

    println!("\t.text\n\t\
            .global _mymain\n\
            _mymain:\n\t\
            mov ${}, %eax\n\t\
            ret\n", val);
}
*/
<commit_msg>removed temp file<commit_after><|endoftext|>


<commit_before>#![crate_id = "app"]
#![crate_type = "bin"]
#![deny(warnings, missing_doc)]
#![feature(macro_rules, phase)]

//! A rust-compress application that allows testing of implemented
//! algorithms and their combinations using a simple command line.
//! Example invocations:
//! echo -n "abracadabra" | ./app bwt | xxd
//! echo "banana" | ./app bwt | ./app -d

#[phase(syntax, link)] extern crate log;
extern crate compress;
extern crate collections;

use collections::HashMap;
use std::{io, os, str};
use compress::{bwt, lz4};
//use compress::entropy::ari;

static MAGIC    : u32   = 0x73632172;   //=r!cs

struct Config {
    exe_name: ~str,
    methods: Vec<~str>,
    block_size: uint,
    decompress: bool,
}

impl Config {
    fn query(args: &[~str]) -> Config {
        let mut cfg = Config {
            exe_name: args[0].clone(),
            methods: Vec::new(),
            block_size: 1<<16,
            decompress: false,
        };
        let mut handlers: HashMap<&str,|&str, &mut Config|> = HashMap::new();
        handlers.insert("d",|_, cfg| { cfg.decompress = true; });
        handlers.insert("block",|b, cfg| {
            cfg.block_size = from_str(b).unwrap();
        });

        for arg in args.iter().skip(1) {
            if arg.starts_with("-") {
                match handlers.mut_iter().find(|&(&k,_)| arg.slice_from(1).starts_with(k)) {
                    Some((k,h)) => (*h)(arg.slice_from(1+k.len()), &mut cfg),
                    None => println!("Warning: unrecognized option: {}", *arg),
                }
            }else {
                cfg.methods.push(arg.to_owned());
            }
        }
        cfg
    }
}

struct Pass {
    encode: |Box<Writer>,&Config|:'static -> Box<io::Writer>,
    decode: |Box<Reader>,&Config|:'static -> Box<io::Reader>,
    info: ~str,
}

/// main entry point
pub fn main() {
    let mut passes: HashMap<~str,Pass> = HashMap::new();
    passes.insert("dummy".to_str(), Pass {
        encode: |w,_| w,
        decode: |r,_| r,
        info: "pass-through".to_str(),
    });
    /* // unclear what to do with Ari since it requires the size to be known
    passes.insert(~"ari", Pass {
        encode: |w,_c| {
            ~ari::ByteEncoder::new(w) as ~Writer
        },
        decode: |r,_c| {
            ~ari::ByteDecoder::new(r) as ~Reader
        },
        info: ~"Adaptive arithmetic byte coder",
    });*/
    passes.insert("bwt".to_str(), Pass {
        encode: |w,c| {
            box bwt::Encoder::new(w, c.block_size) as Box<Writer>
        },
        decode: |r,_c| {
            box bwt::Decoder::new(r, true) as Box<Reader>
        },
        info: "Burrows-Wheeler Transformation".to_str(),
    });
    passes.insert("mtf".to_str(), Pass {
        encode: |w,_c| {
            box bwt::mtf::Encoder::new(w) as Box<Writer>
        },
        decode: |r,_c| {
            box bwt::mtf::Decoder::new(r) as Box<Reader>
        },
        info: "Move-To-Front Transformation".to_str(),
    });
    /* // looks like we are missing the encoder implementation
    passes.insert(~"flate", Pass {
        encode: |w,_c| {
            ~flate::Encoder::new(w, true) as ~Writer
        },
        decode: |r,_c| {
            ~flate::Decoder::new(r, true) as ~Reader
        },
        info: ~"Standardized Ziv-Lempel + Huffman variant",
    });*/
    passes.insert("lz4".to_str(), Pass {
        encode: |w,_c| {
            box lz4::Encoder::new(w) as Box<Writer>
        },
        decode: |r,_c| { // LZ4 decoder seem to work
            box lz4::Decoder::new(r) as Box<Reader>
        },
        info: "Ziv-Lempel derivative, focused at speed".to_str(),
    });

    let config = Config::query(os::args().as_slice());
    let mut input = io::stdin();
    let mut output = io::stdout();
    if config.decompress {
        assert!(config.methods.is_empty(), "Decompression methods are set in stone");
        match input.read_le_u32() {
            Ok(magic) if magic != MAGIC => {
                error!("Input is not a rust-compress archive");
                return
            },
            Err(e) => {
                error!("Unable to read input: {}", e.to_str());
                return
            },
            _ => () //OK
        }
        let methods = Vec::from_fn( input.read_u8().unwrap() as uint, |_| {
            let len = input.read_u8().unwrap() as uint;
            let bytes = input.read_exact(len).unwrap();
            str::from_utf8(bytes.as_slice()).unwrap().to_owned()
        });
        let mut rsum: Box<Reader> = box input;
        for met in methods.iter() {
            info!("Found pass {}", *met);
            match passes.find_mut(met) {
                Some(pa) => rsum = (pa.decode)(rsum, &config),
                None => fail!("Pass is not implemented"),
            }
        }
        io::util::copy(&mut rsum, &mut output).unwrap();
    }else if config.methods.is_empty() {
        println!("rust-compress test application");
        println!("Usage:");
        println!("\t{} <options> <method1> .. <methodN> <input >output", config.exe_name);
        println!("Options:");
        println!("\t-d (to decompress)");
        println!("\t-block<N> (BWT block size)");
        println!("Passes:");
        for (name,pa) in passes.iter() {
            println!("\t{} = {}", *name, pa.info);
        }
    }else {
        output.write_le_u32(MAGIC).unwrap();
        output.write_u8(config.methods.len() as u8).unwrap();
        for met in config.methods.iter() {
            output.write_u8(met.len() as u8).unwrap();
            output.write_str(*met).unwrap();
        }
        let mut wsum: Box<Writer> = box output;
        for met in config.methods.iter() {
            match passes.find_mut(met) {
                Some(pa) => wsum = (pa.encode)(wsum, &config),
                None => fail!("Pass {} is not implemented", *met)
            }
        }
        io::util::copy(&mut input, &mut wsum).unwrap();
        wsum.flush().unwrap();
    }
}
<commit_msg>APP - unlocked Ari block<commit_after>#![crate_id = "app"]
#![crate_type = "bin"]
#![deny(warnings, missing_doc)]
#![feature(macro_rules, phase)]

//! A rust-compress application that allows testing of implemented
//! algorithms and their combinations using a simple command line.
//! Example invocations:
//! echo -n "abracadabra" | ./app bwt | xxd
//! echo "banana" | ./app bwt | ./app -d

#[phase(syntax, link)] extern crate log;
extern crate compress;
extern crate collections;

use collections::HashMap;
use std::{io, os, str};
use compress::{bwt, lz4};
use compress::entropy::ari;

static MAGIC    : u32   = 0x73632172;   //=r!cs

struct Config {
    exe_name: ~str,
    methods: Vec<~str>,
    block_size: uint,
    decompress: bool,
}

impl Config {
    fn query(args: &[~str]) -> Config {
        let mut cfg = Config {
            exe_name: args[0].clone(),
            methods: Vec::new(),
            block_size: 1<<16,
            decompress: false,
        };
        let mut handlers: HashMap<&str,|&str, &mut Config|> = HashMap::new();
        handlers.insert("d",|_, cfg| { cfg.decompress = true; });
        handlers.insert("block",|b, cfg| {
            cfg.block_size = from_str(b).unwrap();
        });

        for arg in args.iter().skip(1) {
            if arg.starts_with("-") {
                match handlers.mut_iter().find(|&(&k,_)| arg.slice_from(1).starts_with(k)) {
                    Some((k,h)) => (*h)(arg.slice_from(1+k.len()), &mut cfg),
                    None => println!("Warning: unrecognized option: {}", *arg),
                }
            }else {
                cfg.methods.push(arg.to_owned());
            }
        }
        cfg
    }
}

struct Pass {
    encode: |Box<Writer>, &Config|: 'static -> Box<io::Writer>,
    decode: |Box<Reader>, &Config|: 'static -> Box<io::Reader>,
    info: ~str,
}

/// main entry point
pub fn main() {
    let mut passes: HashMap<~str,Pass> = HashMap::new();
    passes.insert("dummy".to_str(), Pass {
        encode: |w,_| w,
        decode: |r,_| r,
        info: "pass-through".to_str(),
    });
    passes.insert("ari".to_str(), Pass {
        encode: |w,_c| {
            box ari::ByteEncoder::new(w) as Box<Writer>
        },
        decode: |r,_c| {
            box ari::ByteDecoder::new(r) as Box<Reader>
        },
        info: "Adaptive arithmetic byte coder".to_str(),
    });
    passes.insert("bwt".to_str(), Pass {
        encode: |w,c| {
            box bwt::Encoder::new(w, c.block_size) as Box<Writer>
        },
        decode: |r,_c| {
            box bwt::Decoder::new(r, true) as Box<Reader>
        },
        info: "Burrows-Wheeler Transformation".to_str(),
    });
    passes.insert("mtf".to_str(), Pass {
        encode: |w,_c| {
            box bwt::mtf::Encoder::new(w) as Box<Writer>
        },
        decode: |r,_c| {
            box bwt::mtf::Decoder::new(r) as Box<Reader>
        },
        info: "Move-To-Front Transformation".to_str(),
    });
    /* // looks like we are missing the encoder implementation
    passes.insert(~"flate", Pass {
        encode: |w,_c| {
            ~flate::Encoder::new(w, true) as ~Writer
        },
        decode: |r,_c| {
            ~flate::Decoder::new(r, true) as ~Reader
        },
        info: ~"Standardized Ziv-Lempel + Huffman variant",
    });*/
    passes.insert("lz4".to_str(), Pass {
        encode: |w,_c| {
            box lz4::Encoder::new(w) as Box<Writer>
        },
        decode: |r,_c| { // LZ4 decoder seem to work
            box lz4::Decoder::new(r) as Box<Reader>
        },
        info: "Ziv-Lempel derivative, focused at speed".to_str(),
    });

    let config = Config::query(os::args().as_slice());
    let mut input = io::stdin();
    let mut output = io::stdout();
    if config.decompress {
        assert!(config.methods.is_empty(), "Decompression methods are set in stone");
        match input.read_le_u32() {
            Ok(magic) if magic != MAGIC => {
                error!("Input is not a rust-compress archive");
                return
            },
            Err(e) => {
                error!("Unable to read input: {}", e.to_str());
                return
            },
            _ => () //OK
        }
        let methods = Vec::from_fn( input.read_u8().unwrap() as uint, |_| {
            let len = input.read_u8().unwrap() as uint;
            let bytes = input.read_exact(len).unwrap();
            str::from_utf8(bytes.as_slice()).unwrap().to_owned()
        });
        let mut rsum: Box<Reader> = box input;
        for met in methods.iter() {
            info!("Found pass {}", *met);
            match passes.find_mut(met) {
                Some(pa) => rsum = (pa.decode)(rsum, &config),
                None => fail!("Pass is not implemented"),
            }
        }
        io::util::copy(&mut rsum, &mut output).unwrap();
    }else if config.methods.is_empty() {
        println!("rust-compress test application");
        println!("Usage:");
        println!("\t{} <options> <method1> .. <methodN> <input >output", config.exe_name);
        println!("Options:");
        println!("\t-d (to decompress)");
        println!("\t-block<N> (BWT block size)");
        println!("Passes:");
        for (name,pa) in passes.iter() {
            println!("\t{} = {}", *name, pa.info);
        }
    }else {
        output.write_le_u32(MAGIC).unwrap();
        output.write_u8(config.methods.len() as u8).unwrap();
        for met in config.methods.iter() {
            output.write_u8(met.len() as u8).unwrap();
            output.write_str(*met).unwrap();
        }
        let mut wsum: Box<Writer> = box output;
        for met in config.methods.iter() {
            match passes.find_mut(met) {
                Some(pa) => wsum = (pa.encode)(wsum, &config),
                None => fail!("Pass {} is not implemented", *met)
            }
        }
        io::util::copy(&mut input, &mut wsum).unwrap();
        wsum.flush().unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

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

use grpcio::{ChannelBuilder, Environment};
use kvproto::{
    kvrpcpb::*,
    metapb::{Peer, Region},
    tikvpb::TikvClient,
};
use test_raftstore::*;
use tikv_util::{config::ReadableDuration, HandyRwLock};

fn deadlock(client: &TikvClient, ctx: Context, key1: &[u8], ts: u64) -> bool {
    let key1 = key1.to_vec();
    let mut key2 = key1.clone();
    key2.push(0);
    must_kv_pessimistic_lock(client, ctx.clone(), key1.clone(), ts);
    must_kv_pessimistic_lock(client, ctx.clone(), key2.clone(), ts + 1);

    let (client_clone, mut ctx_clone, key1_clone) = (client.clone(), ctx.clone(), key1.clone());
    let handle = thread::spawn(move || {
        // `resource_group_tag` is set to check if the wait chain reported by the deadlock error
        // carries the correct information.
        ctx_clone.set_resource_group_tag(b"tag1".to_vec());
        let resp = kv_pessimistic_lock(
            &client_clone,
            ctx_clone,
            vec![key1_clone],
            ts + 1,
            ts + 1,
            false,
        );
        assert_eq!(resp.errors.len(), 1);
        assert!(resp.errors[0].has_locked(), "{:?}", resp.errors[0]);
    });
    // Sleep to make sure txn(ts+1) is waiting for txn(ts)
    thread::sleep(Duration::from_millis(100));
    let mut ctx2 = ctx.clone();
    ctx2.set_resource_group_tag(b"tag2".to_vec());
    let resp = kv_pessimistic_lock(client, ctx2, vec![key2.clone()], ts, ts, false);
    handle.join().unwrap();

    // Clean up
    must_kv_pessimistic_rollback(client, ctx.clone(), key1.clone(), ts);
    must_kv_pessimistic_rollback(client, ctx, key2.clone(), ts + 1);

    assert_eq!(resp.errors.len(), 1);
    if resp.errors[0].has_deadlock() {
        let wait_chain = resp.errors[0].get_deadlock().get_wait_chain();
        assert_eq!(wait_chain[0].get_txn(), ts + 1);
        assert_eq!(wait_chain[0].get_wait_for_txn(), ts);
        assert_eq!(wait_chain[0].get_key(), key1.as_slice());
        assert_eq!(wait_chain[0].get_resource_group_tag(), b"tag1");
        assert_eq!(wait_chain[1].get_txn(), ts);
        assert_eq!(wait_chain[1].get_wait_for_txn(), ts + 1);
        assert_eq!(wait_chain[1].get_key(), key2.as_slice());
        assert_eq!(wait_chain[1].get_resource_group_tag(), b"tag2");
    }
    resp.errors[0].has_deadlock()
}

fn build_leader_client(cluster: &mut Cluster<ServerCluster>, key: &[u8]) -> (TikvClient, Context) {
    let region_id = cluster.get_region_id(key);
    let leader = cluster.leader_of_region(region_id).unwrap();
    let epoch = cluster.get_region_epoch(region_id);

    let env = Arc::new(Environment::new(1));
    let channel =
        ChannelBuilder::new(env).connect(&cluster.sim.rl().get_addr(leader.get_store_id()));
    let client = TikvClient::new(channel);

    let mut ctx = Context::default();
    ctx.set_region_id(region_id);
    ctx.set_peer(leader);
    ctx.set_region_epoch(epoch);

    (client, ctx)
}

/// Creates a deadlock on the store containing key.
fn must_detect_deadlock(cluster: &mut Cluster<ServerCluster>, key: &[u8], ts: u64) {
    // Sometimes, deadlocks can't be detected at once due to leader change, but it will be
    // detected.
    for _ in 0..3 {
        let (client, ctx) = build_leader_client(cluster, key);
        if deadlock(&client, ctx, key, ts) {
            return;
        }
    }
    panic!("failed to detect deadlock");
}

fn deadlock_detector_leader_must_be(cluster: &mut Cluster<ServerCluster>, store_id: u64) {
    let leader_region = cluster.get_region(b"");
    assert_eq!(
        cluster
            .leader_of_region(leader_region.get_id())
            .unwrap()
            .get_store_id(),
        store_id
    );
    let leader_peer = find_peer_of_store(&leader_region, store_id);
    cluster
        .pd_client
        .region_leader_must_be(leader_region.get_id(), leader_peer);
}

fn must_transfer_leader(cluster: &mut Cluster<ServerCluster>, region_key: &[u8], store_id: u64) {
    let region = cluster.get_region(region_key);
    let target_peer = find_peer_of_store(&region, store_id);
    cluster.must_transfer_leader(region.get_id(), target_peer.clone());
    cluster
        .pd_client
        .region_leader_must_be(region.get_id(), target_peer);
    cluster.must_put(region_key, b"v");
}

/// Transfers the region containing region_key from source store to target peer.
///
/// REQUIRE: The source store must be the leader the region and the target store must not have
/// this region.
fn must_transfer_region(
    cluster: &mut Cluster<ServerCluster>,
    region_key: &[u8],
    source_store_id: u64,
    target_store_id: u64,
    target_peer_id: u64,
) {
    let target_peer = new_peer(target_store_id, target_peer_id);
    let region = cluster.get_region(region_key);
    cluster
        .pd_client
        .must_add_peer(region.get_id(), target_peer);
    must_transfer_leader(cluster, region_key, target_store_id);
    let source_peer = find_peer_of_store(&region, source_store_id);
    cluster
        .pd_client
        .must_remove_peer(region.get_id(), source_peer);
    cluster.must_put(region_key, b"v");
}

fn must_split_region(cluster: &mut Cluster<ServerCluster>, region_key: &[u8], split_key: &[u8]) {
    let region = cluster.get_region(region_key);
    cluster.must_split(&region, split_key);
    cluster.must_put(split_key, b"v");
}

fn must_merge_region(
    cluster: &mut Cluster<ServerCluster>,
    source_region_key: &[u8],
    target_region_key: &[u8],
) {
    let (source_id, target_id) = (
        cluster.get_region(source_region_key).get_id(),
        cluster.get_region(target_region_key).get_id(),
    );
    cluster.pd_client.must_merge(source_id, target_id);
    cluster.must_put(target_region_key, b"v");
}

fn find_peer_of_store(region: &Region, store_id: u64) -> Peer {
    region
        .get_peers()
        .iter()
        .find(|p| p.get_store_id() == store_id)
        .unwrap()
        .clone()
}

/// Creates a cluster with only one region and store(1) is the leader of the region.
fn new_cluster_for_deadlock_test(count: usize) -> Cluster<ServerCluster> {
    let mut cluster = new_server_cluster(0, count);
    cluster.cfg.pessimistic_txn.wait_for_lock_timeout = ReadableDuration::millis(500);
    cluster.cfg.pessimistic_txn.pipelined = false;
    let pd_client = Arc::clone(&cluster.pd_client);
    // Disable default max peer count check.
    pd_client.disable_default_operator();
    // Region 1 has 3 peers. And peer(1, 1) is the leader of region 1.
    let region_id = cluster.run_conf_change();
    pd_client.must_add_peer(region_id, new_peer(2, 2));
    pd_client.must_add_peer(region_id, new_peer(3, 3));
    cluster.must_transfer_leader(region_id, new_peer(1, 1));
    cluster.must_put(b"a", b"a");
    deadlock_detector_leader_must_be(&mut cluster, 1);
    must_detect_deadlock(&mut cluster, b"k", 10);
    cluster
}

#[test]
fn test_detect_deadlock_basic() {
    let mut cluster = new_cluster_for_deadlock_test(3);
    must_split_region(&mut cluster, b"k", b"k");
    must_transfer_leader(&mut cluster, b"", 1);
    must_transfer_leader(&mut cluster, b"k", 1);
    deadlock_detector_leader_must_be(&mut cluster, 1);

    // Detect on leader
    must_detect_deadlock(&mut cluster, b"k1", 10);
    // Detect on follower
    must_transfer_leader(&mut cluster, b"", 2);
    deadlock_detector_leader_must_be(&mut cluster, 2);
    must_detect_deadlock(&mut cluster, b"k1", 20);
}

#[test]
fn test_detect_deadlock_when_transfer_leader() {
    let mut cluster = new_cluster_for_deadlock_test(3);
    // Transfer the leader of region 1 to store(2).
    // The leader of deadlock detector should also be transfered to store(2).
    must_transfer_leader(&mut cluster, b"", 2);
    deadlock_detector_leader_must_be(&mut cluster, 2);
    must_detect_deadlock(&mut cluster, b"k", 10);
}

#[test]
fn test_detect_deadlock_when_split_region() {
    let mut cluster = new_cluster_for_deadlock_test(3);
    must_split_region(&mut cluster, b"", b"k1");
    // After split, the leader is still store(1).
    deadlock_detector_leader_must_be(&mut cluster, 1);
    must_detect_deadlock(&mut cluster, b"k", 10);
    // Transfer the new region's leader to store(2) and deadlock occours on it.
    must_transfer_leader(&mut cluster, b"k1", 2);
    deadlock_detector_leader_must_be(&mut cluster, 1);
    must_detect_deadlock(&mut cluster, b"k1", 10);
}

#[test]
fn test_detect_deadlock_when_transfer_region() {
    let mut cluster = new_cluster_for_deadlock_test(4);
    // Transfer the leader region to store(4) and the leader of deadlock detector should be
    // also transfered.
    must_transfer_region(&mut cluster, b"k", 1, 4, 4);
    deadlock_detector_leader_must_be(&mut cluster, 4);
    must_detect_deadlock(&mut cluster, b"k", 10);

    must_split_region(&mut cluster, b"", b"k1");
    // Transfer the new region to store(1). It shouldn't affect deadlock detector.
    must_transfer_region(&mut cluster, b"k1", 4, 1, 5);
    deadlock_detector_leader_must_be(&mut cluster, 4);
    must_detect_deadlock(&mut cluster, b"k", 10);
    must_detect_deadlock(&mut cluster, b"k1", 10);

    // Transfer the new region back to store(4) which will send a role change message with empty
    // key range. It shouldn't affect deadlock detector.
    must_transfer_region(&mut cluster, b"k1", 1, 4, 6);
    deadlock_detector_leader_must_be(&mut cluster, 4);
    must_detect_deadlock(&mut cluster, b"k", 10);
    must_detect_deadlock(&mut cluster, b"k1", 10);
}

#[test]
fn test_detect_deadlock_when_merge_region() {
    let mut cluster = new_cluster_for_deadlock_test(3);

    // Source region will be destroyed.
    for as_target in &[false, true] {
        must_split_region(&mut cluster, b"", b"k1");
        if *as_target {
            must_merge_region(&mut cluster, b"k1", b"");
        } else {
            must_merge_region(&mut cluster, b"", b"k1");
        }
        deadlock_detector_leader_must_be(&mut cluster, 1);
        must_detect_deadlock(&mut cluster, b"k", 10);
    }

    // Leaders of two regions are on different store.
    for as_target in &[false, true] {
        must_split_region(&mut cluster, b"", b"k1");
        must_transfer_leader(&mut cluster, b"k1", 2);
        if *as_target {
            must_merge_region(&mut cluster, b"k1", b"");
            deadlock_detector_leader_must_be(&mut cluster, 1);
        } else {
            must_merge_region(&mut cluster, b"", b"k1");
            deadlock_detector_leader_must_be(&mut cluster, 2);
        }
        must_detect_deadlock(&mut cluster, b"k", 10);
        must_transfer_leader(&mut cluster, b"", 1);
    }
}
<commit_msg>tests: try to stablize the deadlock integration test cases (#12625)<commit_after>// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

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

use grpcio::{ChannelBuilder, Environment};
use kvproto::{
    kvrpcpb::*,
    metapb::{Peer, Region},
    tikvpb::TikvClient,
};
use test_raftstore::*;
use tikv_util::{config::ReadableDuration, HandyRwLock};

fn deadlock(client: &TikvClient, ctx: Context, key1: &[u8], ts: u64) -> bool {
    let key1 = key1.to_vec();
    let mut key2 = key1.clone();
    key2.push(0);
    must_kv_pessimistic_lock(client, ctx.clone(), key1.clone(), ts);
    must_kv_pessimistic_lock(client, ctx.clone(), key2.clone(), ts + 1);

    let (client_clone, mut ctx_clone, key1_clone) = (client.clone(), ctx.clone(), key1.clone());
    let handle = thread::spawn(move || {
        // `resource_group_tag` is set to check if the wait chain reported by the deadlock error
        // carries the correct information.
        ctx_clone.set_resource_group_tag(b"tag1".to_vec());
        let resp = kv_pessimistic_lock(
            &client_clone,
            ctx_clone,
            vec![key1_clone],
            ts + 1,
            ts + 1,
            false,
        );
        assert_eq!(resp.errors.len(), 1);
        assert!(resp.errors[0].has_locked(), "{:?}", resp.errors[0]);
    });
    // Sleep to make sure txn(ts+1) is waiting for txn(ts)
    thread::sleep(Duration::from_millis(300));
    let mut ctx2 = ctx.clone();
    ctx2.set_resource_group_tag(b"tag2".to_vec());
    let resp = kv_pessimistic_lock(client, ctx2, vec![key2.clone()], ts, ts, false);
    handle.join().unwrap();

    // Clean up
    must_kv_pessimistic_rollback(client, ctx.clone(), key1.clone(), ts);
    must_kv_pessimistic_rollback(client, ctx, key2.clone(), ts + 1);

    assert_eq!(resp.errors.len(), 1);
    if resp.errors[0].has_deadlock() {
        let wait_chain = resp.errors[0].get_deadlock().get_wait_chain();
        assert_eq!(wait_chain[0].get_txn(), ts + 1);
        assert_eq!(wait_chain[0].get_wait_for_txn(), ts);
        assert_eq!(wait_chain[0].get_key(), key1.as_slice());
        assert_eq!(wait_chain[0].get_resource_group_tag(), b"tag1");
        assert_eq!(wait_chain[1].get_txn(), ts);
        assert_eq!(wait_chain[1].get_wait_for_txn(), ts + 1);
        assert_eq!(wait_chain[1].get_key(), key2.as_slice());
        assert_eq!(wait_chain[1].get_resource_group_tag(), b"tag2");
    }
    resp.errors[0].has_deadlock()
}

fn build_leader_client(cluster: &mut Cluster<ServerCluster>, key: &[u8]) -> (TikvClient, Context) {
    let region_id = cluster.get_region_id(key);
    let leader = cluster.leader_of_region(region_id).unwrap();
    let epoch = cluster.get_region_epoch(region_id);

    let env = Arc::new(Environment::new(1));
    let channel =
        ChannelBuilder::new(env).connect(&cluster.sim.rl().get_addr(leader.get_store_id()));
    let client = TikvClient::new(channel);

    let mut ctx = Context::default();
    ctx.set_region_id(region_id);
    ctx.set_peer(leader);
    ctx.set_region_epoch(epoch);

    (client, ctx)
}

/// Creates a deadlock on the store containing key.
fn must_detect_deadlock(cluster: &mut Cluster<ServerCluster>, key: &[u8], ts: u64) {
    // Sometimes, deadlocks can't be detected at once due to leader change, but it will be
    // detected.
    for _ in 0..5 {
        let (client, ctx) = build_leader_client(cluster, key);
        if deadlock(&client, ctx, key, ts) {
            return;
        }
    }
    panic!("failed to detect deadlock");
}

fn deadlock_detector_leader_must_be(cluster: &mut Cluster<ServerCluster>, store_id: u64) {
    let leader_region = cluster.get_region(b"");
    assert_eq!(
        cluster
            .leader_of_region(leader_region.get_id())
            .unwrap()
            .get_store_id(),
        store_id
    );
    let leader_peer = find_peer_of_store(&leader_region, store_id);
    cluster
        .pd_client
        .region_leader_must_be(leader_region.get_id(), leader_peer);
}

fn must_transfer_leader(cluster: &mut Cluster<ServerCluster>, region_key: &[u8], store_id: u64) {
    let region = cluster.get_region(region_key);
    let target_peer = find_peer_of_store(&region, store_id);
    cluster.must_transfer_leader(region.get_id(), target_peer.clone());
    cluster
        .pd_client
        .region_leader_must_be(region.get_id(), target_peer);
    cluster.must_put(region_key, b"v");
}

/// Transfers the region containing region_key from source store to target peer.
///
/// REQUIRE: The source store must be the leader the region and the target store must not have
/// this region.
fn must_transfer_region(
    cluster: &mut Cluster<ServerCluster>,
    region_key: &[u8],
    source_store_id: u64,
    target_store_id: u64,
    target_peer_id: u64,
) {
    let target_peer = new_peer(target_store_id, target_peer_id);
    let region = cluster.get_region(region_key);
    cluster
        .pd_client
        .must_add_peer(region.get_id(), target_peer);
    must_transfer_leader(cluster, region_key, target_store_id);
    let source_peer = find_peer_of_store(&region, source_store_id);
    cluster
        .pd_client
        .must_remove_peer(region.get_id(), source_peer);
    cluster.must_put(region_key, b"v");
}

fn must_split_region(cluster: &mut Cluster<ServerCluster>, region_key: &[u8], split_key: &[u8]) {
    let region = cluster.get_region(region_key);
    cluster.must_split(&region, split_key);
    cluster.must_put(split_key, b"v");
}

fn must_merge_region(
    cluster: &mut Cluster<ServerCluster>,
    source_region_key: &[u8],
    target_region_key: &[u8],
) {
    let (source_id, target_id) = (
        cluster.get_region(source_region_key).get_id(),
        cluster.get_region(target_region_key).get_id(),
    );
    cluster.pd_client.must_merge(source_id, target_id);
    cluster.must_put(target_region_key, b"v");
}

fn find_peer_of_store(region: &Region, store_id: u64) -> Peer {
    region
        .get_peers()
        .iter()
        .find(|p| p.get_store_id() == store_id)
        .unwrap()
        .clone()
}

/// Creates a cluster with only one region and store(1) is the leader of the region.
fn new_cluster_for_deadlock_test(count: usize) -> Cluster<ServerCluster> {
    let mut cluster = new_server_cluster(0, count);
    cluster.cfg.pessimistic_txn.wait_for_lock_timeout = ReadableDuration::millis(500);
    cluster.cfg.pessimistic_txn.pipelined = false;
    let pd_client = Arc::clone(&cluster.pd_client);
    // Disable default max peer count check.
    pd_client.disable_default_operator();
    // Region 1 has 3 peers. And peer(1, 1) is the leader of region 1.
    let region_id = cluster.run_conf_change();
    pd_client.must_add_peer(region_id, new_peer(2, 2));
    pd_client.must_add_peer(region_id, new_peer(3, 3));
    cluster.must_transfer_leader(region_id, new_peer(1, 1));
    cluster.must_put(b"a", b"a");
    deadlock_detector_leader_must_be(&mut cluster, 1);
    must_detect_deadlock(&mut cluster, b"k", 10);
    cluster
}

#[test]
fn test_detect_deadlock_basic() {
    let mut cluster = new_cluster_for_deadlock_test(3);
    must_split_region(&mut cluster, b"k", b"k");
    must_transfer_leader(&mut cluster, b"", 1);
    must_transfer_leader(&mut cluster, b"k", 1);
    deadlock_detector_leader_must_be(&mut cluster, 1);

    // Detect on leader
    must_detect_deadlock(&mut cluster, b"k1", 10);
    // Detect on follower
    must_transfer_leader(&mut cluster, b"", 2);
    deadlock_detector_leader_must_be(&mut cluster, 2);
    must_detect_deadlock(&mut cluster, b"k1", 20);
}

#[test]
fn test_detect_deadlock_when_transfer_leader() {
    let mut cluster = new_cluster_for_deadlock_test(3);
    // Transfer the leader of region 1 to store(2).
    // The leader of deadlock detector should also be transfered to store(2).
    must_transfer_leader(&mut cluster, b"", 2);
    deadlock_detector_leader_must_be(&mut cluster, 2);
    must_detect_deadlock(&mut cluster, b"k", 10);
}

#[test]
fn test_detect_deadlock_when_split_region() {
    let mut cluster = new_cluster_for_deadlock_test(3);
    must_split_region(&mut cluster, b"", b"k1");
    // After split, the leader is still store(1).
    deadlock_detector_leader_must_be(&mut cluster, 1);
    must_detect_deadlock(&mut cluster, b"k", 10);
    // Transfer the new region's leader to store(2) and deadlock occours on it.
    must_transfer_leader(&mut cluster, b"k1", 2);
    deadlock_detector_leader_must_be(&mut cluster, 1);
    must_detect_deadlock(&mut cluster, b"k1", 10);
}

#[test]
fn test_detect_deadlock_when_transfer_region() {
    let mut cluster = new_cluster_for_deadlock_test(4);
    // Transfer the leader region to store(4) and the leader of deadlock detector should be
    // also transfered.
    must_transfer_region(&mut cluster, b"k", 1, 4, 4);
    deadlock_detector_leader_must_be(&mut cluster, 4);
    must_detect_deadlock(&mut cluster, b"k", 10);

    must_split_region(&mut cluster, b"", b"k1");
    // Transfer the new region to store(1). It shouldn't affect deadlock detector.
    must_transfer_region(&mut cluster, b"k1", 4, 1, 5);
    deadlock_detector_leader_must_be(&mut cluster, 4);
    must_detect_deadlock(&mut cluster, b"k", 10);
    must_detect_deadlock(&mut cluster, b"k1", 10);

    // Transfer the new region back to store(4) which will send a role change message with empty
    // key range. It shouldn't affect deadlock detector.
    must_transfer_region(&mut cluster, b"k1", 1, 4, 6);
    deadlock_detector_leader_must_be(&mut cluster, 4);
    must_detect_deadlock(&mut cluster, b"k", 10);
    must_detect_deadlock(&mut cluster, b"k1", 10);
}

#[test]
fn test_detect_deadlock_when_merge_region() {
    let mut cluster = new_cluster_for_deadlock_test(3);

    // Source region will be destroyed.
    for as_target in &[false, true] {
        must_split_region(&mut cluster, b"", b"k1");
        if *as_target {
            must_merge_region(&mut cluster, b"k1", b"");
        } else {
            must_merge_region(&mut cluster, b"", b"k1");
        }
        deadlock_detector_leader_must_be(&mut cluster, 1);
        must_detect_deadlock(&mut cluster, b"k", 10);
    }

    // Leaders of two regions are on different store.
    for as_target in &[false, true] {
        must_split_region(&mut cluster, b"", b"k1");
        must_transfer_leader(&mut cluster, b"k1", 2);
        if *as_target {
            must_merge_region(&mut cluster, b"k1", b"");
            deadlock_detector_leader_must_be(&mut cluster, 1);
        } else {
            must_merge_region(&mut cluster, b"", b"k1");
            deadlock_detector_leader_must_be(&mut cluster, 2);
        }
        must_detect_deadlock(&mut cluster, b"k", 10);
        must_transfer_leader(&mut cluster, b"", 1);
    }
}
<|endoftext|>


<commit_before>use std::f64;
use std::i64;
use rand::Rng;
use error::StatsError;
use function::factorial;
use function::gamma;
use result::Result;
use super::{Distribution, Univariate, Discrete};

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Poisson {
    lambda: f64
}

impl Poisson {
    pub fn new(lambda: f64) -> Result<Poisson> {
        if lambda.is_nan() || lambda < 0.0 {
            Err(StatsError::BadParams)
        } else {
            Ok(Poisson{lambda: lambda})
        }
    }

    pub fn lambda(&self) -> f64 {
        self.lambda
    }
}

impl Distribution for Poisson {
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        0.0
    }
}

impl Univariate for Poisson {
    fn mean(&self) -> f64 {
        self.lambda
    }

    fn variance(&self) -> f64 {
        self.lambda
    }

    fn std_dev(&self) -> f64 {
        self.variance().sqrt()
    }

    fn entropy(&self) -> f64 {
        0.5 * (2.0 * f64::consts::PI * f64::consts::E * self.lambda).ln()
        - 1.0 / (12.0 * self.lambda)
        - 1.0 / (24.0 * self.lambda * self.lambda)
        - 19.0 / (360.0 * self.lambda * self.lambda * self.lambda)
    }

    fn skewness(&self) -> f64 {
       1.0 / self.lambda.sqrt()
    }

    fn median(&self) -> f64 {
        (self.lambda + 1.0 / 3.0 - 0.02 / self.lambda).floor()
    }

    fn cdf(&self, x: f64) -> f64 {
        1.0 - gamma::gamma_lr(x + 1.0, self.lambda).unwrap()
    }
}

impl Discrete for Poisson {
    fn mode(&self) -> i64 {
        self.lambda.floor() as i64
    }

    fn min(&self) -> i64 {
        0
    }

    fn max(&self) -> i64 {
        i64::MAX
    }

    fn pmf(&self, x: i64) -> f64 {
        if x < 0 {
            panic!("{}", StatsError::ArgNotNegative("x"));
        }
        (-self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x as u64)).exp()
    }

    fn ln_pmf(&self, x: i64) -> f64 {
        if x < 0 {
            panic!("{}", StatsError::ArgNotNegative("x"));
        }
        -self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x as u64)
    }
}<commit_msg>complete poisson distribution<commit_after>use std::f64;
use std::i64;
use rand::Rng;
use error::StatsError;
use function::factorial;
use function::gamma;
use result::Result;
use super::{Distribution, Univariate, Discrete};

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Poisson {
    lambda: f64
}

impl Poisson {
    pub fn new(lambda: f64) -> Result<Poisson> {
        if lambda.is_nan() || lambda < 0.0 {
            Err(StatsError::BadParams)
        } else {
            Ok(Poisson{lambda: lambda})
        }
    }

    pub fn lambda(&self) -> f64 {
        self.lambda
    }
}

impl Distribution for Poisson {
    fn sample<R: Rng>(&self, r: &mut R) -> f64 {
        sample_unchecked(r, self.lambda)
    }
}

impl Univariate for Poisson {
    fn mean(&self) -> f64 {
        self.lambda
    }

    fn variance(&self) -> f64 {
        self.lambda
    }

    fn std_dev(&self) -> f64 {
        self.variance().sqrt()
    }

    fn entropy(&self) -> f64 {
        0.5 * (2.0 * f64::consts::PI * f64::consts::E * self.lambda).ln()
        - 1.0 / (12.0 * self.lambda)
        - 1.0 / (24.0 * self.lambda * self.lambda)
        - 19.0 / (360.0 * self.lambda * self.lambda * self.lambda)
    }

    fn skewness(&self) -> f64 {
       1.0 / self.lambda.sqrt()
    }

    fn median(&self) -> f64 {
        (self.lambda + 1.0 / 3.0 - 0.02 / self.lambda).floor()
    }

    fn cdf(&self, x: f64) -> f64 {
        1.0 - gamma::gamma_lr(x + 1.0, self.lambda).unwrap()
    }
}

impl Discrete for Poisson {
    fn mode(&self) -> i64 {
        self.lambda.floor() as i64
    }

    fn min(&self) -> i64 {
        0
    }

    fn max(&self) -> i64 {
        i64::MAX
    }

    fn pmf(&self, x: i64) -> f64 {
        if x < 0 {
            panic!("{}", StatsError::ArgNotNegative("x"));
        }
        (-self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x as u64)).exp()
    }

    fn ln_pmf(&self, x: i64) -> f64 {
        if x < 0 {
            panic!("{}", StatsError::ArgNotNegative("x"));
        }
        -self.lambda + x as f64 * self.lambda.ln() - factorial::ln_factorial(x as u64)
    }
}

/// Generates one sample from the Poisson distribution either by
/// Knuth's method if lambda < 30.0 or Rejection method PA by
/// A. C. Atkinson from the Journal of the Royal Statistical Society
/// Series C (Applied Statistics) Vol. 28 No. 1. (1979) pp. 29 - 35
/// otherwise
fn sample_unchecked<R: Rng>(r: &mut R, lambda: f64) -> f64 {
    if lambda < 30.0 {
        let limit = (-lambda).exp();
        let mut count = 0.0;
        let mut product = r.next_f64();
        while product >= limit {
            count += 1.0;
            product *= r.next_f64();
        }
        count
    } else {
        let c = 0.767 - 3.36 / lambda;
        let beta = f64::consts::PI / (3.0 * lambda).sqrt();
        let alpha = beta * lambda;
        let k = c.ln() - lambda - beta.ln();

        loop {
            let u = r.next_f64();
            let x = (alpha - ((1.0 - u) / u).ln()) / beta;
            let n = (x + 0.5).floor();
            if n < 0.0 {
                continue;
            }

            let v = r.next_f64();
            let y = alpha - beta * x;
            let temp = 1.0 + y.exp();
            let lhs = y + (v / (temp * temp)).ln();
            let rhs = k + n * lambda.ln() - factorial::ln_factorial(n as u64);
            if lhs <= rhs {
                return n;
            }
        }
    }
}<|endoftext|>


<commit_before>use std::hashmap::HashMap;
mod simplepattern_test;

struct ParameterDictionary {
    params: HashMap<~str, ~[~str]>
}

impl ParameterDictionary {
    fn new() -> ParameterDictionary {
        ParameterDictionary{params: HashMap::new()}
    }
    fn add(&mut self, key: &str, value: &str) {
        let v=self.params.find_or_insert(key.into_owned(), ~[]);
        v.push(value.into_owned());
    }
}
impl Index<~str, ~str> for ParameterDictionary {
    fn index(&self, rhs: &~str) -> ~str {
        self.params.get(rhs).head().clone()
    }
}

pub trait PatternMatcher {
    fn matches(&self, input: &str) -> MatchResult;
}

struct MatchResult {
    is_match: bool,
    params: ParameterDictionary //the contents of this are undefined when not matching
}

impl MatchResult {
    fn a_match(params: ParameterDictionary) -> MatchResult {
        MatchResult{is_match: true, params: params}
    }
    fn no_match() -> MatchResult{
        MatchResult{is_match: false, params: ParameterDictionary::new()}
    }
}

/*
        private List<Group> Groups;

        private class Group {
            public string ParamName;
            public string Text;
            public bool IsParam=false;
            public List<string> ValidMatches=new List<string>();
            public bool MatchAll=true;
            public bool Optional=false;
            public char End;
            public Regex MatchType=null;
        }
*/

priv struct PatternGroup{
    name: ~str,
    text: ~str,
    valid_values: ~[~str],
    match_all: bool,
}

pub struct SimplePattern {
    pattern: ~str,
    groups: ~[PatternGroup]
}

impl SimplePattern {
    fn new(pattern: &str) -> SimplePattern {
        let mut x=SimplePattern { pattern: pattern.into_owned(), groups: ~[]};
        x.update_groups();
        x
    }
    /*This will update the "groups", which is basically a way to pre-cache and break apart the important parts of the pattern*/
    fn update_groups(&mut self){
        for g in self.pattern.split_iter('/').filter(|x| !x.is_empty()) {
            if(g.char_at(0) == '[') {
                //group

            }else{
                //just text
                self.groups.push(PatternGroup{
                    name: ~"",
                    text: g.into_owned(),
                    valid_values: ~[],
                    match_all: false,
                });
            }
        }
    }
}

impl PatternMatcher for SimplePattern {
    fn matches(&self, input: &str) -> MatchResult {
        let parts=input.split_iter('/').filter(|x| !x.is_empty()).to_owned_vec();
        let mut res=false; //input == self.pattern;
        if(parts.len() == 0 && self.groups.len() ==0 ){
            return MatchResult::a_match(ParameterDictionary::new());
        }
        if(parts.len() < self.groups.len()){
            return MatchResult::no_match();
        }
        println!("{0:u} {1:u}",parts.len(), self.groups.len());

        //if(input.split_iter('/').len() !=
        res=true;
        let mut ran=false;
        let mut i=0;
        for inp in parts.iter() {
            ran=true;
            if(i >= self.groups.len()){
                return MatchResult::no_match();
            }
            let pat=&self.groups[i];
            println(*inp);
            println(pat.text);
            if(pat.name == ~""){
                //just a raw match
                if(*inp != pat.text) {
                    res=false;
                    break;
                }
            }
            i+=1;
        }
        if(ran == false)
        {
            res=true;
        }
        MatchResult{is_match: res, params: ParameterDictionary::new()}
    }

}

/*
 /** This will parse the Pattern string one group at a time. **
        int ParseParam (int start, ref Group g)
        {
            start++;

            int end=Pattern.Substring(start).IndexOf('}')+start;
            if(end+1>=Pattern.Length-1){
                g.End='\0';
            }else{
                g.End=Pattern[end+1];
            }
            string p=CutString(Pattern,start,end);
            g.Text=p;
            int tmp=p.IndexOf('[');
            if(tmp==-1){ //not found. Just trim it up and get the paramname
                p=p.Trim();
                if(p=="*"){
                    g.Optional=true; //meh. Still add it as a match-all group for the hell of it
                }
                g.MatchAll=true;
            }else{
                //return end;
                g.MatchAll=false;
                string l=CutString(p,tmp+1,p.IndexOf(']'));
                l=l.Replace(" ","");
                p=p.Substring(0,p.IndexOf("=")).Trim();
                int count=0;
                while(true){
                    if(l.Length==0){
                        break;
                    }
                    int endm=l.IndexOf(',');
                    if(endm==-1){
                        endm=l.Length;
                        g.ValidMatches.Add(l);
                        break;
                    }
                    g.ValidMatches.Add(l.Remove(endm));
                    l=l.Substring(endm+1);
                    count++;
                    if(count>100){
                        throw new ApplicationException("inifinite loop detected");
                    }
                }
            }

            g.ParamName=p;
            return end;
        }
     /** This will update all of the "groups" or parameter names/values for the pattern string. *
        private void UpdateGroups ()
        {
            List<Group> groups = new List<Group> ();
            Group g=new Group();
            for(int i=0;i<Pattern.Length;i++){
                if(Pattern[i]=='{'){
                    if(g!=null) //g will never be null
                        groups.Add(g);
                    g=new Group();
                    g.IsParam=true;
                    i=ParseParam(i,ref g);
                    groups.Add(g);
                    g=null;
                }else if(g==null){
                    g=new Group();
                    g.IsParam=false;
                    g.Text+=Pattern[i];
                }else{
                    g.Text+=Pattern[i];
                }
            }
            if(g!=null){
                groups.Add(g);
            }
            Groups=groups;
        }
    a}
        /**Little helper method to cut a string from start to end point. Just shorter than typing .Remove(end).Substring(start) **
        private string CutString(string s,int start,int end){
            return s.Remove(end).Substring(start);
        }
*/

<commit_msg>Make basic route parameters work. Remove all those C# code comments<commit_after>use std::hashmap::HashMap;
mod simplepattern_test;

struct ParameterDictionary {
    params: HashMap<~str, ~[~str]>
}

impl ParameterDictionary {
    fn new() -> ParameterDictionary {
        ParameterDictionary{params: HashMap::new()}
    }
    fn push(&mut self, key: &str, value: &str) {
        let v=self.params.find_or_insert(key.into_owned(), ~[]);
        v.push(value.into_owned());
    }
}
impl Index<~str, ~str> for ParameterDictionary {
    fn index(&self, rhs: &~str) -> ~str {
        self.params.get(rhs).head().clone()
    }
}

pub trait PatternMatcher {
    fn matches(&self, input: &str) -> MatchResult;
}

struct MatchResult {
    is_match: bool,
    params: ParameterDictionary //the contents of this are undefined when not matching
}

impl MatchResult {
    fn a_match(params: ParameterDictionary) -> MatchResult {
        MatchResult{is_match: true, params: params}
    }
    fn no_match() -> MatchResult{
        MatchResult{is_match: false, params: ParameterDictionary::new()}
    }
}

priv struct PatternGroup{
    name: ~str,
    text: ~str,
    valid_values: ~[~str],
    match_all: bool,
}

pub struct SimplePattern {
    pattern: ~str,
    groups: ~[PatternGroup]
}

impl SimplePattern {
    fn new(pattern: &str) -> SimplePattern {
        let mut x=SimplePattern { pattern: pattern.into_owned(), groups: ~[]};
        x.update_groups();
        x
    }
    /*This will update the "groups", which is basically a way to pre-cache and break apart the important parts of the pattern*/
    fn update_groups(&mut self){
        for g in self.pattern.split_iter('/').filter(|x| !x.is_empty()) {
            if(g.char_at(0) == '[') {
                //group
                if(g.iter().any(|x| x=='=')) {
                    //let
                    //self.groups.push(PatternGroup{

                }else{
                    println("fuck");
                    //just name
                    self.groups.push(PatternGroup{
                        name: g.trim_chars(&'[').trim_chars(&']').to_owned(),
                        text: ~"",
                        valid_values: ~[~"*"],
                        match_all: false
                    });
                }

            }else{
                //just text
                self.groups.push(PatternGroup{
                    name: ~"",
                    text: g.into_owned(),
                    valid_values: ~[],
                    match_all: false,
                });
            }
        }
    }
}

impl PatternMatcher for SimplePattern {
    fn matches(&self, input: &str) -> MatchResult {
        let parts=input.split_iter('/').filter(|x| !x.is_empty()).to_owned_vec();
        let mut res=false; //input == self.pattern;
        if(parts.len() == 0 && self.groups.len() ==0 ){
            return MatchResult::a_match(ParameterDictionary::new());
        }
        if(parts.len() < self.groups.len()){
            return MatchResult::no_match();
        }

        //if(input.split_iter('/').len() !=
        res=true;
        let mut ran=false;
        let mut i=0;
        let mut params=ParameterDictionary::new();
        for inp in parts.iter() {
            ran=true;
            if(i >= self.groups.len()){
                return MatchResult::no_match();
            }
            let pat=&self.groups[i];
            if(pat.name == ~""){
                //just a raw match
                if(*inp != pat.text) {
                    res=false;
                    break;
                }
            }else{
                params.push(pat.name, *inp);
            }
            i+=1;
        }
        if(ran == false)
        {
            res=true;
        }
        MatchResult{is_match: res, params: params}
    }

}
<|endoftext|>