<commit_before>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{marker, mem};
use {buffer, json};

use {Gltf, Loaded, Source};

pub use json::accessor::ComponentType as DataType;
pub use json::accessor::Type as Dimensions;

/// A typed view into a buffer view.
#[derive(Clone, Debug)]
pub struct Accessor<'a> {
    /// The parent `Gltf` struct.
    gltf: &'a Gltf,

    /// The corresponding JSON index.
    index: usize,

    /// The corresponding JSON struct.
    json: &'a json::accessor::Accessor,

    /// The buffer view this accessor reads from.
    view: buffer::View<'a>,
}

/// An `Iterator` that iterates over the members of an accessor.
#[derive(Clone, Debug)]
pub struct Iter<'a, T: Copy> {
    /// The total number of iterations left.
    count: usize,

    /// The index of the next iteration.
    index: usize,

    /// The number of bytes between each item.
    stride: usize,

    /// Byte offset into the buffer view where the items begin.
    offset: usize,

    /// The accessor we're iterating over.
    accessor: Loaded<'a, Accessor<'a>>,

    /// Consumes the data type we're returning at each iteration.
    _consume_data_type: marker::PhantomData<T>,
}

impl<'a> Accessor<'a> {
    /// Constructs an `Accessor`.
    pub(crate) fn new(
        gltf: &'a Gltf,
        index: usize,
        json: &'a json::accessor::Accessor,
    ) -> Self {
        let view = gltf.views().nth(index).unwrap();
        Self {
            gltf,
            index,
            json,
            view,
        }
    }

    /// Converts an `Accessor` into a `Loaded<Accessor>`.
    pub fn loaded(self, source: &'a Source) -> Loaded<'a, Accessor<'a>> {
        Loaded {
            item: self,
            source,
        }
    }

    /// Returns the internal JSON index.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Returns the size of each component that this accessor describes.
    pub fn size(&self) -> usize {
        self.data_type().size() * self.dimensions().multiplicity()
    }

    /// Returns the internal JSON item.
    pub fn as_json(&self) -> &json::accessor::Accessor {
        self.json
    }

    /// Returns the buffer view this accessor reads from.
    pub fn view(&self) -> buffer::View<'a> {
        self.gltf.views().nth(self.json.buffer_view.value()).unwrap()
    }

    /// Returns the offset relative to the start of the parent buffer view in bytes.
    pub fn offset(&self) -> usize {
        self.json.byte_offset as usize
    }

    /// Returns the number of components within the buffer view - not to be confused
    /// with the number of bytes in the buffer view.
    pub fn count(&self) -> usize {
        self.json.count as usize
    }

    /// Returns the data type of components in the attribute.
    pub fn data_type(&self) -> DataType {
        self.json.component_type.unwrap().0
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &json::Extras {
        &self.json.extras
    }

    /// Specifies if the attribute is a scalar, vector, or matrix.
    pub fn dimensions(&self) -> Dimensions {
        self.json.type_.unwrap()
    }

    /// Returns the minimum value of each component in this attribute.
    pub fn min(&self) -> &[f32] {
        &self.json.min
    }

    /// Returns the maximum value of each component in this attribute.
    pub fn max(&self) -> &[f32] {
        &self.json.max
    }

    /// Optional user-defined name for this object.
    #[cfg(feature = "names")]
    pub fn name(&self) -> Option<&'a str> {
        self.json.name.as_ref().map(String::as_str)
    }

    /// Specifies whether integer data values should be normalized.
    pub fn normalized(&self) -> bool {
        self.json.normalized
    }

    /// Returns sparse storage of attributes that deviate from their initialization
    /// value.
    pub fn sparse(&self) -> Option<sparse::Sparse> {
        self.json.sparse.as_ref().map(|json| {
            sparse::Sparse::new(self.gltf, json)
        })
    }
}

impl<'a> Loaded<'a, Accessor<'a>> {
    /// Returns an `Iterator` that interprets the data pointed to by the accessor
    /// as the given type.
    ///
    /// The data referenced by the accessor is guaranteed to be appropriately
    /// aligned for any standard Rust type.
    ///
    /// # Panics
    ///
    /// If the size of an individual `T` does not match the accessor component size.
    pub unsafe fn iter<T: Copy>(&self) -> Iter<'a, T> {
        assert_eq!(self.size(), mem::size_of::<T>());
        let count = self.count();
        let offset = self.offset();
        let stride = self.view.stride().unwrap_or(mem::size_of::<T>());
        Iter {
            accessor: self.clone(),
            count,
            offset,
            stride,
            index: 0,
            _consume_data_type: marker::PhantomData,
        }
    }

    /// Returns sparse storage of attributes that deviate from their initialization
    /// value.
    pub fn sparse(&'a self) -> Option<Loaded<'a, sparse::Sparse<'a>>> {
        self.item
            .sparse()
            .map(|item| {
                Loaded {
                    item,
                    source: self.source,
                }
            })
    }

    /// Returns the buffer view this accessor reads from.
    pub fn view(&'a self) -> Loaded<'a, buffer::View<'a>> {
        Loaded {
            item: self.item.view(),
            source: self.source,
        }
    }
}

impl<'a, T: Copy> ExactSizeIterator for Iter<'a, T> {}
impl<'a, T: Copy> Iterator for Iter<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.count {
            let ptr_offset = self.offset + self.index * self.stride;
            let view = Loaded {
                item: self.accessor.view(),
                source: self.accessor.source,
            };
            let data = view.data();
            let ptr = unsafe { data.as_ptr().offset(ptr_offset as isize) };
            let value: T = unsafe { mem::transmute_copy(&*ptr) };
            self.index += 1;
            Some(value)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.count - self.index;
        (hint, Some(hint))
    }
}

/// Contains data structures for sparse storage.
pub mod sparse {
    use {Gltf, Loaded};
    use {buffer, json};

    /// The index data type.
    #[derive(Clone, Debug)]
    pub enum IndexType {
        /// Corresponds to `GL_UNSIGNED_BYTE`.
        U8 = 5121,

        /// Corresponds to `GL_UNSIGNED_SHORT`.
        U16 = 5123,

        /// Corresponds to `GL_UNSIGNED_INT`.
        U32 = 5125,
    }

    /// Indices of those attributes that deviate from their initialization value.
    pub struct Indices<'a> {
        /// The parent `Gltf` struct.
        gltf: &'a Gltf,

        /// The corresponding JSON struct.
        json: &'a json::accessor::sparse::Indices,
    }

    impl<'a> Indices<'a> {
        /// Constructs `sparse::Indices`.
        pub(crate) fn new(
            gltf: &'a Gltf,
            json: &'a json::accessor::sparse::Indices,
        ) -> Self {
            Self {
                gltf: gltf,
                json: json,
            }
        }

        /// Returns the internal JSON item.
        pub fn as_json(&self) ->  &json::accessor::sparse::Indices {
            self.json
        }

        /// Returns the buffer view containing the sparse indices.
        pub fn view(&self) -> buffer::View<'a> {
            self.gltf.views().nth(self.json.buffer_view.value()).unwrap()
        }

        /// The offset relative to the start of the parent buffer view in bytes.
        pub fn offset(&self) -> u32 {
            self.json.byte_offset
        }

        /// The data type of each index.
        pub fn index_type(&self) -> IndexType {
            match self.json.component_type.unwrap().0 {
                json::accessor::ComponentType::U8 => IndexType::U8,
                json::accessor::ComponentType::U16 => IndexType::U16,
                json::accessor::ComponentType::U32 => IndexType::U32,
                _ => unreachable!(),
            }
        }

        /// Optional application specific data.
        pub fn extras(&self) -> &json::Extras {
            &self.json.extras
        }
    }

    impl<'a> Loaded<'a, Indices<'a>> {
        /// Returns the buffer view containing the sparse indices.
        pub fn view(&self) -> Loaded<'a, buffer::View<'a>> {
            Loaded {
                item: self.item.view(),
                source: self.source,
            }
        }
    }

    /// Sparse storage of attributes that deviate from their initialization value.
    pub struct Sparse<'a> {
        /// The parent `Gltf` struct.
        gltf: &'a Gltf,

        /// The corresponding JSON struct.
        json: &'a json::accessor::sparse::Sparse,
    }

    impl<'a> Sparse<'a> {
        /// Constructs `Sparse`.
        pub(crate) fn new(
            gltf: &'a Gltf,
            json: &'a json::accessor::sparse::Sparse,
        ) -> Self {
            Self {
                gltf: gltf,
                json: json,
            }
        }

        /// Returns the internal JSON item.
        pub fn as_json(&self) -> &json::accessor::sparse::Sparse {
            self.json
        }

        /// Returns the number of attributes encoded in this sparse accessor.
        pub fn count(&self) -> u32 {
            self.json.count
        }

        /// Returns an index array of size `count` that points to those accessor
        /// attributes that deviate from their initialization value.
        pub fn indices(&self) -> Indices<'a> {
            Indices::new(self.gltf, &self.json.indices)
        }

        /// Returns an array of size `count * number_of_components`, storing the
        /// displaced accessor attributes pointed by `indices`.
        pub fn values(&self) -> Values<'a> {
            Values::new(self.gltf, &self.json.values)
        }

        /// Optional application specific data.
        pub fn extras(&self) -> &json::Extras {
            &self.json.extras
        }
    }

    impl<'a> Loaded<'a, Sparse<'a>> {
        /// Returns an index array of size `count` that points to those accessor
        /// attributes that deviate from their initialization value.
        pub fn indices(&'a self) -> Loaded<'a, Indices<'a>> {
            Loaded {
                item: self.item.indices(),
                source: self.source,
            }
        }

        /// Returns an array of size `count * number_of_components`, storing the
        /// displaced accessor attributes pointed by `indices`.
        pub fn values(&'a self) -> Loaded<'a, Values<'a>> {
            Loaded {
                item: self.item.values(),
                source: self.source,
            }
        }
    }

    /// Array of size `count * number_of_components` storing the displaced accessor
    /// attributes pointed by `accessor::sparse::Indices`.
    pub struct Values<'a> {
        /// The parent `Gltf` struct.
        gltf: &'a Gltf,

        /// The corresponding JSON struct.
        json: &'a json::accessor::sparse::Values,
    }

    impl<'a> Values<'a> {
        /// Constructs `sparse::Values`.
        pub(crate) fn new(
            gltf: &'a Gltf,
            json: &'a json::accessor::sparse::Values,
        ) -> Self {
            Self {
                gltf: gltf,
                json: json,
            }
        }

        /// Returns the internal JSON item.
        pub fn as_json(&self) ->  &json::accessor::sparse::Values {
            self.json
        }

        /// Returns the buffer view containing the sparse values.
        pub fn view(&self) -> buffer::View {
            self.gltf.views().nth(self.json.buffer_view.value()).unwrap()
        }

        /// The offset relative to the start of the parent buffer view in bytes.
        pub fn offset(&self) -> u32 {
            self.json.byte_offset
        }

        /// Optional application specific data.
        pub fn extras(&self) -> &json::Extras {
            &self.json.extras
        }
    }

    impl<'a> Loaded<'a, Values<'a>> {
        /// Returns the buffer view containing the sparse values.
        pub fn view(&'a self) -> Loaded<'a, buffer::View> {
            Loaded {
                item: self.item.view(),
                source: self.source,
            }
        }
    }

    impl IndexType {
        /// Returns the number of bytes this value represents.
        pub fn size(&self) -> usize {
            use self::IndexType::*;
            match *self {
                U8 => 1,
                U16 => 2,
                U32 => 4,
            }
        }
    }
}
<commit_msg>Fix incorrect buffer view for accessors<commit_after>
// Copyright 2017 The gltf Library Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{marker, mem};
use {buffer, json};

use {Gltf, Loaded, Source};

pub use json::accessor::ComponentType as DataType;
pub use json::accessor::Type as Dimensions;

/// A typed view into a buffer view.
#[derive(Clone, Debug)]
pub struct Accessor<'a> {
    /// The parent `Gltf` struct.
    gltf: &'a Gltf,

    /// The corresponding JSON index.
    index: usize,

    /// The corresponding JSON struct.
    json: &'a json::accessor::Accessor,

    /// The buffer view this accessor reads from.
    view: buffer::View<'a>,
}

/// An `Iterator` that iterates over the members of an accessor.
#[derive(Clone, Debug)]
pub struct Iter<'a, T: Copy> {
    /// The total number of iterations left.
    count: usize,

    /// The index of the next iteration.
    index: usize,

    /// The number of bytes between each item.
    stride: usize,

    /// Byte offset into the buffer view where the items begin.
    offset: usize,

    /// The accessor we're iterating over.
    accessor: Loaded<'a, Accessor<'a>>,

    /// Consumes the data type we're returning at each iteration.
    _consume_data_type: marker::PhantomData<T>,
}

impl<'a> Accessor<'a> {
    /// Constructs an `Accessor`.
    pub(crate) fn new(
        gltf: &'a Gltf,
        index: usize,
        json: &'a json::accessor::Accessor,
    ) -> Self {
        let view = gltf.views().nth(json.buffer_view.value()).unwrap();
        Self {
            gltf,
            index,
            json,
            view,
        }
    }

    /// Converts an `Accessor` into a `Loaded<Accessor>`.
    pub fn loaded(self, source: &'a Source) -> Loaded<'a, Accessor<'a>> {
        Loaded {
            item: self,
            source,
        }
    }

    /// Returns the internal JSON index.
    pub fn index(&self) -> usize {
        self.index
    }

    /// Returns the size of each component that this accessor describes.
    pub fn size(&self) -> usize {
        self.data_type().size() * self.dimensions().multiplicity()
    }

    /// Returns the internal JSON item.
    pub fn as_json(&self) -> &json::accessor::Accessor {
        self.json
    }

    /// Returns the buffer view this accessor reads from.
    pub fn view(&self) -> buffer::View<'a> {
        self.gltf.views().nth(self.json.buffer_view.value()).unwrap()
    }

    /// Returns the offset relative to the start of the parent buffer view in bytes.
    pub fn offset(&self) -> usize {
        self.json.byte_offset as usize
    }

    /// Returns the number of components within the buffer view - not to be confused
    /// with the number of bytes in the buffer view.
    pub fn count(&self) -> usize {
        self.json.count as usize
    }

    /// Returns the data type of components in the attribute.
    pub fn data_type(&self) -> DataType {
        self.json.component_type.unwrap().0
    }

    /// Optional application specific data.
    pub fn extras(&self) -> &json::Extras {
        &self.json.extras
    }

    /// Specifies if the attribute is a scalar, vector, or matrix.
    pub fn dimensions(&self) -> Dimensions {
        self.json.type_.unwrap()
    }

    /// Returns the minimum value of each component in this attribute.
    pub fn min(&self) -> &[f32] {
        &self.json.min
    }

    /// Returns the maximum value of each component in this attribute.
    pub fn max(&self) -> &[f32] {
        &self.json.max
    }

    /// Optional user-defined name for this object.
    #[cfg(feature = "names")]
    pub fn name(&self) -> Option<&'a str> {
        self.json.name.as_ref().map(String::as_str)
    }

    /// Specifies whether integer data values should be normalized.
    pub fn normalized(&self) -> bool {
        self.json.normalized
    }

    /// Returns sparse storage of attributes that deviate from their initialization
    /// value.
    pub fn sparse(&self) -> Option<sparse::Sparse> {
        self.json.sparse.as_ref().map(|json| {
            sparse::Sparse::new(self.gltf, json)
        })
    }
}

impl<'a> Loaded<'a, Accessor<'a>> {
    /// Returns an `Iterator` that interprets the data pointed to by the accessor
    /// as the given type.
    ///
    /// The data referenced by the accessor is guaranteed to be appropriately
    /// aligned for any standard Rust type.
    ///
    /// # Panics
    ///
    /// If the size of an individual `T` does not match the accessor component size.
    pub unsafe fn iter<T: Copy>(&self) -> Iter<'a, T> {
        assert_eq!(self.size(), mem::size_of::<T>());
        let count = self.count();
        let offset = self.offset();
        let stride = self.view.stride().unwrap_or(mem::size_of::<T>());
        Iter {
            accessor: self.clone(),
            count,
            offset,
            stride,
            index: 0,
            _consume_data_type: marker::PhantomData,
        }
    }

    /// Returns sparse storage of attributes that deviate from their initialization
    /// value.
    pub fn sparse(&'a self) -> Option<Loaded<'a, sparse::Sparse<'a>>> {
        self.item
            .sparse()
            .map(|item| {
                Loaded {
                    item,
                    source: self.source,
                }
            })
    }

    /// Returns the buffer view this accessor reads from.
    pub fn view(&'a self) -> Loaded<'a, buffer::View<'a>> {
        Loaded {
            item: self.item.view(),
            source: self.source,
        }
    }
}

impl<'a, T: Copy> ExactSizeIterator for Iter<'a, T> {}
impl<'a, T: Copy> Iterator for Iter<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.count {
            let ptr_offset = self.offset + self.index * self.stride;
            let view = Loaded {
                item: self.accessor.view(),
                source: self.accessor.source,
            };
            let data = view.data();
            let ptr = unsafe { data.as_ptr().offset(ptr_offset as isize) };
            let value: T = unsafe { mem::transmute_copy(&*ptr) };
            self.index += 1;
            Some(value)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.count - self.index;
        (hint, Some(hint))
    }
}

/// Contains data structures for sparse storage.
pub mod sparse {
    use {Gltf, Loaded};
    use {buffer, json};

    /// The index data type.
    #[derive(Clone, Debug)]
    pub enum IndexType {
        /// Corresponds to `GL_UNSIGNED_BYTE`.
        U8 = 5121,

        /// Corresponds to `GL_UNSIGNED_SHORT`.
        U16 = 5123,

        /// Corresponds to `GL_UNSIGNED_INT`.
        U32 = 5125,
    }

    /// Indices of those attributes that deviate from their initialization value.
    pub struct Indices<'a> {
        /// The parent `Gltf` struct.
        gltf: &'a Gltf,

        /// The corresponding JSON struct.
        json: &'a json::accessor::sparse::Indices,
    }

    impl<'a> Indices<'a> {
        /// Constructs `sparse::Indices`.
        pub(crate) fn new(
            gltf: &'a Gltf,
            json: &'a json::accessor::sparse::Indices,
        ) -> Self {
            Self {
                gltf: gltf,
                json: json,
            }
        }

        /// Returns the internal JSON item.
        pub fn as_json(&self) ->  &json::accessor::sparse::Indices {
            self.json
        }

        /// Returns the buffer view containing the sparse indices.
        pub fn view(&self) -> buffer::View<'a> {
            self.gltf.views().nth(self.json.buffer_view.value()).unwrap()
        }

        /// The offset relative to the start of the parent buffer view in bytes.
        pub fn offset(&self) -> u32 {
            self.json.byte_offset
        }

        /// The data type of each index.
        pub fn index_type(&self) -> IndexType {
            match self.json.component_type.unwrap().0 {
                json::accessor::ComponentType::U8 => IndexType::U8,
                json::accessor::ComponentType::U16 => IndexType::U16,
                json::accessor::ComponentType::U32 => IndexType::U32,
                _ => unreachable!(),
            }
        }

        /// Optional application specific data.
        pub fn extras(&self) -> &json::Extras {
            &self.json.extras
        }
    }

    impl<'a> Loaded<'a, Indices<'a>> {
        /// Returns the buffer view containing the sparse indices.
        pub fn view(&self) -> Loaded<'a, buffer::View<'a>> {
            Loaded {
                item: self.item.view(),
                source: self.source,
            }
        }
    }

    /// Sparse storage of attributes that deviate from their initialization value.
    pub struct Sparse<'a> {
        /// The parent `Gltf` struct.
        gltf: &'a Gltf,

        /// The corresponding JSON struct.
        json: &'a json::accessor::sparse::Sparse,
    }

    impl<'a> Sparse<'a> {
        /// Constructs `Sparse`.
        pub(crate) fn new(
            gltf: &'a Gltf,
            json: &'a json::accessor::sparse::Sparse,
        ) -> Self {
            Self {
                gltf: gltf,
                json: json,
            }
        }

        /// Returns the internal JSON item.
        pub fn as_json(&self) -> &json::accessor::sparse::Sparse {
            self.json
        }

        /// Returns the number of attributes encoded in this sparse accessor.
        pub fn count(&self) -> u32 {
            self.json.count
        }

        /// Returns an index array of size `count` that points to those accessor
        /// attributes that deviate from their initialization value.
        pub fn indices(&self) -> Indices<'a> {
            Indices::new(self.gltf, &self.json.indices)
        }

        /// Returns an array of size `count * number_of_components`, storing the
        /// displaced accessor attributes pointed by `indices`.
        pub fn values(&self) -> Values<'a> {
            Values::new(self.gltf, &self.json.values)
        }

        /// Optional application specific data.
        pub fn extras(&self) -> &json::Extras {
            &self.json.extras
        }
    }

    impl<'a> Loaded<'a, Sparse<'a>> {
        /// Returns an index array of size `count` that points to those accessor
        /// attributes that deviate from their initialization value.
        pub fn indices(&'a self) -> Loaded<'a, Indices<'a>> {
            Loaded {
                item: self.item.indices(),
                source: self.source,
            }
        }

        /// Returns an array of size `count * number_of_components`, storing the
        /// displaced accessor attributes pointed by `indices`.
        pub fn values(&'a self) -> Loaded<'a, Values<'a>> {
            Loaded {
                item: self.item.values(),
                source: self.source,
            }
        }
    }

    /// Array of size `count * number_of_components` storing the displaced accessor
    /// attributes pointed by `accessor::sparse::Indices`.
    pub struct Values<'a> {
        /// The parent `Gltf` struct.
        gltf: &'a Gltf,

        /// The corresponding JSON struct.
        json: &'a json::accessor::sparse::Values,
    }

    impl<'a> Values<'a> {
        /// Constructs `sparse::Values`.
        pub(crate) fn new(
            gltf: &'a Gltf,
            json: &'a json::accessor::sparse::Values,
        ) -> Self {
            Self {
                gltf: gltf,
                json: json,
            }
        }

        /// Returns the internal JSON item.
        pub fn as_json(&self) ->  &json::accessor::sparse::Values {
            self.json
        }

        /// Returns the buffer view containing the sparse values.
        pub fn view(&self) -> buffer::View {
            self.gltf.views().nth(self.json.buffer_view.value()).unwrap()
        }

        /// The offset relative to the start of the parent buffer view in bytes.
        pub fn offset(&self) -> u32 {
            self.json.byte_offset
        }

        /// Optional application specific data.
        pub fn extras(&self) -> &json::Extras {
            &self.json.extras
        }
    }

    impl<'a> Loaded<'a, Values<'a>> {
        /// Returns the buffer view containing the sparse values.
        pub fn view(&'a self) -> Loaded<'a, buffer::View> {
            Loaded {
                item: self.item.view(),
                source: self.source,
            }
        }
    }

    impl IndexType {
        /// Returns the number of bytes this value represents.
        pub fn size(&self) -> usize {
            use self::IndexType::*;
            match *self {
                U8 => 1,
                U16 => 2,
                U32 => 4,
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Types for the *m.call.hangup* event.

use js_int::UInt;
use ruma_events_macros::ruma_event;
use serde::{Deserialize, Serialize};

ruma_event! {
    /// Sent by either party to signal their termination of the call. This can be sent either once
    /// the call has has been established or before to abort the call.
    HangupEvent {
        kind: RoomEvent,
        event_type: "m.call.hangup",
        content: {
            /// The ID of the call this event relates to.
            pub call_id: String,

            /// The version of the VoIP specification this messages adheres to.
            pub version: UInt,

            /// Optional error reason for the hangup.
            pub reason: Option<Reason>,
        },
    }
}

/// A reason for a hangup.
///
/// This should not be provided when the user naturally ends or rejects the call. When there was an
/// error in the call negotiation, this should be `ice_failed` for when ICE negotiation fails or
/// `invite_timeout` for when the other party did not answer in time.
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
pub enum Reason {
    /// ICE negotiation failure.
    #[serde(rename = "ice_failed")]
    IceFailed,

    /// Party did not answer in time.
    #[serde(rename = "invite_timeout")]
    InviteTimeout,

    /// Additional variants may be added in the future and will not be considered breaking changes
    /// to ruma-events.
    #[doc(hidden)]
    #[serde(skip)]
    __Nonexhaustive,
}

impl_enum! {
    Reason {
        IceFailed => "ice_failed",
        InviteTimeout => "invite_timeout",
    }
}
<commit_msg>Update serde attrs in call::hangup<commit_after>//! Types for the *m.call.hangup* event.

use js_int::UInt;
use ruma_events_macros::ruma_event;
use serde::{Deserialize, Serialize};

ruma_event! {
    /// Sent by either party to signal their termination of the call. This can be sent either once
    /// the call has has been established or before to abort the call.
    HangupEvent {
        kind: RoomEvent,
        event_type: "m.call.hangup",
        content: {
            /// The ID of the call this event relates to.
            pub call_id: String,

            /// The version of the VoIP specification this messages adheres to.
            pub version: UInt,

            /// Optional error reason for the hangup.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub reason: Option<Reason>,
        },
    }
}

/// A reason for a hangup.
///
/// This should not be provided when the user naturally ends or rejects the call. When there was an
/// error in the call negotiation, this should be `ice_failed` for when ICE negotiation fails or
/// `invite_timeout` for when the other party did not answer in time.
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Reason {
    /// ICE negotiation failure.
    IceFailed,

    /// Party did not answer in time.
    InviteTimeout,

    /// Additional variants may be added in the future and will not be considered breaking changes
    /// to ruma-events.
    #[doc(hidden)]
    #[serde(skip)]
    __Nonexhaustive,
}

impl_enum! {
    Reason {
        IceFailed => "ice_failed",
        InviteTimeout => "invite_timeout",
    }
}
<|endoftext|>


<commit_before>use card::Card;

#[derive(Debug, PartialEq)]
pub struct CardPoints {
    card: Card,
    points: i32
}

impl CardPoints {
	pub fn new(card: Card, points: i32) -> CardPoints {
		CardPoints { card: card, points: points }
	}
}

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

	use card::*;

    #[test]
    fn equality() {
    	let card = Card::new(Suit::Heart, Rank::Ace);
    	assert_eq!(CardPoints::new(card, 1), CardPoints::new(card, 1));
    }
}
<commit_msg>Update card_points.rs<commit_after>use card::Card;

#[derive(Debug, PartialEq)]
pub struct CardPoints {
    card: Card,
    points: i32
}

impl CardPoints {
    pub fn new(card: Card, points: i32) -> CardPoints {
        CardPoints { card: card, points: points }
    }
}

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

    use card::*;

    #[test]
    fn equality() {
        let card = Card::new(Suit::Heart, Rank::Ace);
        assert_eq!(CardPoints::new(card, 1), CardPoints::new(card, 1));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::cmp::Ordering;
use std::fmt;
use std::ops::Deref;
use std::mem;
use std::slice;
use std::sync::Arc;

use input::Char;
use literal::LiteralSearcher;

/// `InstPtr` represents the index of an instruction in a regex program.
pub type InstPtr = usize;

/// Program is a sequence of instructions and various facts about thos
/// instructions.
#[derive(Clone)]
pub struct Program {
    /// A sequence of instructions that represents an NFA.
    pub insts: Vec<Inst>,
    /// Pointers to each Match instruction in the sequence.
    ///
    /// This is always length 1 unless this program represents a regex set.
    pub matches: Vec<InstPtr>,
    /// The ordered sequence of all capture groups extracted from the AST.
    /// Unnamed groups are `None`.
    pub captures: Vec<Option<String>>,
    /// Pointers to all named capture groups into `captures`.
    pub capture_name_idx: Arc<HashMap<String, usize>>,
    /// A pointer to the start instruction. This can vary depending on how
    /// the program was compiled. For example, programs for use with the DFA
    /// engine have a `.*?` inserted at the beginning of unanchored regular
    /// expressions. The actual starting point of the program is after the
    /// `.*?`.
    pub start: InstPtr,
    /// A set of equivalence classes for discriminating bytes in the compiled
    /// program.
    pub byte_classes: Vec<u8>,
    /// When true, this program can only match valid UTF-8.
    pub only_utf8: bool,
    /// When true, this program uses byte range instructions instead of Unicode
    /// range instructions.
    pub is_bytes: bool,
    /// When true, the program is compiled for DFA matching. For example, this
    /// implies `is_bytes` and also inserts a preceding `.*?` for unanchored
    /// regexes.
    pub is_dfa: bool,
    /// When true, the program matches text in reverse (for use only in the
    /// DFA).
    pub is_reverse: bool,
    /// Whether the regex must match from the start of the input.
    pub is_anchored_start: bool,
    /// Whether the regex must match at the end of the input.
    pub is_anchored_end: bool,
    /// Whether this program contains a Unicode word boundary instruction.
    pub has_unicode_word_boundary: bool,
    /// A possibly empty machine for very quickly matching prefix literals.
    pub prefixes: LiteralSearcher,
    /// A limit on the size of the cache that the DFA is allowed to use while
    /// matching.
    ///
    /// The cache limit specifies approximately how much space we're willing to
    /// give to the state cache. Once the state cache exceeds the size, it is
    /// wiped and all states must be re-computed.
    ///
    /// Note that this value does not impact correctness. It can be set to 0
    /// and the DFA will run just fine. (It will only ever store exactly one
    /// state in the cache, and will likely run very slowly, but it will work.)
    ///
    /// Also note that this limit is *per thread of execution*. That is,
    /// if the same regex is used to search text across multiple threads
    /// simultaneously, then the DFA cache is not shared. Instead, copies are
    /// made.
    pub dfa_size_limit: usize,
}

impl Program {
    /// Creates an empty instruction sequence. Fields are given default
    /// values.
    pub fn new() -> Self {
        Program {
            insts: vec![],
            matches: vec![],
            captures: vec![],
            capture_name_idx: Arc::new(HashMap::new()),
            start: 0,
            byte_classes: vec![0; 256],
            only_utf8: true,
            is_bytes: false,
            is_dfa: false,
            is_reverse: false,
            is_anchored_start: false,
            is_anchored_end: false,
            has_unicode_word_boundary: false,
            prefixes: LiteralSearcher::empty(),
            dfa_size_limit: 2 * (1<<20),
        }
    }

    /// If pc is an index to a no-op instruction (like Save), then return the
    /// next pc that is not a no-op instruction.
    pub fn skip(&self, mut pc: usize) -> usize {
        loop {
            match self[pc] {
                Inst::Save(ref i) => pc = i.goto,
                _ => return pc,
            }
        }
    }

    /// Return true if and only if an execution engine at instruction `pc` will
    /// always lead to a match.
    pub fn leads_to_match(&self, pc: usize) -> bool {
        if self.matches.len() > 1 {
            // If we have a regex set, then we have more than one ending
            // state, so leading to one of those states is generally
            // meaningless.
            return false;
        }
        match self[self.skip(pc)] {
            Inst::Match(_) => true,
            _ => false,
        }
    }

    /// Returns true if the current configuration demands that an implicit
    /// `.*?` be prepended to the instruction sequence.
    pub fn needs_dotstar(&self) -> bool {
        self.is_dfa && !self.is_reverse && !self.is_anchored_start
    }

    /// Returns true if this program uses Byte instructions instead of
    /// Char/Range instructions.
    pub fn uses_bytes(&self) -> bool {
        self.is_bytes || self.is_dfa
    }

    /// Returns true if this program exclusively matches valid UTF-8 bytes.
    ///
    /// That is, if an invalid UTF-8 byte is seen, then no match is possible.
    pub fn only_utf8(&self) -> bool {
        self.only_utf8
    }

    /// Return the approximate heap usage of this instruction sequence in
    /// bytes.
    pub fn approximate_size(&self) -> usize {
        // The only instruction that uses heap space is Ranges (for
        // Unicode codepoint programs) to store non-overlapping codepoint
        // ranges. To keep this operation constant time, we ignore them.
        (self.len() * mem::size_of::<Inst>())
        + (self.matches.len() * mem::size_of::<InstPtr>())
        + (self.captures.len() * mem::size_of::<Option<String>>())
        + (self.capture_name_idx.len() *
           (mem::size_of::<String>() + mem::size_of::<usize>()))
        + (self.byte_classes.len() * mem::size_of::<u8>())
        + self.prefixes.approximate_size()
    }
}

impl Deref for Program {
    type Target = [Inst];

    fn deref(&self) -> &Self::Target {
        &*self.insts
    }
}

impl fmt::Debug for Program {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Inst::*;

        fn with_goto(cur: usize, goto: usize, fmtd: String) -> String {
            if goto == cur + 1 {
                fmtd
            } else {
                format!("{} (goto: {})", fmtd, goto)
            }
        }

        fn visible_byte(b: u8) -> String {
            use std::ascii::escape_default;
            let escaped = escape_default(b).collect::<Vec<u8>>();
            String::from_utf8_lossy(&escaped).into_owned()
        }

        for (pc, inst) in self.iter().enumerate() {
            match *inst {
                Match(slot) => {
                    write!(f, "{:04} Match({:?})", pc, slot)?
                }
                Save(ref inst) => {
                    let s = format!("{:04} Save({})", pc, inst.slot);
                    write!(f, "{}", with_goto(pc, inst.goto, s))?;
                }
                Split(ref inst) => {
                    write!(
                        f, "{:04} Split({}, {})", pc, inst.goto1, inst.goto2)?;
                }
                EmptyLook(ref inst) => {
                    let s = format!("{:?}", inst.look);
                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                }
                Char(ref inst) => {
                    let s = format!("{:?}", inst.c);
                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                }
                Ranges(ref inst) => {
                    let ranges = inst.ranges
                        .iter()
                        .map(|r| format!("{:?}-{:?}", r.0, r.1))
                        .collect::<Vec<String>>()
                        .join(", ");
                    write!(
                        f, "{:04} {}", pc, with_goto(pc, inst.goto, ranges))?;
                }
                Bytes(ref inst) => {
                    let s = format!(
                        "Bytes({}, {})",
                        visible_byte(inst.start),
                        visible_byte(inst.end));
                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                }
            }
            if pc == self.start {
                write!(f, " (start)")?;
            }
            write!(f, "\n")?;
        }
        Ok(())
    }
}

impl<'a> IntoIterator for &'a Program {
    type Item = &'a Inst;
    type IntoIter = slice::Iter<'a, Inst>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

/// Inst is an instruction code in a Regex program.
///
/// Regrettably, a regex program either contains Unicode codepoint
/// instructions (Char and Ranges) or it contains byte instructions (Bytes).
/// A regex program can never contain both.
///
/// It would be worth investigating splitting this into two distinct types and
/// then figuring out how to make the matching engines polymorphic over those
/// types without sacrificing performance.
///
/// Other than the benefit of moving invariants into the type system, another
/// benefit is the decreased size. If we remove the `Char` and `Ranges`
/// instructions from the `Inst` enum, then its size shrinks from 40 bytes to
/// 24 bytes. (This is because of the removal of a `Vec` in the `Ranges`
/// variant.) Given that byte based machines are typically much bigger than
/// their Unicode analogues (because they can decode UTF-8 directly), this ends
/// up being a pretty significant savings.
#[derive(Clone, Debug)]
pub enum Inst {
    /// Match indicates that the program has reached a match state.
    ///
    /// The number in the match corresponds to the Nth logical regular
    /// expression in this program. This index is always 0 for normal regex
    /// programs. Values greater than 0 appear when compiling regex sets, and
    /// each match instruction gets its own unique value. The value corresponds
    /// to the Nth regex in the set.
    Match(usize),
    /// Save causes the program to save the current location of the input in
    /// the slot indicated by InstSave.
    Save(InstSave),
    /// Split causes the program to diverge to one of two paths in the
    /// program, preferring goto1 in InstSplit.
    Split(InstSplit),
    /// EmptyLook represents a zero-width assertion in a regex program. A
    /// zero-width assertion does not consume any of the input text.
    EmptyLook(InstEmptyLook),
    /// Char requires the regex program to match the character in InstChar at
    /// the current position in the input.
    Char(InstChar),
    /// Ranges requires the regex program to match the character at the current
    /// position in the input with one of the ranges specified in InstRanges.
    Ranges(InstRanges),
    /// Bytes is like Ranges, except it expresses a single byte range. It is
    /// used in conjunction with Split instructions to implement multi-byte
    /// character classes.
    Bytes(InstBytes),
}

impl Inst {
    /// Returns true if and only if this is a match instruction.
    pub fn is_match(&self) -> bool {
        match *self {
            Inst::Match(_) => true,
            _ => false,
        }
    }
}

/// Representation of the Save instruction.
#[derive(Clone, Debug)]
pub struct InstSave {
    /// The next location to execute in the program.
    pub goto: InstPtr,
    /// The capture slot (there are two slots for every capture in a regex,
    /// including the zeroth capture for the entire match).
    pub slot: usize,
}

/// Representation of the Split instruction.
#[derive(Clone, Debug)]
pub struct InstSplit {
    /// The first instruction to try. A match resulting from following goto1
    /// has precedence over a match resulting from following goto2.
    pub goto1: InstPtr,
    /// The second instruction to try. A match resulting from following goto1
    /// has precedence over a match resulting from following goto2.
    pub goto2: InstPtr,
}

/// Representation of the `EmptyLook` instruction.
#[derive(Clone, Debug)]
pub struct InstEmptyLook {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The type of zero-width assertion to check.
    pub look: EmptyLook,
}

/// The set of zero-width match instructions.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum EmptyLook {
    /// Start of line or input.
    StartLine,
    /// End of line or input.
    EndLine,
    /// Start of input.
    StartText,
    /// End of input.
    EndText,
    /// Word character on one side and non-word character on other.
    WordBoundary,
    /// Word character on both sides or non-word character on both sides.
    NotWordBoundary,
    /// ASCII word boundary.
    WordBoundaryAscii,
    /// Not ASCII word boundary.
    NotWordBoundaryAscii,
}

/// Representation of the Char instruction.
#[derive(Clone, Debug)]
pub struct InstChar {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The character to test.
    pub c: char,
}

/// Representation of the Ranges instruction.
#[derive(Clone, Debug)]
pub struct InstRanges {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The set of Unicode scalar value ranges to test.
    pub ranges: Vec<(char, char)>,
}

impl InstRanges {
    /// Tests whether the given input character matches this instruction.
    pub fn matches(&self, c: Char) -> bool {
        // This speeds up the `match_class_unicode` benchmark by checking
        // some common cases quickly without binary search. e.g., Matching
        // a Unicode class on predominantly ASCII text.
        for r in self.ranges.iter().take(4) {
            if c < r.0 {
                return false;
            }
            if c <= r.1 {
                return true;
            }
        }
        self.ranges.binary_search_by(|r| {
            if r.1 < c {
                Ordering::Less
            } else if r.0 > c {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).is_ok()
    }

    /// Return the number of distinct characters represented by all of the
    /// ranges.
    pub fn num_chars(&self) -> usize {
        self.ranges.iter()
            .map(|&(s, e)| 1 + (e as u32) - (s as u32))
            .fold(0, |acc, len| acc + len)
            as usize
    }
}

/// Representation of the Bytes instruction.
#[derive(Clone, Debug)]
pub struct InstBytes {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The start (inclusive) of this byte range.
    pub start: u8,
    /// The end (inclusive) of this byte range.
    pub end: u8,
}

impl InstBytes {
    /// Returns true if and only if the given byte is in this range.
    pub fn matches(&self, byte: u8) -> bool {
        self.start <= byte && byte <= self.end
    }
}
<commit_msg>perf: always inline Program's Deref<commit_after>use std::collections::HashMap;
use std::cmp::Ordering;
use std::fmt;
use std::ops::Deref;
use std::mem;
use std::slice;
use std::sync::Arc;

use input::Char;
use literal::LiteralSearcher;

/// `InstPtr` represents the index of an instruction in a regex program.
pub type InstPtr = usize;

/// Program is a sequence of instructions and various facts about thos
/// instructions.
#[derive(Clone)]
pub struct Program {
    /// A sequence of instructions that represents an NFA.
    pub insts: Vec<Inst>,
    /// Pointers to each Match instruction in the sequence.
    ///
    /// This is always length 1 unless this program represents a regex set.
    pub matches: Vec<InstPtr>,
    /// The ordered sequence of all capture groups extracted from the AST.
    /// Unnamed groups are `None`.
    pub captures: Vec<Option<String>>,
    /// Pointers to all named capture groups into `captures`.
    pub capture_name_idx: Arc<HashMap<String, usize>>,
    /// A pointer to the start instruction. This can vary depending on how
    /// the program was compiled. For example, programs for use with the DFA
    /// engine have a `.*?` inserted at the beginning of unanchored regular
    /// expressions. The actual starting point of the program is after the
    /// `.*?`.
    pub start: InstPtr,
    /// A set of equivalence classes for discriminating bytes in the compiled
    /// program.
    pub byte_classes: Vec<u8>,
    /// When true, this program can only match valid UTF-8.
    pub only_utf8: bool,
    /// When true, this program uses byte range instructions instead of Unicode
    /// range instructions.
    pub is_bytes: bool,
    /// When true, the program is compiled for DFA matching. For example, this
    /// implies `is_bytes` and also inserts a preceding `.*?` for unanchored
    /// regexes.
    pub is_dfa: bool,
    /// When true, the program matches text in reverse (for use only in the
    /// DFA).
    pub is_reverse: bool,
    /// Whether the regex must match from the start of the input.
    pub is_anchored_start: bool,
    /// Whether the regex must match at the end of the input.
    pub is_anchored_end: bool,
    /// Whether this program contains a Unicode word boundary instruction.
    pub has_unicode_word_boundary: bool,
    /// A possibly empty machine for very quickly matching prefix literals.
    pub prefixes: LiteralSearcher,
    /// A limit on the size of the cache that the DFA is allowed to use while
    /// matching.
    ///
    /// The cache limit specifies approximately how much space we're willing to
    /// give to the state cache. Once the state cache exceeds the size, it is
    /// wiped and all states must be re-computed.
    ///
    /// Note that this value does not impact correctness. It can be set to 0
    /// and the DFA will run just fine. (It will only ever store exactly one
    /// state in the cache, and will likely run very slowly, but it will work.)
    ///
    /// Also note that this limit is *per thread of execution*. That is,
    /// if the same regex is used to search text across multiple threads
    /// simultaneously, then the DFA cache is not shared. Instead, copies are
    /// made.
    pub dfa_size_limit: usize,
}

impl Program {
    /// Creates an empty instruction sequence. Fields are given default
    /// values.
    pub fn new() -> Self {
        Program {
            insts: vec![],
            matches: vec![],
            captures: vec![],
            capture_name_idx: Arc::new(HashMap::new()),
            start: 0,
            byte_classes: vec![0; 256],
            only_utf8: true,
            is_bytes: false,
            is_dfa: false,
            is_reverse: false,
            is_anchored_start: false,
            is_anchored_end: false,
            has_unicode_word_boundary: false,
            prefixes: LiteralSearcher::empty(),
            dfa_size_limit: 2 * (1<<20),
        }
    }

    /// If pc is an index to a no-op instruction (like Save), then return the
    /// next pc that is not a no-op instruction.
    pub fn skip(&self, mut pc: usize) -> usize {
        loop {
            match self[pc] {
                Inst::Save(ref i) => pc = i.goto,
                _ => return pc,
            }
        }
    }

    /// Return true if and only if an execution engine at instruction `pc` will
    /// always lead to a match.
    pub fn leads_to_match(&self, pc: usize) -> bool {
        if self.matches.len() > 1 {
            // If we have a regex set, then we have more than one ending
            // state, so leading to one of those states is generally
            // meaningless.
            return false;
        }
        match self[self.skip(pc)] {
            Inst::Match(_) => true,
            _ => false,
        }
    }

    /// Returns true if the current configuration demands that an implicit
    /// `.*?` be prepended to the instruction sequence.
    pub fn needs_dotstar(&self) -> bool {
        self.is_dfa && !self.is_reverse && !self.is_anchored_start
    }

    /// Returns true if this program uses Byte instructions instead of
    /// Char/Range instructions.
    pub fn uses_bytes(&self) -> bool {
        self.is_bytes || self.is_dfa
    }

    /// Returns true if this program exclusively matches valid UTF-8 bytes.
    ///
    /// That is, if an invalid UTF-8 byte is seen, then no match is possible.
    pub fn only_utf8(&self) -> bool {
        self.only_utf8
    }

    /// Return the approximate heap usage of this instruction sequence in
    /// bytes.
    pub fn approximate_size(&self) -> usize {
        // The only instruction that uses heap space is Ranges (for
        // Unicode codepoint programs) to store non-overlapping codepoint
        // ranges. To keep this operation constant time, we ignore them.
        (self.len() * mem::size_of::<Inst>())
        + (self.matches.len() * mem::size_of::<InstPtr>())
        + (self.captures.len() * mem::size_of::<Option<String>>())
        + (self.capture_name_idx.len() *
           (mem::size_of::<String>() + mem::size_of::<usize>()))
        + (self.byte_classes.len() * mem::size_of::<u8>())
        + self.prefixes.approximate_size()
    }
}

impl Deref for Program {
    type Target = [Inst];

    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        &*self.insts
    }
}

impl fmt::Debug for Program {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Inst::*;

        fn with_goto(cur: usize, goto: usize, fmtd: String) -> String {
            if goto == cur + 1 {
                fmtd
            } else {
                format!("{} (goto: {})", fmtd, goto)
            }
        }

        fn visible_byte(b: u8) -> String {
            use std::ascii::escape_default;
            let escaped = escape_default(b).collect::<Vec<u8>>();
            String::from_utf8_lossy(&escaped).into_owned()
        }

        for (pc, inst) in self.iter().enumerate() {
            match *inst {
                Match(slot) => {
                    write!(f, "{:04} Match({:?})", pc, slot)?
                }
                Save(ref inst) => {
                    let s = format!("{:04} Save({})", pc, inst.slot);
                    write!(f, "{}", with_goto(pc, inst.goto, s))?;
                }
                Split(ref inst) => {
                    write!(
                        f, "{:04} Split({}, {})", pc, inst.goto1, inst.goto2)?;
                }
                EmptyLook(ref inst) => {
                    let s = format!("{:?}", inst.look);
                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                }
                Char(ref inst) => {
                    let s = format!("{:?}", inst.c);
                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                }
                Ranges(ref inst) => {
                    let ranges = inst.ranges
                        .iter()
                        .map(|r| format!("{:?}-{:?}", r.0, r.1))
                        .collect::<Vec<String>>()
                        .join(", ");
                    write!(
                        f, "{:04} {}", pc, with_goto(pc, inst.goto, ranges))?;
                }
                Bytes(ref inst) => {
                    let s = format!(
                        "Bytes({}, {})",
                        visible_byte(inst.start),
                        visible_byte(inst.end));
                    write!(f, "{:04} {}", pc, with_goto(pc, inst.goto, s))?;
                }
            }
            if pc == self.start {
                write!(f, " (start)")?;
            }
            write!(f, "\n")?;
        }
        Ok(())
    }
}

impl<'a> IntoIterator for &'a Program {
    type Item = &'a Inst;
    type IntoIter = slice::Iter<'a, Inst>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

/// Inst is an instruction code in a Regex program.
///
/// Regrettably, a regex program either contains Unicode codepoint
/// instructions (Char and Ranges) or it contains byte instructions (Bytes).
/// A regex program can never contain both.
///
/// It would be worth investigating splitting this into two distinct types and
/// then figuring out how to make the matching engines polymorphic over those
/// types without sacrificing performance.
///
/// Other than the benefit of moving invariants into the type system, another
/// benefit is the decreased size. If we remove the `Char` and `Ranges`
/// instructions from the `Inst` enum, then its size shrinks from 40 bytes to
/// 24 bytes. (This is because of the removal of a `Vec` in the `Ranges`
/// variant.) Given that byte based machines are typically much bigger than
/// their Unicode analogues (because they can decode UTF-8 directly), this ends
/// up being a pretty significant savings.
#[derive(Clone, Debug)]
pub enum Inst {
    /// Match indicates that the program has reached a match state.
    ///
    /// The number in the match corresponds to the Nth logical regular
    /// expression in this program. This index is always 0 for normal regex
    /// programs. Values greater than 0 appear when compiling regex sets, and
    /// each match instruction gets its own unique value. The value corresponds
    /// to the Nth regex in the set.
    Match(usize),
    /// Save causes the program to save the current location of the input in
    /// the slot indicated by InstSave.
    Save(InstSave),
    /// Split causes the program to diverge to one of two paths in the
    /// program, preferring goto1 in InstSplit.
    Split(InstSplit),
    /// EmptyLook represents a zero-width assertion in a regex program. A
    /// zero-width assertion does not consume any of the input text.
    EmptyLook(InstEmptyLook),
    /// Char requires the regex program to match the character in InstChar at
    /// the current position in the input.
    Char(InstChar),
    /// Ranges requires the regex program to match the character at the current
    /// position in the input with one of the ranges specified in InstRanges.
    Ranges(InstRanges),
    /// Bytes is like Ranges, except it expresses a single byte range. It is
    /// used in conjunction with Split instructions to implement multi-byte
    /// character classes.
    Bytes(InstBytes),
}

impl Inst {
    /// Returns true if and only if this is a match instruction.
    pub fn is_match(&self) -> bool {
        match *self {
            Inst::Match(_) => true,
            _ => false,
        }
    }
}

/// Representation of the Save instruction.
#[derive(Clone, Debug)]
pub struct InstSave {
    /// The next location to execute in the program.
    pub goto: InstPtr,
    /// The capture slot (there are two slots for every capture in a regex,
    /// including the zeroth capture for the entire match).
    pub slot: usize,
}

/// Representation of the Split instruction.
#[derive(Clone, Debug)]
pub struct InstSplit {
    /// The first instruction to try. A match resulting from following goto1
    /// has precedence over a match resulting from following goto2.
    pub goto1: InstPtr,
    /// The second instruction to try. A match resulting from following goto1
    /// has precedence over a match resulting from following goto2.
    pub goto2: InstPtr,
}

/// Representation of the `EmptyLook` instruction.
#[derive(Clone, Debug)]
pub struct InstEmptyLook {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The type of zero-width assertion to check.
    pub look: EmptyLook,
}

/// The set of zero-width match instructions.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum EmptyLook {
    /// Start of line or input.
    StartLine,
    /// End of line or input.
    EndLine,
    /// Start of input.
    StartText,
    /// End of input.
    EndText,
    /// Word character on one side and non-word character on other.
    WordBoundary,
    /// Word character on both sides or non-word character on both sides.
    NotWordBoundary,
    /// ASCII word boundary.
    WordBoundaryAscii,
    /// Not ASCII word boundary.
    NotWordBoundaryAscii,
}

/// Representation of the Char instruction.
#[derive(Clone, Debug)]
pub struct InstChar {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The character to test.
    pub c: char,
}

/// Representation of the Ranges instruction.
#[derive(Clone, Debug)]
pub struct InstRanges {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The set of Unicode scalar value ranges to test.
    pub ranges: Vec<(char, char)>,
}

impl InstRanges {
    /// Tests whether the given input character matches this instruction.
    pub fn matches(&self, c: Char) -> bool {
        // This speeds up the `match_class_unicode` benchmark by checking
        // some common cases quickly without binary search. e.g., Matching
        // a Unicode class on predominantly ASCII text.
        for r in self.ranges.iter().take(4) {
            if c < r.0 {
                return false;
            }
            if c <= r.1 {
                return true;
            }
        }
        self.ranges.binary_search_by(|r| {
            if r.1 < c {
                Ordering::Less
            } else if r.0 > c {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).is_ok()
    }

    /// Return the number of distinct characters represented by all of the
    /// ranges.
    pub fn num_chars(&self) -> usize {
        self.ranges.iter()
            .map(|&(s, e)| 1 + (e as u32) - (s as u32))
            .fold(0, |acc, len| acc + len)
            as usize
    }
}

/// Representation of the Bytes instruction.
#[derive(Clone, Debug)]
pub struct InstBytes {
    /// The next location to execute in the program if this instruction
    /// succeeds.
    pub goto: InstPtr,
    /// The start (inclusive) of this byte range.
    pub start: u8,
    /// The end (inclusive) of this byte range.
    pub end: u8,
}

impl InstBytes {
    /// Returns true if and only if the given byte is in this range.
    pub fn matches(&self, byte: u8) -> bool {
        self.start <= byte && byte <= self.end
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::rc::Rc;

#[derive(Clone, Copy)]
enum Color {
    Red,
    Black
}

struct TreeNode<K, V> {
    color: Color,
    elem: (K, V),
    left: Option<Rc<TreeNode<K, V>>>,
    right: Option<Rc<TreeNode<K, V>>>
}

struct Tree<K, V> {
    root: Option<Rc<TreeNode<K, V>>>
}

impl<K, V> Tree<K, V> {
    pub fn new() -> Tree<K, V> {
        Tree { root: None }
    }
}

impl<K, V> Tree<K, V>
    where K: Ord + Clone, V: Clone
{
    pub fn get(&self, key: &K) -> Option<&V> {
        find_exact(&self.root, key)
    }

    pub fn insert(&self, key: K, value: V) -> Tree<K, V> {
        let mut root = insert(&self.root, (key, value));
        root.color = Color::Black;
        Tree { root: Some(Rc::new(root)) }
    }
}

impl<K, V> TreeNode<K, V>
    where K: Clone, V: Clone
{
    fn change_black(&self) -> TreeNode<K, V> {
        TreeNode {
            color: Color::Black,
            elem: self.elem.clone(),
            left: self.left.clone(),
            right: self.right.clone()
        }
    }
}

fn find_exact<'a, K, V>(node: &'a Option<Rc<TreeNode<K, V>>>, key: &K) -> Option<&'a V>
    where K: Ord
{
    let mut cursor = node;
    loop {
        match *cursor {
            None => return None,
            Some(ref n) => match key.cmp(&n.elem.0) {
                Ordering::Less => cursor = &n.left,
                Ordering::Equal => return Some(&n.elem.1),
                Ordering::Greater => cursor = &n.right,
            }
        }
    }
}

fn insert<K, V>(node: &Option<Rc<TreeNode<K, V>>>, elem: (K, V)) -> TreeNode<K, V>
    where K: Ord + Clone, V: Clone
{
    match *node {
        None => TreeNode {
            color: Color::Red,
            elem: elem,
            left: None,
            right: None
        },
        Some(ref n) => match elem.0.cmp(&n.elem.0) {
            Ordering::Less => match n.color {
                Color::Black => balance_left(insert(&n.left, elem), n, &n.right),
                Color::Red => TreeNode {
                    color: Color::Red,
                    elem: n.elem.clone(),
                    left: Some(Rc::new(insert(&n.left, elem))),
                    right: n.right.clone()
                }
            },
            Ordering::Greater => match n.color {
                Color::Black => balance_right(&n.left, n, insert(&n.right, elem)),
                Color::Red => TreeNode {
                    color: Color::Red,
                    elem: n.elem.clone(),
                    left: n.left.clone(),
                    right: Some(Rc::new(insert(&n.right, elem)))
                }
            },
            Ordering::Equal => TreeNode {
                color: n.color,
                elem: elem,
                left: n.left.clone(),
                right: n.right.clone()
            }
        }
    }
}

fn balance_left<K, V>(left: TreeNode<K, V>,
                      node: &TreeNode<K, V>,
                      right: &Option<Rc<TreeNode<K, V>>>) -> TreeNode<K, V>
    where K: Ord + Clone, V: Clone
{
    if let Color::Red = left.color {
        if let Some(ref ll) = left.left {
            if let Color::Red = ll.color {
                let lr = TreeNode {
                    color: Color::Black,
                    elem: node.elem.clone(),
                    left: left.right.clone(),
                    right: right.clone()
                };

                return TreeNode {
                    color: Color::Red,
                    elem: left.elem,
                    left: Some(Rc::new(ll.change_black())),
                    right: Some(Rc::new(lr))
                }
            }
        }

        if let Some(ref lr) = left.right {
            if let Color::Red = lr.color {
                return TreeNode {
                    color: Color::Red,
                    elem: lr.elem.clone(),
                    left: Some(Rc::new(TreeNode {
                        color: Color::Black,
                        elem: left.elem,
                        left: left.left.clone(),
                        right: lr.left.clone()
                    })),
                    right: Some(Rc::new(TreeNode {
                        color: Color::Black,
                        elem: node.elem.clone(),
                        left: lr.right.clone(),
                        right: right.clone()
                    }))
                }
            }
        }
    }

    TreeNode {
        color: Color::Black,
        elem: node.elem.clone(),
        left: Some(Rc::new(left)),
        right: right.clone()
    }
}

fn balance_right<K, V>(left: &Option<Rc<TreeNode<K, V>>>,
                       node: &TreeNode<K, V>,
                       right: TreeNode<K, V>) -> TreeNode<K, V>
    where K: Ord + Clone, V: Clone
{
    if let Color::Red = right.color {
        if let Some(ref rr) = right.right {
            if let Color::Red = rr.color {
                let rl = TreeNode {
                    color: Color::Black,
                    elem: node.elem.clone(),
                    left: left.clone(),
                    right: right.left.clone()
                };

                return TreeNode {
                    color: Color::Red,
                    elem: right.elem,
                    left: Some(Rc::new(rl)),
                    right: Some(Rc::new(rr.change_black()))
                }
            }
        }

        if let Some(ref rl) = right.left {
            if let Color::Red = rl.color {
                return TreeNode {
                    color: Color::Red,
                    elem: rl.elem.clone(),
                    left: Some(Rc::new(TreeNode {
                        color: Color::Black,
                        elem: node.elem.clone(),
                        left: left.clone(),
                        right: rl.left.clone()
                    })),
                    right: Some(Rc::new(TreeNode {
                        color: Color::Black,
                        elem: right.elem,
                        left: rl.right.clone(),
                        right: right.right.clone()
                    }))
                }
            }
        }
    }

    TreeNode {
        color: Color::Black,
        elem: node.elem.clone(),
        left: left.clone(),
        right: Some(Rc::new(right))
    }
}

#[cfg(test)]
mod test {
    use std::fmt;

    use super::{Color, Tree, TreeNode};

    fn format_tree<K, V>(f: &mut fmt::Formatter, node: &TreeNode<K, V>) -> fmt::Result
        where K: fmt::Display, V: fmt::Display
    {
        try!(write!(f, "("));
        if let Some(ref l) = node.left {
            try!(format_tree(f, l));
            try!(write!(f, " "));
        }

        match node.color {
            Color::Black => try!(write!(f, "B")),
            Color::Red => try!(write!(f, "R"))
        }

        try!(write!(f, "{}{}", node.elem.0, node.elem.1));

        if let Some(ref r) = node.right {
            try!(write!(f, " "));
            try!(format_tree(f, r));
        }

        write!(f, ")")
    }

    impl<K, V> fmt::Display for Tree<K, V> where K: fmt::Display, V: fmt::Display
    {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match self.root {
                None => write!(f, "()"),
                Some(ref root) => format_tree(f, root)
            }
        }

    }

    #[test]
    fn test_insert() {
        let r0 = Tree::new();
        assert_eq!("()".to_string(), format!("{}", r0));

        let r1 = r0.insert(4, "d");
        assert_eq!("(B4d)".to_string(), format!("{}", r1));

        let r2 = r1.insert(7, "g");
        assert_eq!("(B4d (R7g))".to_string(), format!("{}", r2));

        let r3 = r2.insert(12, "l");
        assert_eq!("((B4d) B7g (B12l))".to_string(), format!("{}", r3));

        let r4 = r3.insert(15, "o");
        assert_eq!("((B4d) B7g (B12l (R15o)))".to_string(), format!("{}", r4));

        let r5 = r4.insert(3, "c");
        assert_eq!("(((R3c) B4d) B7g (B12l (R15o)))".to_string(), format!("{}", r5));

        let r6 = r5.insert(5, "e");
        assert_eq!("(((R3c) B4d (R5e)) B7g (B12l (R15o)))".to_string(), format!("{}", r6));

        let r7 = r6.insert(14, "n");
        assert_eq!("(((R3c) B4d (R5e)) B7g ((B12l) R14n (B15o)))".to_string(), format!("{}", r7));

        let r8 = r7.insert(18, "r");
        assert_eq!("(((R3c) B4d (R5e)) B7g ((B12l) R14n (B15o (R18r))))".to_string(), format!("{}", r8));

        let r9 = r8.insert(16, "p");
        assert_eq!("((((R3c) B4d (R5e)) B7g (B12l)) B14n ((B15o) B16p (B18r)))".to_string(), format!("{}", r9));

        let r10 = r9.insert(17, "q");
        assert_eq!("((((R3c) B4d (R5e)) B7g (B12l)) B14n ((B15o) B16p ((R17q) B18r)))".to_string(), format!("{}", r10));
    }
}
<commit_msg>Weight-balanced tree algorithm<commit_after>use std::cmp::Ordering;
use std::rc::Rc;

static DELTA: usize = 3;
static GAMMA: usize = 2;

struct TreeNode<K, V> {
    size: usize,
    elem: (K, V),
    left: Option<Rc<TreeNode<K, V>>>,
    right: Option<Rc<TreeNode<K, V>>>
}

struct Tree<K, V> {
    root: Option<Rc<TreeNode<K, V>>>
}

impl<K, V> Tree<K, V> {
    pub fn new() -> Tree<K, V> {
        Tree { root: None }
    }
}

impl<K, V> Tree<K, V>
    where K: Ord + Clone, V: Clone
{
    pub fn get(&self, key: &K) -> Option<&V> {
        find_exact(&self.root, key)
    }

    pub fn insert(&self, key: K, value: V) -> Tree<K, V> {
        let mut root = insert(&self.root, (key, value));
        Tree { root: Some(Rc::new(root)) }
    }
}

impl<K, V> TreeNode<K, V> {
    fn new(elem: (K, V), left: Option<Rc<TreeNode<K, V>>>, right: Option<Rc<TreeNode<K, V>>>)
        -> TreeNode<K, V>
    {
        TreeNode {
            elem: elem,
            size: size(&left) + size(&right) + 1,
            left: left,
            right: right
        }
    }
}

fn find_exact<'a, K, V>(node: &'a Option<Rc<TreeNode<K, V>>>, key: &K) -> Option<&'a V>
    where K: Ord
{
    let mut cursor = node;
    loop {
        match *cursor {
            None => return None,
            Some(ref n) => match key.cmp(&n.elem.0) {
                Ordering::Less => cursor = &n.left,
                Ordering::Equal => return Some(&n.elem.1),
                Ordering::Greater => cursor = &n.right,
            }
        }
    }
}

fn insert<K, V>(node: &Option<Rc<TreeNode<K, V>>>, elem: (K, V)) -> TreeNode<K, V>
    where K: Ord + Clone, V: Clone
{
    match *node {
        None => TreeNode {
            size: 1,
            elem: elem,
            left: None,
            right: None
        },
        Some(ref n) => match elem.0.cmp(&n.elem.0) {
            Ordering::Less => {
                balance_right(n.elem.clone(), insert(&n.left, elem), &n.right)
            },
            Ordering::Greater => {
                balance_left(n.elem.clone(), &n.left, insert(&n.right, elem))
            },
            Ordering::Equal => TreeNode {
                size: n.size,
                elem: elem,
                left: n.left.clone(),
                right: n.right.clone()
            }
        }
    }
}

fn is_balanced(a: usize, b: usize) -> bool
{
    DELTA * (a + 1) >= b + 1
}

fn is_single(a: usize, b: usize) -> bool
{
    a + 1 < GAMMA * (b + 1)
}

fn size<K, V>(node: &Option<Rc<TreeNode<K, V>>>) -> usize {
    match *node {
        None => 0,
        Some(ref n) => n.size
    }
}

fn balance_left<K, V>(elem: (K, V),
                      left: &Option<Rc<TreeNode<K, V>>>,
                      right: TreeNode<K, V>) -> TreeNode<K, V>
    where K: Ord + Clone, V: Clone
{
    let lsize = size(left);
    if is_balanced(lsize, right.size) {
        TreeNode::new(elem, left.clone(), Some(Rc::new(right)))
    } else {
        let TreeNode { elem: r_elem, size: rsize, left: rl, right: rr } = right;
        if is_single(size(&rl), size(&rr)) {
            let new_l = TreeNode::new(elem, left.clone(), rl);
            TreeNode::new(
                r_elem,
                Some(Rc::new(new_l)),
                rr
            )
        } else {
            if let Some(ref rl_node) = rl {
                let new_l = TreeNode::new(elem, left.clone(), rl_node.left.clone());
                let new_r = TreeNode::new(r_elem, rl_node.right.clone(), rr);
                TreeNode::new(
                    rl_node.elem.clone(),
                    Some(Rc::new(new_l)),
                    Some(Rc::new(new_r))
                )
            } else {
                panic!("size invariant does not match!")
            }
        }
    }
}

fn balance_right<K, V>(elem: (K, V),
                       left: TreeNode<K, V>,
                       right: &Option<Rc<TreeNode<K, V>>>) -> TreeNode<K, V>
    where K: Ord + Clone, V: Clone
{
    let rsize = size(right);
    if is_balanced(rsize, left.size) {
        TreeNode::new(elem, Some(Rc::new(left)), right.clone())
    } else {
        let TreeNode { elem: l_elem, size: lsize, left: ll, right: lr } = left;
        if is_single(size(&lr), size(&ll)) {
            let new_r = TreeNode::new(elem, lr, right.clone());
            TreeNode::new(
                l_elem,
                ll,
                Some(Rc::new(new_r)),
            )
        } else {
            if let Some(ref lr_node) = lr {
                let new_l = TreeNode::new(l_elem, ll, lr_node.left.clone());
                let new_r = TreeNode::new(elem, lr_node.right.clone(), right.clone());
                TreeNode::new(
                    lr_node.elem.clone(),
                    Some(Rc::new(new_l)),
                    Some(Rc::new(new_r))
                )
            } else {
                panic!("size invariant does not match!")
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::rc::Rc;

    use super::{Tree, TreeNode, is_balanced, size};

    fn traverse<K, V>(node: &Option<Rc<TreeNode<K, V>>>, res: &mut Vec<(K, V)>)
        where K: Clone, V: Clone
    {
        if let Some(ref n) = *node {
            traverse(&n.left, res);
            res.push(n.elem.clone());
            traverse(&n.right, res);
        }
    }

    fn balanced<K, V>(node: &Option<Rc<TreeNode<K, V>>>) -> bool
    {
        if let Some(ref n) = *node {
            is_balanced(size(&n.left), size(&n.right))
                && is_balanced(size(&n.right), size(&n.left))
                && balanced(&n.left)
                && balanced(&n.right)
        } else {
            true
        }
    }

    #[test]
    fn test_insert() {
        let r0 = Tree::new();
        let r1 = r0.insert(4, 'd');
        let r2 = r1.insert(7, 'g');
        let r3 = r2.insert(12, 'l');
        let r4 = r3.insert(15, 'o');
        let r5 = r4.insert(3, 'c');
        let r6 = r5.insert(5, 'e');
        let r7 = r6.insert(14, 'n');
        let r8 = r7.insert(18, 'r');
        let r9 = r8.insert(16, 'p');
        let r10 = r9.insert(17, 'q');

        let expected = vec![
            (3, 'c'), (4, 'd'), (5, 'e'), (7, 'g'),
            (12, 'l'), (14, 'n'), (15, 'o'), (16, 'p'),
            (17, 'q'), (18, 'r')
        ];

        let mut res = Vec::new();
        traverse(&r10.root, &mut res);

        assert_eq!(expected, res);
        assert!(balanced(&r10.root));
    }
}
<|endoftext|>


<commit_before>//!
//! Helper to decompose a packet of binary data into multiple arbitrary data
//! structures.
//!

use std::mem;

/// An iterator that can be used to fetch typed arguments from a byte slice
pub struct ArgumentIterator<'a> {
    data: &'a [u8],
    pos: uint,
}

impl<'a> ArgumentIterator<'a> {
    /// Create a new argument iterator for the given byte slice
    pub fn new (data: &'a [u8]) -> ArgumentIterator<'a> {
        ArgumentIterator { data: data, pos: 0 }
    }

    /// Fetch a typed argument
    pub fn fetch<T> (&mut self) -> &'a T {
        let value = unsafe { mem::transmute(self.data.as_ptr().offset(self.pos as int)) };
        self.pos += mem::size_of::<T>();
        assert!(self.pos <= self.data.len(), "trying to fetch argument behind data");
        value
    }

    /// Fetch a (zero-terminated) string (can be non-utf8)
    pub fn fetch_str (&mut self) -> &'a [u8] {
        let start = self.pos;
        while self.data[self.pos] != 0u8 {
            self.pos += 1
        }
        self.pos += 1;  // Eat the null terminator
        self.data.slice(start, self.pos-1)
    }

    /// Fetch a (zero-terminated) Posix path
    pub fn fetch_path (&mut self) -> PosixPath {
        PosixPath::new(self.fetch_str())
    }

    /// Fetch a slice of the remaining data
    pub fn fetch_data (&mut self) -> &'a [u8] {
        let bytes = self.data.slice_from(self.pos);
        self.pos = self.data.len();
        bytes
    }
}

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

    static TEST_DATA: [u8, ..12] = [0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, 0x62, 0x61, 0x7a, 0x00];
    struct TestArgument { p1: u8, p2: u8, p3: u16 }

    #[test]
    fn generic_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x62);
        assert_eq!(arg.p2, 0x61);
        assert_eq!(arg.p3, 0x0072);
    }

    #[test]
    fn string_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_str();
        assert_eq!(arg, b"foo");
        let arg = it.fetch_str();
        assert_eq!(arg, b"bar");
    }

    #[test]
    fn path_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_path();
        assert_eq!(arg.as_str(), Some("foo"));
        let arg = it.fetch_path();
        assert_eq!(arg.as_str(), Some("bar"));
    }

    #[test]
    fn remaining_data_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        it.fetch_str();
        it.fetch_str();
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00].as_slice());
    }

    #[test]
    fn mixed_arguments () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg = it.fetch_str();
        assert_eq!(arg, b"bar");
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00].as_slice());
    }
}
<commit_msg>Compare paths in argument tests rather than their string representation<commit_after>//!
//! Helper to decompose a packet of binary data into multiple arbitrary data
//! structures.
//!

use std::mem;

/// An iterator that can be used to fetch typed arguments from a byte slice
pub struct ArgumentIterator<'a> {
    data: &'a [u8],
    pos: uint,
}

impl<'a> ArgumentIterator<'a> {
    /// Create a new argument iterator for the given byte slice
    pub fn new (data: &'a [u8]) -> ArgumentIterator<'a> {
        ArgumentIterator { data: data, pos: 0 }
    }

    /// Fetch a typed argument
    pub fn fetch<T> (&mut self) -> &'a T {
        let value = unsafe { mem::transmute(self.data.as_ptr().offset(self.pos as int)) };
        self.pos += mem::size_of::<T>();
        assert!(self.pos <= self.data.len(), "trying to fetch argument behind data");
        value
    }

    /// Fetch a (zero-terminated) string (can be non-utf8)
    pub fn fetch_str (&mut self) -> &'a [u8] {
        let start = self.pos;
        while self.data[self.pos] != 0u8 {
            self.pos += 1
        }
        self.pos += 1;  // Eat the null terminator
        self.data.slice(start, self.pos-1)
    }

    /// Fetch a (zero-terminated) Posix path
    pub fn fetch_path (&mut self) -> PosixPath {
        PosixPath::new(self.fetch_str())
    }

    /// Fetch a slice of the remaining data
    pub fn fetch_data (&mut self) -> &'a [u8] {
        let bytes = self.data.slice_from(self.pos);
        self.pos = self.data.len();
        bytes
    }
}

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

    static TEST_DATA: [u8, ..12] = [0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, 0x62, 0x61, 0x7a, 0x00];
    struct TestArgument { p1: u8, p2: u8, p3: u16 }

    #[test]
    fn generic_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x62);
        assert_eq!(arg.p2, 0x61);
        assert_eq!(arg.p3, 0x0072);
    }

    #[test]
    fn string_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_str();
        assert_eq!(arg, b"foo");
        let arg = it.fetch_str();
        assert_eq!(arg, b"bar");
    }

    #[test]
    fn path_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg = it.fetch_path();
        assert!(arg == PosixPath::new("foo"));
        let arg = it.fetch_path();
        assert!(arg == PosixPath::new("bar"));
    }

    #[test]
    fn remaining_data_argument () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        it.fetch_str();
        it.fetch_str();
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00].as_slice());
    }

    #[test]
    fn mixed_arguments () {
        let mut it = ArgumentIterator::new(&TEST_DATA);
        let arg: &TestArgument = it.fetch();
        assert_eq!(arg.p1, 0x66);
        assert_eq!(arg.p2, 0x6f);
        assert_eq!(arg.p3, 0x006f);
        let arg = it.fetch_str();
        assert_eq!(arg, b"bar");
        let arg = it.fetch_data();
        assert_eq!(arg, [0x62, 0x61, 0x7a, 0x00].as_slice());
    }
}
<|endoftext|>


<commit_before>//! Utilities for interacting with the build queue

use crate::error::Result;
use postgres::Connection;

/// The default queue priority
const DEFAULT_PRIORITY: i32 = 0;

/// Get the build queue priority for a crate
pub fn get_crate_priority(conn: &Connection, name: &str) -> Result<i32> {
    // Search the `priority` table for a priority where the crate name matches the stored pattern
    let query = conn.query(
        "SELECT priority FROM crate_priorities WHERE $1 LIKE pattern LIMIT 1",
        &[&name],
    )?;

    // If no match is found, return the default priority
    if let Some(row) = query.iter().next() {
        Ok(row.get(0))
    } else {
        Ok(DEFAULT_PRIORITY)
    }
}

/// Adds a crate to the build queue to be built by rustdoc. `priority` should be gotten from `get_crate_priority`
pub fn add_crate_to_queue(
    conn: &Connection,
    name: &str,
    version: &str,
    priority: i32,
) -> Result<()> {
    conn.execute(
        "INSERT INTO queue (name, version, priority) VALUES ($1, $2, $3)",
        &[&name, &version, &priority],
    )?;

    Ok(())
}

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

    /// Set all crates that match [`pattern`] to have a certain priority
    ///
    /// Note: `pattern` is used in a `LIKE` statement, so it must follow the postgres like syntax
    ///
    /// [`pattern`]: https://www.postgresql.org/docs/8.3/functions-matching.html
    pub fn set_crate_priority(conn: &Connection, pattern: &str, priority: i32) -> Result<()> {
        conn.query(
            "INSERT INTO crate_priorities (pattern, priority) VALUES ($1, $2)",
            &[&pattern, &priority],
        )?;

        Ok(())
    }

    /// Remove a pattern from the priority table, returning the priority that it was associated with or `None`
    /// if nothing was removed
    pub fn remove_crate_priority(conn: &Connection, pattern: &str) -> Result<Option<i32>> {
        let query = conn.query(
            "DELETE FROM crate_priorities WHERE pattern = $1 RETURNING priority",
            &[&pattern],
        )?;

        Ok(query.iter().next().map(|row| row.get(0)))
    }

    #[test]
    fn set_priority() {
        wrapper(|env| {
            let db = env.db();

            set_crate_priority(&db.conn(), "cratesfyi-%", -100)?;
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-database")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-s3")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-webserver")?, -100);
            assert_eq!(
                get_crate_priority(&db.conn(), "cratesfyi")?,
                DEFAULT_PRIORITY
            );

            set_crate_priority(&db.conn(), "_c_", 100)?;
            assert_eq!(get_crate_priority(&db.conn(), "rcc")?, 100);
            assert_eq!(get_crate_priority(&db.conn(), "rc")?, DEFAULT_PRIORITY);

            set_crate_priority(&db.conn(), "hexponent", 10)?;
            assert_eq!(get_crate_priority(&db.conn(), "hexponent")?, 10);
            assert_eq!(
                get_crate_priority(&db.conn(), "hexponents")?,
                DEFAULT_PRIORITY
            );
            assert_eq!(
                get_crate_priority(&db.conn(), "floathexponent")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn remove_priority() {
        wrapper(|env| {
            let db = env.db();

            set_crate_priority(&db.conn(), "cratesfyi-%", -100)?;
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-")?, -100);

            assert_eq!(
                remove_crate_priority(&db.conn(), "cratesfyi-%")?,
                Some(-100)
            );
            assert_eq!(
                get_crate_priority(&db.conn(), "cratesfyi-")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn get_priority() {
        wrapper(|env| {
            let db = env.db();

            set_crate_priority(&db.conn(), "cratesfyi-%", -100)?;

            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-database")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-s3")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-webserver")?, -100);
            assert_eq!(
                get_crate_priority(&db.conn(), "unrelated")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn get_default_priority() {
        wrapper(|env| {
            let db = env.db();

            assert_eq!(
                get_crate_priority(&db.conn(), "cratesfyi")?,
                DEFAULT_PRIORITY
            );
            assert_eq!(get_crate_priority(&db.conn(), "rcc")?, DEFAULT_PRIORITY);
            assert_eq!(get_crate_priority(&db.conn(), "lasso")?, DEFAULT_PRIORITY);
            assert_eq!(
                get_crate_priority(&db.conn(), "hexponent")?,
                DEFAULT_PRIORITY
            );
            assert_eq!(
                get_crate_priority(&db.conn(), "rust4lyfe")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn add_to_queue() {
        wrapper(|env| {
            let db = env.db();

            let test_crates = [
                ("rcc", "0.1.0", 2),
                ("lasso", "0.1.0", -1),
                ("hexponent", "0.1.0", 0),
                ("destroy-all-humans", "0.0.0-alpha", -100000),
                ("totally-not-destroying-humans", "0.0.1", 0),
            ];

            for (name, version, priority) in test_crates.iter() {
                add_crate_to_queue(&db.conn(), name, version, *priority)?;

                let query = db.conn().query(
                    "SELECT name, version, priority FROM queue WHERE name = $1",
                    &[&name],
                )?;

                assert!(query.len() == 1);
                let row = query.iter().next().unwrap();

                assert_eq!(&row.get::<_, String>(0), name);
                assert_eq!(&row.get::<_, String>(1), version);
                assert_eq!(row.get::<_, i32>(2), *priority);
            }

            Ok(())
        })
    }
}
<commit_msg>Update src/utils/queue.rs<commit_after>//! Utilities for interacting with the build queue

use crate::error::Result;
use postgres::Connection;

const DEFAULT_PRIORITY: i32 = 0;

/// Get the build queue priority for a crate
pub fn get_crate_priority(conn: &Connection, name: &str) -> Result<i32> {
    // Search the `priority` table for a priority where the crate name matches the stored pattern
    let query = conn.query(
        "SELECT priority FROM crate_priorities WHERE $1 LIKE pattern LIMIT 1",
        &[&name],
    )?;

    // If no match is found, return the default priority
    if let Some(row) = query.iter().next() {
        Ok(row.get(0))
    } else {
        Ok(DEFAULT_PRIORITY)
    }
}

/// Adds a crate to the build queue to be built by rustdoc. `priority` should be gotten from `get_crate_priority`
pub fn add_crate_to_queue(
    conn: &Connection,
    name: &str,
    version: &str,
    priority: i32,
) -> Result<()> {
    conn.execute(
        "INSERT INTO queue (name, version, priority) VALUES ($1, $2, $3)",
        &[&name, &version, &priority],
    )?;

    Ok(())
}

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

    /// Set all crates that match [`pattern`] to have a certain priority
    ///
    /// Note: `pattern` is used in a `LIKE` statement, so it must follow the postgres like syntax
    ///
    /// [`pattern`]: https://www.postgresql.org/docs/8.3/functions-matching.html
    pub fn set_crate_priority(conn: &Connection, pattern: &str, priority: i32) -> Result<()> {
        conn.query(
            "INSERT INTO crate_priorities (pattern, priority) VALUES ($1, $2)",
            &[&pattern, &priority],
        )?;

        Ok(())
    }

    /// Remove a pattern from the priority table, returning the priority that it was associated with or `None`
    /// if nothing was removed
    pub fn remove_crate_priority(conn: &Connection, pattern: &str) -> Result<Option<i32>> {
        let query = conn.query(
            "DELETE FROM crate_priorities WHERE pattern = $1 RETURNING priority",
            &[&pattern],
        )?;

        Ok(query.iter().next().map(|row| row.get(0)))
    }

    #[test]
    fn set_priority() {
        wrapper(|env| {
            let db = env.db();

            set_crate_priority(&db.conn(), "cratesfyi-%", -100)?;
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-database")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-s3")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-webserver")?, -100);
            assert_eq!(
                get_crate_priority(&db.conn(), "cratesfyi")?,
                DEFAULT_PRIORITY
            );

            set_crate_priority(&db.conn(), "_c_", 100)?;
            assert_eq!(get_crate_priority(&db.conn(), "rcc")?, 100);
            assert_eq!(get_crate_priority(&db.conn(), "rc")?, DEFAULT_PRIORITY);

            set_crate_priority(&db.conn(), "hexponent", 10)?;
            assert_eq!(get_crate_priority(&db.conn(), "hexponent")?, 10);
            assert_eq!(
                get_crate_priority(&db.conn(), "hexponents")?,
                DEFAULT_PRIORITY
            );
            assert_eq!(
                get_crate_priority(&db.conn(), "floathexponent")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn remove_priority() {
        wrapper(|env| {
            let db = env.db();

            set_crate_priority(&db.conn(), "cratesfyi-%", -100)?;
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-")?, -100);

            assert_eq!(
                remove_crate_priority(&db.conn(), "cratesfyi-%")?,
                Some(-100)
            );
            assert_eq!(
                get_crate_priority(&db.conn(), "cratesfyi-")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn get_priority() {
        wrapper(|env| {
            let db = env.db();

            set_crate_priority(&db.conn(), "cratesfyi-%", -100)?;

            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-database")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-s3")?, -100);
            assert_eq!(get_crate_priority(&db.conn(), "cratesfyi-webserver")?, -100);
            assert_eq!(
                get_crate_priority(&db.conn(), "unrelated")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn get_default_priority() {
        wrapper(|env| {
            let db = env.db();

            assert_eq!(
                get_crate_priority(&db.conn(), "cratesfyi")?,
                DEFAULT_PRIORITY
            );
            assert_eq!(get_crate_priority(&db.conn(), "rcc")?, DEFAULT_PRIORITY);
            assert_eq!(get_crate_priority(&db.conn(), "lasso")?, DEFAULT_PRIORITY);
            assert_eq!(
                get_crate_priority(&db.conn(), "hexponent")?,
                DEFAULT_PRIORITY
            );
            assert_eq!(
                get_crate_priority(&db.conn(), "rust4lyfe")?,
                DEFAULT_PRIORITY
            );

            Ok(())
        })
    }

    #[test]
    fn add_to_queue() {
        wrapper(|env| {
            let db = env.db();

            let test_crates = [
                ("rcc", "0.1.0", 2),
                ("lasso", "0.1.0", -1),
                ("hexponent", "0.1.0", 0),
                ("destroy-all-humans", "0.0.0-alpha", -100000),
                ("totally-not-destroying-humans", "0.0.1", 0),
            ];

            for (name, version, priority) in test_crates.iter() {
                add_crate_to_queue(&db.conn(), name, version, *priority)?;

                let query = db.conn().query(
                    "SELECT name, version, priority FROM queue WHERE name = $1",
                    &[&name],
                )?;

                assert!(query.len() == 1);
                let row = query.iter().next().unwrap();

                assert_eq!(&row.get::<_, String>(0), name);
                assert_eq!(&row.get::<_, String>(1), version);
                assert_eq!(row.get::<_, i32>(2), *priority);
            }

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