<commit_before>use std::slice;
use std::vec;
use std::cmp;

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// The iterator **Zip\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::Zip;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
///
/// for (i, a, b) in Zip::new((0i32..100, xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct Zip<T> {
    t: T
}

impl<T> Zip<T> where Zip<T>: Iterator
{
    /// Create a new **Zip** from a tuple of iterators.
    pub fn new(t: T) -> Zip<T>
    {
        Zip{t: t}
    }
}

macro_rules! impl_zip_iter {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for Zip<($($B,)*)>
            where
            $(
                $B: Iterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<
                    ($(<$B as Iterator>::Item,)*)
                >
            {
                let &mut Zip { t : ($(ref mut $B,)*)} = self;
                // WARNING: partial consume possible
                // Zip worked the same.
                $(
                    let $B = match $B.next() {
                        None => return None,
                        Some(elt) => elt
                    };
                )*
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                let low = ::std::usize::MAX;
                let high = None;
                let &Zip { t : ($(ref $B,)*) } = self;
                $(
                    // update estimate
                    let (l, h) = $B.size_hint();
                    let low = cmp::min(low, l);
                    let high = match (high, h) {
                        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
                        _ => high.or(h)
                    };
                )*
                (low, high)
            }
        }
    );
}

impl_zip_iter!(A);
impl_zip_iter!(A, B);
impl_zip_iter!(A, B, C);
impl_zip_iter!(A, B, C, D);
impl_zip_iter!(A, B, C, D, E);
impl_zip_iter!(A, B, C, D, E, F);
impl_zip_iter!(A, B, C, D, E, F, G);
impl_zip_iter!(A, B, C, D, E, F, G, H);
impl_zip_iter!(A, B, C, D, E, F, G, H, I);

/// A **TrustedIterator** has exact size, always.
pub unsafe trait TrustedIterator : ExactSizeIterator
{
    /* no methods */
}

/* Not safe yet!
unsafe impl TrustedIterator for ::std::ops::Range<usize> { }
unsafe impl TrustedIterator for ::std::ops::Range<u32> { }
unsafe impl TrustedIterator for ::std::ops::Range<i32> { }
unsafe impl TrustedIterator for ::std::ops::Range<u16> { }
unsafe impl TrustedIterator for ::std::ops::Range<i16> { }
unsafe impl TrustedIterator for ::std::ops::Range<u8> { }
unsafe impl TrustedIterator for ::std::ops::Range<i8> { }
*/
unsafe impl<'a, T> TrustedIterator for slice::Iter<'a, T> { }
unsafe impl<'a, T> TrustedIterator for slice::IterMut<'a, T> { }
unsafe impl<T> TrustedIterator for vec::IntoIter<T> { }

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// **ZipTrusted** is an experimental version of **Zip**, and it can only use iterators that are
/// known to provide their exact size up front. The lockstep iteration can then compile to faster
/// code, ideally not checking more than once per lap for the end of iteration.
///
/// The iterator **ZipTrusted\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::ZipTrusted;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
///
/// for (i, a, b) in ZipTrusted::new((0i32..100, xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct ZipTrusted<T> {
    length: usize,
    t: T
}

trait SetLength {
    fn set_length(&mut self);
}

impl<T> ZipTrusted<T> where ZipTrusted<T>: SetLength
{
    /// Create a new **ZipTrusted** from a tuple of iterators.
    #[inline]
    pub fn new(t: T) -> ZipTrusted<T>
    {
        let mut iter = ZipTrusted {
            length: 0,
            t: t,
        };
        iter.set_length();
        iter
    }
}

macro_rules! impl_zip_trusted {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> SetLength for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            #[inline]
            fn set_length(&mut self)
            {
                let len = ::std::usize::MAX;
                let ($(ref $B,)*) = self.t;
                $(
                    let (l, h) = $B.size_hint();
                    let len = cmp::min(len, l);
                    debug_assert!(Some(l) == h);
                )*
                self.length = len;
            }
        }

        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<<Self as Iterator>::Item>
            {
                let ($(ref mut $B,)*) = self.t;

                if self.length == 0 {
                    return None
                }
                $(
                    let next_opt = $B.next();
                    let $B;
                    unsafe {
                        ::std::intrinsics::assume(match next_opt {
                            None => false,
                            Some(_) => true,
                        });
                        $B = match next_opt {
                            None => return None,
                            Some(elt) => elt
                        };
                    }
                )*
                self.length -= 1;
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                (self.length, Some(self.length))
            }
        }
    );
}

impl_zip_trusted!(A);
impl_zip_trusted!(A, B);
impl_zip_trusted!(A, B, C);
impl_zip_trusted!(A, B, C, D);
impl_zip_trusted!(A, B, C, D, E);
impl_zip_trusted!(A, B, C, D, E, F);
impl_zip_trusted!(A, B, C, D, E, F, G);
impl_zip_trusted!(A, B, C, D, E, F, G, H);
impl_zip_trusted!(A, B, C, D, E, F, G, H, I);

<commit_msg>Fix example<commit_after>use std::slice;
use std::vec;
use std::cmp;

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// The iterator **Zip\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::Zip;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
///
/// for (i, a, b) in Zip::new((0i32..100, xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct Zip<T> {
    t: T
}

impl<T> Zip<T> where Zip<T>: Iterator
{
    /// Create a new **Zip** from a tuple of iterators.
    pub fn new(t: T) -> Zip<T>
    {
        Zip{t: t}
    }
}

macro_rules! impl_zip_iter {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for Zip<($($B,)*)>
            where
            $(
                $B: Iterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<
                    ($(<$B as Iterator>::Item,)*)
                >
            {
                let &mut Zip { t : ($(ref mut $B,)*)} = self;
                // WARNING: partial consume possible
                // Zip worked the same.
                $(
                    let $B = match $B.next() {
                        None => return None,
                        Some(elt) => elt
                    };
                )*
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                let low = ::std::usize::MAX;
                let high = None;
                let &Zip { t : ($(ref $B,)*) } = self;
                $(
                    // update estimate
                    let (l, h) = $B.size_hint();
                    let low = cmp::min(low, l);
                    let high = match (high, h) {
                        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
                        _ => high.or(h)
                    };
                )*
                (low, high)
            }
        }
    );
}

impl_zip_iter!(A);
impl_zip_iter!(A, B);
impl_zip_iter!(A, B, C);
impl_zip_iter!(A, B, C, D);
impl_zip_iter!(A, B, C, D, E);
impl_zip_iter!(A, B, C, D, E, F);
impl_zip_iter!(A, B, C, D, E, F, G);
impl_zip_iter!(A, B, C, D, E, F, G, H);
impl_zip_iter!(A, B, C, D, E, F, G, H, I);

/// A **TrustedIterator** has exact size, always.
pub unsafe trait TrustedIterator : ExactSizeIterator
{
    /* no methods */
}

/* Not safe yet!
unsafe impl TrustedIterator for ::std::ops::Range<usize> { }
unsafe impl TrustedIterator for ::std::ops::Range<u32> { }
unsafe impl TrustedIterator for ::std::ops::Range<i32> { }
unsafe impl TrustedIterator for ::std::ops::Range<u16> { }
unsafe impl TrustedIterator for ::std::ops::Range<i16> { }
unsafe impl TrustedIterator for ::std::ops::Range<u8> { }
unsafe impl TrustedIterator for ::std::ops::Range<i8> { }
*/
unsafe impl<'a, T> TrustedIterator for slice::Iter<'a, T> { }
unsafe impl<'a, T> TrustedIterator for slice::IterMut<'a, T> { }
unsafe impl<T> TrustedIterator for vec::IntoIter<T> { }

#[derive(Clone)]
/// Create an iterator running multiple iterators in lockstep.
///
/// **ZipTrusted** is an experimental version of **Zip**, and it can only use iterators that are
/// known to provide their exact size up front. The lockstep iteration can then compile to faster
/// code, ideally not checking more than once per lap for the end of iteration.
///
/// The iterator **ZipTrusted\<(I, J, ..., M)\>** is formed from a tuple of iterators and yields elements
/// until any of the subiterators yields **None**.
///
/// Iterator element type is like **(A, B, ..., E)** where **A** to **E** are the respective
/// subiterator types.
///
/// ## Example
///
/// ```
/// use itertools::ZipTrusted;
///
/// // Iterate over three sequences side-by-side
/// let mut xs = [0, 0, 0];
/// let ys = [69, 107, 101];
/// let index = [0, 1, 2, 3];
///
/// for (&i, a, b) in ZipTrusted::new((index.iter(), xs.iter_mut(), ys.iter())) {
///    *a = i ^ *b;
/// }
///
/// assert_eq!(xs, [69, 106, 103]);
/// ```
pub struct ZipTrusted<T> {
    length: usize,
    t: T
}

trait SetLength {
    fn set_length(&mut self);
}

impl<T> ZipTrusted<T> where ZipTrusted<T>: SetLength
{
    /// Create a new **ZipTrusted** from a tuple of iterators.
    #[inline]
    pub fn new(t: T) -> ZipTrusted<T>
    {
        let mut iter = ZipTrusted {
            length: 0,
            t: t,
        };
        iter.set_length();
        iter
    }
}

macro_rules! impl_zip_trusted {
    ($($B:ident),*) => (
        #[allow(non_snake_case)]
        impl<$($B),*> SetLength for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            #[inline]
            fn set_length(&mut self)
            {
                let len = ::std::usize::MAX;
                let ($(ref $B,)*) = self.t;
                $(
                    let (l, h) = $B.size_hint();
                    let len = cmp::min(len, l);
                    debug_assert!(Some(l) == h);
                )*
                self.length = len;
            }
        }

        #[allow(non_snake_case)]
        impl<$($B),*> Iterator for ZipTrusted<($($B,)*)>
            where
            $(
                $B: TrustedIterator,
            )*
        {
            type Item = ($(<$B as Iterator>::Item,)*);

            fn next(&mut self) -> Option<<Self as Iterator>::Item>
            {
                let ($(ref mut $B,)*) = self.t;

                if self.length == 0 {
                    return None
                }
                $(
                    let next_opt = $B.next();
                    let $B;
                    unsafe {
                        ::std::intrinsics::assume(match next_opt {
                            None => false,
                            Some(_) => true,
                        });
                        $B = match next_opt {
                            None => return None,
                            Some(elt) => elt
                        };
                    }
                )*
                self.length -= 1;
                Some(($($B,)*))
            }

            fn size_hint(&self) -> (usize, Option<usize>)
            {
                (self.length, Some(self.length))
            }
        }
    );
}

impl_zip_trusted!(A);
impl_zip_trusted!(A, B);
impl_zip_trusted!(A, B, C);
impl_zip_trusted!(A, B, C, D);
impl_zip_trusted!(A, B, C, D, E);
impl_zip_trusted!(A, B, C, D, E, F);
impl_zip_trusted!(A, B, C, D, E, F, G);
impl_zip_trusted!(A, B, C, D, E, F, G, H);
impl_zip_trusted!(A, B, C, D, E, F, G, H, I);

<|endoftext|>


<commit_before>// ignore-android: FIXME(#10381)
// compile-flags:-g

// gdb-command: run

// gdb-command: print slice
// gdbg-check: $1 = struct &[i32](size=3) = {0, 1, 2}
// gdbr-check: $1 = &[i32](size=3) = {0, 1, 2}

// gdb-command: print mut_slice
// gdbg-check: $2 = struct &mut [i32](size=4) = {2, 3, 5, 7}
// gdbr-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7}

// gdb-command: print str_slice
// gdb-check: $3 = "string slice"

// gdb-command: print mut_str_slice
// gdb-check: $4 = "mutable string slice"

// lldb-command: run

// lldb-command: print slice
// lldb-check: (&[i32]) $0 = size=3 { [0] = 0 [1] = 1 [2] = 2 }

// lldb-command: print mut_slice
// lldb-check: (&mut [i32]) $1 = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 }

// lldb-command: print str_slice
// lldb-check: (&str) $2 = "string slice" { data_ptr = [...] length = 12 }

// lldb-command: print mut_str_slice
// lldb-check: (&mut str) $3 = "mutable string slice" { data_ptr = [...] length = 20 }

fn b() {}

fn main() {
    let slice: &[i32] = &[0, 1, 2];
    let mut_slice: &mut [i32] = &mut [2, 3, 5, 7];

    let str_slice: &str = "string slice";
    let mut mut_str_slice_buffer = String::from("mutable string slice");
    let mut_str_slice: &mut str = mut_str_slice_buffer.as_mut_str();

    b(); // #break
}
<commit_msg>Ignore Windows debugger pretty-printing tests<commit_after>// ignore-android: FIXME(#10381)
// ignore-windows
// compile-flags:-g

// gdb-command: run

// gdb-command: print slice
// gdbg-check: $1 = struct &[i32](size=3) = {0, 1, 2}
// gdbr-check: $1 = &[i32](size=3) = {0, 1, 2}

// gdb-command: print mut_slice
// gdbg-check: $2 = struct &mut [i32](size=4) = {2, 3, 5, 7}
// gdbr-check: $2 = &mut [i32](size=4) = {2, 3, 5, 7}

// gdb-command: print str_slice
// gdb-check: $3 = "string slice"

// gdb-command: print mut_str_slice
// gdb-check: $4 = "mutable string slice"

// lldb-command: run

// lldb-command: print slice
// lldb-check: (&[i32]) $0 = size=3 { [0] = 0 [1] = 1 [2] = 2 }

// lldb-command: print mut_slice
// lldb-check: (&mut [i32]) $1 = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 }

// lldb-command: print str_slice
// lldb-check: (&str) $2 = "string slice" { data_ptr = [...] length = 12 }

// lldb-command: print mut_str_slice
// lldb-check: (&mut str) $3 = "mutable string slice" { data_ptr = [...] length = 20 }

fn b() {}

fn main() {
    let slice: &[i32] = &[0, 1, 2];
    let mut_slice: &mut [i32] = &mut [2, 3, 5, 7];

    let str_slice: &str = "string slice";
    let mut mut_str_slice_buffer = String::from("mutable string slice");
    let mut_str_slice: &mut str = mut_str_slice_buffer.as_mut_str();

    b(); // #break
}
<|endoftext|>


<commit_before>use std::fmt;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::message::Message;
use crate::message_dyn::MessageDyn;
use crate::reflect::dynamic::DynamicMessage;
use crate::reflect::file::index::FileIndexMessageEntry;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::message::dynamic::DynamicMessageDescriptor;
use crate::reflect::message::generated::GeneratedMessageDescriptor;
use crate::reflect::message::index::MessageIndex;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::FileDescriptor;
use crate::reflect::OneofDescriptor;

pub(crate) mod dynamic;
pub(crate) mod generated;
pub(crate) mod index;
pub(crate) mod message_ref;
pub(crate) mod path;

/// Dynamic representation of message type.
///
/// Used for reflection.
#[derive(Clone, Eq, PartialEq)]
pub struct MessageDescriptor {
    file_descriptor: FileDescriptor,
    index: usize,
}

impl fmt::Display for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageDescriptor")
            // TODO: add smth
            .finish()
    }
}

impl MessageDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get internal index.
    ///
    /// Only needed for codegen.
    #[doc(hidden)]
    pub fn get_index_in_file_for_codegen(&self) -> usize {
        self.index
    }

    /// Get underlying `DescriptorProto` object.
    pub fn get_proto(&self) -> &DescriptorProto {
        self.file_descriptor.message_proto(self.index)
    }

    /// Message name as specified in `.proto` file.
    pub fn get_name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Get enums declared in this message.
    pub fn get_enums(&self) -> Vec<EnumDescriptor> {
        let first_enum_index = self.get_index_entry().first_enum_index;
        self.get_proto()
            .enum_type
            .iter()
            .enumerate()
            .map(|(i, _)| EnumDescriptor::new(self.file_descriptor.clone(), first_enum_index + i))
            .collect()
    }

    fn get_index_entry(&self) -> &FileIndexMessageEntry {
        self.file_descriptor.message_index_entry(self.index)
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: Message>() -> MessageDescriptor {
        M::descriptor_static()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor::new(file_descriptor, index)
    }

    /// Messages declared in this messages.
    pub fn get_nested_messages(&self) -> Vec<MessageDescriptor> {
        self.get_index_entry()
            .nested_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), *i))
            .collect()
    }

    pub(crate) fn get_impl(&self) -> MessageDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                MessageDescriptorImplRef::Generated(&g.messages[self.index])
            }
            FileDescriptorImpl::Dynamic(d) => {
                MessageDescriptorImplRef::Dynamic(&d.messages[self.index])
            }
        }
    }

    /// [`FileDescriptor`] containing this message.
    pub fn file_descriptor(&self) -> &FileDescriptor {
        &self.file_descriptor
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor().proto()
    }

    /// This message descriptor is a map entry.
    pub fn is_map_entry(&self) -> bool {
        self.get_proto().options.get_or_default().get_map_entry()
    }

    fn assert_not_map_entry(&self) {
        assert!(
            !self.is_map_entry(),
            "message is map entry: {}",
            self.full_name()
        );
    }

    /// New empty message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn new_instance(&self) -> Box<dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.new_instance(),
            MessageDescriptorImplRef::Dynamic(..) => Box::new(DynamicMessage::new(self.clone())),
        }
    }

    /// Shared immutable empty message.
    ///
    /// Returns `None` for dynamic message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn default_instance(&self) -> Option<&'static dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => Some(g.non_map().factory.default_instance()),
            MessageDescriptorImplRef::Dynamic(..) => None,
        }
    }

    /// Clone a message
    pub(crate) fn clone_message(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        assert!(&message.descriptor_dyn() == self);
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.clone(message),
            MessageDescriptorImplRef::Dynamic(..) => {
                let message: &DynamicMessage = <dyn MessageDyn>::downcast_ref(message).unwrap();
                Box::new(message.clone())
            }
        }
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.eq(a, b),
            MessageDescriptorImplRef::Dynamic(..) => unimplemented!(),
        }
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub(crate) fn reflect_eq(
        &self,
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(self, &a.descriptor_dyn());
        assert_eq!(self, &b.descriptor_dyn());

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_eq(&bf, mode) {
                return false;
            }
        }
        true
    }

    pub(crate) fn reflect_eq_maybe_unrelated(
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        let ad = a.descriptor_dyn();
        let bd = b.descriptor_dyn();
        ad == bd && ad.reflect_eq(a, b, mode)
    }

    /// Message name as given in `.proto` file
    pub fn name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.get_index_entry().full_name
    }

    /// Message field descriptors.
    pub fn fields<'a>(&'a self) -> impl ExactSizeIterator<Item = FieldDescriptor> + 'a {
        (0..self.get_index().fields.len()).map(move |index| FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Nested oneofs
    pub fn oneofs<'a>(&'a self) -> impl ExactSizeIterator<Item = OneofDescriptor> + 'a {
        self.get_proto()
            .oneof_decl
            .iter()
            .enumerate()
            .map(move |(index, _)| OneofDescriptor {
                message_descriptor: self.clone(),
                index,
            })
    }

    pub(crate) fn get_index(&self) -> &MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(d) => &d.indices,
        }
    }

    pub(crate) fn get_generated_index(&self) -> &'static MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(_) => panic!("dynamic message: {}", self),
        }
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    // TODO: return value, not pointer, pointer is not compatible with dynamic message
    pub fn get_field_by_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name or field JSON name
    pub fn get_field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name_or_json_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name
    pub fn get_field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_number.get(&number)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }
}

pub(crate) enum MessageDescriptorImplRef<'a> {
    Generated(&'static GeneratedMessageDescriptor),
    Dynamic(&'a DynamicMessageDescriptor),
}
<commit_msg>Shortcuts to parse DynamicMessage<commit_after>use std::fmt;
use std::io::Read;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::message::Message;
use crate::message_dyn::MessageDyn;
use crate::reflect::dynamic::DynamicMessage;
use crate::reflect::file::index::FileIndexMessageEntry;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::message::dynamic::DynamicMessageDescriptor;
use crate::reflect::message::generated::GeneratedMessageDescriptor;
use crate::reflect::message::index::MessageIndex;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::FileDescriptor;
use crate::reflect::OneofDescriptor;
use crate::CodedInputStream;
use crate::ProtobufResult;

pub(crate) mod dynamic;
pub(crate) mod generated;
pub(crate) mod index;
pub(crate) mod message_ref;
pub(crate) mod path;

/// Dynamic representation of message type.
///
/// Used for reflection.
#[derive(Clone, Eq, PartialEq)]
pub struct MessageDescriptor {
    file_descriptor: FileDescriptor,
    index: usize,
}

impl fmt::Display for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageDescriptor")
            // TODO: add smth
            .finish()
    }
}

impl MessageDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get internal index.
    ///
    /// Only needed for codegen.
    #[doc(hidden)]
    pub fn get_index_in_file_for_codegen(&self) -> usize {
        self.index
    }

    /// Get underlying `DescriptorProto` object.
    pub fn get_proto(&self) -> &DescriptorProto {
        self.file_descriptor.message_proto(self.index)
    }

    /// Message name as specified in `.proto` file.
    pub fn get_name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Get enums declared in this message.
    pub fn get_enums(&self) -> Vec<EnumDescriptor> {
        let first_enum_index = self.get_index_entry().first_enum_index;
        self.get_proto()
            .enum_type
            .iter()
            .enumerate()
            .map(|(i, _)| EnumDescriptor::new(self.file_descriptor.clone(), first_enum_index + i))
            .collect()
    }

    fn get_index_entry(&self) -> &FileIndexMessageEntry {
        self.file_descriptor.message_index_entry(self.index)
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: Message>() -> MessageDescriptor {
        M::descriptor_static()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor::new(file_descriptor, index)
    }

    /// Messages declared in this messages.
    pub fn get_nested_messages(&self) -> Vec<MessageDescriptor> {
        self.get_index_entry()
            .nested_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), *i))
            .collect()
    }

    pub(crate) fn get_impl(&self) -> MessageDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                MessageDescriptorImplRef::Generated(&g.messages[self.index])
            }
            FileDescriptorImpl::Dynamic(d) => {
                MessageDescriptorImplRef::Dynamic(&d.messages[self.index])
            }
        }
    }

    /// [`FileDescriptor`] containing this message.
    pub fn file_descriptor(&self) -> &FileDescriptor {
        &self.file_descriptor
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor().proto()
    }

    /// This message descriptor is a map entry.
    pub fn is_map_entry(&self) -> bool {
        self.get_proto().options.get_or_default().get_map_entry()
    }

    fn assert_not_map_entry(&self) {
        assert!(
            !self.is_map_entry(),
            "message is map entry: {}",
            self.full_name()
        );
    }

    /// New empty message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn new_instance(&self) -> Box<dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.new_instance(),
            MessageDescriptorImplRef::Dynamic(..) => Box::new(DynamicMessage::new(self.clone())),
        }
    }

    /// Shared immutable empty message.
    ///
    /// Returns `None` for dynamic message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn default_instance(&self) -> Option<&'static dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => Some(g.non_map().factory.default_instance()),
            MessageDescriptorImplRef::Dynamic(..) => None,
        }
    }

    /// Clone a message
    pub(crate) fn clone_message(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        assert!(&message.descriptor_dyn() == self);
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.clone(message),
            MessageDescriptorImplRef::Dynamic(..) => {
                let message: &DynamicMessage = <dyn MessageDyn>::downcast_ref(message).unwrap();
                Box::new(message.clone())
            }
        }
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.eq(a, b),
            MessageDescriptorImplRef::Dynamic(..) => unimplemented!(),
        }
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub(crate) fn reflect_eq(
        &self,
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(self, &a.descriptor_dyn());
        assert_eq!(self, &b.descriptor_dyn());

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_eq(&bf, mode) {
                return false;
            }
        }
        true
    }

    pub(crate) fn reflect_eq_maybe_unrelated(
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        let ad = a.descriptor_dyn();
        let bd = b.descriptor_dyn();
        ad == bd && ad.reflect_eq(a, b, mode)
    }

    /// Message name as given in `.proto` file
    pub fn name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.get_index_entry().full_name
    }

    /// Message field descriptors.
    pub fn fields<'a>(&'a self) -> impl ExactSizeIterator<Item = FieldDescriptor> + 'a {
        (0..self.get_index().fields.len()).map(move |index| FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Nested oneofs
    pub fn oneofs<'a>(&'a self) -> impl ExactSizeIterator<Item = OneofDescriptor> + 'a {
        self.get_proto()
            .oneof_decl
            .iter()
            .enumerate()
            .map(move |(index, _)| OneofDescriptor {
                message_descriptor: self.clone(),
                index,
            })
    }

    pub(crate) fn get_index(&self) -> &MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(d) => &d.indices,
        }
    }

    pub(crate) fn get_generated_index(&self) -> &'static MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(_) => panic!("dynamic message: {}", self),
        }
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    // TODO: return value, not pointer, pointer is not compatible with dynamic message
    pub fn get_field_by_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name or field JSON name
    pub fn get_field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name_or_json_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name
    pub fn get_field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_number.get(&number)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Parse message from stream.
    pub fn parse_from(&self, is: &mut CodedInputStream) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut r = self.new_instance();
        r.merge_from_dyn(is)?;
        r.check_initialized_dyn()?;
        Ok(r)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    pub fn parse_from_reader(&self, reader: &mut dyn Read) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::new(reader);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    pub fn parse_from_bytes(&self, bytes: &[u8]) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }
}

pub(crate) enum MessageDescriptorImplRef<'a> {
    Generated(&'static GeneratedMessageDescriptor),
    Dynamic(&'a DynamicMessageDescriptor),
}
<|endoftext|>


<commit_before>use crate::ipc_protocol::{
    ServerConnection,
    ServerResponse,
    DrawingProp,
    DrawingPropValue,
};
use crate::renderer_client::ClientId;

use super::super::access_control::{AccessControl, RequiredData};

pub(crate) async fn drawing_prop(
    conn: &ServerConnection,
    client_id: ClientId,
    app_control: &AccessControl,
    prop: DrawingProp,
) {
    let mut data = app_control.get(RequiredData {
        drawing: true,
        turtles: None,
    }).await;

    let drawing = data.drawing_mut();

    use DrawingProp::*;
    let value = match prop {
        Title => DrawingPropValue::Title(drawing.title.clone()),
        Background => DrawingPropValue::Background(drawing.background),
        Center => DrawingPropValue::Center(drawing.center),
        Size => DrawingPropValue::Size(crate::Size {width: drawing.width, height: drawing.height}),
        Width => DrawingPropValue::Width(drawing.width),
        Height => DrawingPropValue::Height(drawing.height),
        IsMaximized => DrawingPropValue::IsMaximized(drawing.is_maximized),
        IsFullscreen => DrawingPropValue::IsFullscreen(drawing.is_fullscreen),
    };

    conn.send(client_id, ServerResponse::DrawingProp(value)).await
        .expect("unable to send response to IPC client");
}

pub(crate) async fn set_drawing_prop(app_control: &AccessControl, prop_value: DrawingPropValue) {
    let mut data = app_control.get(RequiredData {
        drawing: true,
        turtles: None,
    }).await;

    let drawing = data.drawing_mut();

    use DrawingPropValue::*;
    match prop_value {
        Title(title) => drawing.title = title,
        Background(background) => drawing.background = background,
        Center(center) => drawing.center = center,
        Size(crate::Size {width, height}) => {
            drawing.width = width;
            drawing.height = height;
        },
        Width(width) => drawing.width = width,
        Height(height) => drawing.height = height,
        IsMaximized(is_maximized) => drawing.is_maximized = is_maximized,
        IsFullscreen(is_fullscreen) => drawing.is_fullscreen = is_fullscreen,
    }
}
<commit_msg>Added TODO for actually updating the window in response to changes to DrawingState<commit_after>use crate::ipc_protocol::{
    ServerConnection,
    ServerResponse,
    DrawingProp,
    DrawingPropValue,
};
use crate::renderer_client::ClientId;

use super::super::access_control::{AccessControl, RequiredData};

pub(crate) async fn drawing_prop(
    conn: &ServerConnection,
    client_id: ClientId,
    app_control: &AccessControl,
    prop: DrawingProp,
) {
    let mut data = app_control.get(RequiredData {
        drawing: true,
        turtles: None,
    }).await;

    let drawing = data.drawing_mut();

    use DrawingProp::*;
    let value = match prop {
        Title => DrawingPropValue::Title(drawing.title.clone()),
        Background => DrawingPropValue::Background(drawing.background),
        Center => DrawingPropValue::Center(drawing.center),
        Size => DrawingPropValue::Size(crate::Size {width: drawing.width, height: drawing.height}),
        Width => DrawingPropValue::Width(drawing.width),
        Height => DrawingPropValue::Height(drawing.height),
        IsMaximized => DrawingPropValue::IsMaximized(drawing.is_maximized),
        IsFullscreen => DrawingPropValue::IsFullscreen(drawing.is_fullscreen),
    };

    conn.send(client_id, ServerResponse::DrawingProp(value)).await
        .expect("unable to send response to IPC client");
}

pub(crate) async fn set_drawing_prop(app_control: &AccessControl, prop_value: DrawingPropValue) {
    let mut data = app_control.get(RequiredData {
        drawing: true,
        turtles: None,
    }).await;

    let drawing = data.drawing_mut();

    //TODO: Send events through EventLoopProxy that indicate changes in the window (e.g. for
    // changes to `is_maximized` we should call the appropriate method on the Window)
    use DrawingPropValue::*;
    match prop_value {
        Title(title) => drawing.title = title,
        Background(background) => drawing.background = background,
        Center(center) => drawing.center = center,
        Size(crate::Size {width, height}) => {
            drawing.width = width;
            drawing.height = height;
        },
        Width(width) => drawing.width = width,
        Height(height) => drawing.height = height,
        IsMaximized(is_maximized) => drawing.is_maximized = is_maximized,
        IsFullscreen(is_fullscreen) => drawing.is_fullscreen = is_fullscreen,
    }
}
<|endoftext|>


<commit_before><commit_msg>mesh: remove block_exists<commit_after><|endoftext|>


<commit_before><commit_msg>Remove warning<commit_after><|endoftext|>


<commit_before><commit_msg>replace .insert by .insert_with<commit_after><|endoftext|>


<commit_before><commit_msg>Separate MappingParseError from FieldMappingParseError<commit_after><|endoftext|>


<commit_before><commit_msg>Fixing a major bug in the optimizations that was incorrectly removing jump instructions<commit_after><|endoftext|>


<commit_before><commit_msg>added whiteline<commit_after><|endoftext|>


<commit_before>use webcore::value::Reference;
use webcore::try_from::TryInto;
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::window_or_worker::IWindowOrWorker;
use webapi::storage::Storage;
use webapi::location::Location;
use webapi::history::History;
use webcore::once::Once;
use webcore::value::Value;

/// A handle to a pending animation frame request.
#[derive(Debug)]
pub struct RequestAnimationFrameHandle(Value);

impl RequestAnimationFrameHandle {
    /// Cancels an animation frame request.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame)
    pub fn cancel( self ) {
        js! { @(no_return)
            var val = @{&self.0};
            val.window.cancelAnimationFrame(val.request);
            val.callback.drop();
        }
    }
}

/// The `Window` object represents a window containing a DOM document.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window)
// https://html.spec.whatwg.org/#window
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Window")]
#[reference(subclass_of(EventTarget))]
pub struct Window( Reference );

impl IEventTarget for Window {}
impl IWindowOrWorker for Window {}

/// A global instance of [Window](struct.Window.html).
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window)
pub fn window() -> Window {
    unsafe { js!( return window; ).into_reference_unchecked() }.unwrap()
}

impl Window {
    /// The Window.alert() method displays an alert dialog
    /// with the optional specified content and an OK button.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert)
    // https://html.spec.whatwg.org/#the-window-object:dom-alert
    pub fn alert( &self, message: &str ) {
        js!( @(no_return)
            @{self}.alert( @{message} );
        );
    }

    /// The `local_storage` property allows you to access a local [Storage](struct.Storage.html)
    /// object.
    ///
    /// It is similar to the [Window::session_storage](struct.Window.html#method.session_storage).
    /// The only difference is that, while data stored in `local_storage` has
    /// no expiration time, data stored in `session_storage` gets cleared when
    /// the browsing session ends - that is, when the browser is closed.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)
    // https://html.spec.whatwg.org/#the-localstorage-attribute:dom-localstorage
    pub fn local_storage( &self ) -> Storage {
        unsafe {
            js!(
                return @{self.as_ref()}.localStorage;
            ).into_reference_unchecked().unwrap()
        }
    }

    /// The `session_storage` property allows you to access a session [Storage](struct.Storage.html)
    /// object for the current origin.
    ///
    /// It is similar to the [Window::local_storage](struct.Window.html#method.local_storage),
    /// The only difference is that, while data stored in `local_storage` has
    /// no expiration time, data stored in `session_storage` gets cleared when
    /// the browsing session ends.
    ///
    /// A page session lasts for as long as the browser is open and survives over
    /// page reloads and restores. Opening a page in a new tab or window will cause
    /// a new session to be initiated, which differs from how session cookies work.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)
    // https://html.spec.whatwg.org/#the-sessionstorage-attribute:dom-sessionstorage
    pub fn session_storage( &self ) -> Storage {
        unsafe {
            js!(
                return @{self.as_ref()}.sessionStorage;
            ).into_reference_unchecked().unwrap()
        }
    }

    /// Returns a [Location](struct.Location.html) object which contains
    /// information about the URL of the document and provides methods
    /// for changing that URL and loading another URL.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/location)
    // https://html.spec.whatwg.org/#the-window-object:dom-location
    pub fn location( &self ) -> Option< Location > {
        unsafe {
            js!(
                return @{self}.location;
            ).into_reference_unchecked()
        }
    }

    /// You should call this method whenever you're ready to update your animation onscreen.
    /// This will request that your animation function be called before the browser performs the next repaint.
    /// The number of callbacks is usually 60 times per second, but will generally match the display refresh
    /// rate in most web browsers as per W3C recommendation. request_animation_frame() calls are paused in most browsers
    /// when running in background tabs or hidden iframes in order to improve performance and battery life.
    ///
    /// The callback method is passed a single argument, a f64, which indicates the current time when
    /// callbacks queued by requestAnimationFrame() begin to fire. Multiple callbacks in a single frame, therefore,
    /// each receive the same timestamp even though time has passed during the computation of every previous callback's workload.
    /// This timestamp is a decimal number, in milliseconds, but with a minimal precision of 1ms (1000 µs).
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
    // https://html.spec.whatwg.org/#the-window-object:dom-window-requestanimationframe
    pub fn request_animation_frame< F: FnOnce(f64) + 'static>( &self, callback: F) -> RequestAnimationFrameHandle {
        let values: Value = js!{
            var callback = @{Once(callback)};
            var request = @{self}.requestAnimationFrame(callback);
            return { request: request, callback: callback, window: @{self} };
        };
        RequestAnimationFrameHandle(values)
    }

    /// Returns the global [History](struct.History.html) object, which provides methods to
    /// manipulate the browser history.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/history)
    // https://html.spec.whatwg.org/#the-window-object:dom-history
    pub fn history(&self) -> History {
        unsafe {
            js!(
                return @{self}.history;
            ).into_reference_unchecked().unwrap()
        }
    }

    /// Returns the width (in pixels) of the browser window viewport including, if rendered,
    /// the vertical scrollbar.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/window/innerWidth)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-innerwidth
    pub fn inner_width(&self) -> i32 {
        js!(
            return @{self}.innerWidth;
        ).try_into().unwrap()
    }

    /// Returns the height (in pixels) of the browser window viewport including, if rendered,
    /// the horizontal scrollbar.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/window/innerHeight)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-innerheight
    pub fn inner_height(&self) -> i32 {
        js!(
            return @{self}.innerHeight;
        ).try_into().unwrap()
    }

    /// Returns the width of the outside of the browser window. It represents the width
    /// of the whole browser window including sidebar (if expanded), window chrome
    /// and window resizing borders/handles.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerWidth)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-outerheight
    pub fn outer_width(&self) -> i32 {
        js!(
            return @{self}.outerWidth;
        ).try_into().unwrap()
    }

    /// Returns the height of the outside of the browser window. It represents the height
    /// of the whole browser window including sidebar (if expanded), window chrome
    /// and window resizing borders/handles.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerHeight)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-outerheight
    pub fn outer_height(&self) -> i32 {
        js!(
            return @{self}.outerHeight;
        ).try_into().unwrap()
    }

    /// The read-only Window property pageYOffset is an alias for scrollY; as such, it returns
    /// the number of pixels the document is currently scrolled along the vertical axis (that is,
    /// up or down), with a value of 0.0 indicating that the top edge of the Document is currently
    /// aligned with the top edge of the window's content area.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/pageYOffset)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-pageyoffset
    pub fn page_y_offset(&self) -> f64 {
        js!(
            return @{self}.pageYOffset;
        ).try_into().unwrap()
    }

    /// This is an alias for scrollX.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/pageXOffset)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-pagexoffset
    pub fn page_x_offset(&self) -> f64 {
        js!(
            return @{self}.pageXOffset;
        ).try_into().unwrap()
    }
}
<commit_msg>Add `Window::device_pixel_ratio` (#246)<commit_after>use webcore::value::Reference;
use webcore::try_from::TryInto;
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::window_or_worker::IWindowOrWorker;
use webapi::storage::Storage;
use webapi::location::Location;
use webapi::history::History;
use webcore::once::Once;
use webcore::value::Value;

/// A handle to a pending animation frame request.
#[derive(Debug)]
pub struct RequestAnimationFrameHandle(Value);

impl RequestAnimationFrameHandle {
    /// Cancels an animation frame request.
    ///
    /// [(Javascript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame)
    pub fn cancel( self ) {
        js! { @(no_return)
            var val = @{&self.0};
            val.window.cancelAnimationFrame(val.request);
            val.callback.drop();
        }
    }
}

/// The `Window` object represents a window containing a DOM document.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window)
// https://html.spec.whatwg.org/#window
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Window")]
#[reference(subclass_of(EventTarget))]
pub struct Window( Reference );

impl IEventTarget for Window {}
impl IWindowOrWorker for Window {}

/// A global instance of [Window](struct.Window.html).
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window)
pub fn window() -> Window {
    unsafe { js!( return window; ).into_reference_unchecked() }.unwrap()
}

impl Window {
    /// The Window.alert() method displays an alert dialog
    /// with the optional specified content and an OK button.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert)
    // https://html.spec.whatwg.org/#the-window-object:dom-alert
    pub fn alert( &self, message: &str ) {
        js!( @(no_return)
            @{self}.alert( @{message} );
        );
    }

    /// The `local_storage` property allows you to access a local [Storage](struct.Storage.html)
    /// object.
    ///
    /// It is similar to the [Window::session_storage](struct.Window.html#method.session_storage).
    /// The only difference is that, while data stored in `local_storage` has
    /// no expiration time, data stored in `session_storage` gets cleared when
    /// the browsing session ends - that is, when the browser is closed.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)
    // https://html.spec.whatwg.org/#the-localstorage-attribute:dom-localstorage
    pub fn local_storage( &self ) -> Storage {
        unsafe {
            js!(
                return @{self.as_ref()}.localStorage;
            ).into_reference_unchecked().unwrap()
        }
    }

    /// The `session_storage` property allows you to access a session [Storage](struct.Storage.html)
    /// object for the current origin.
    ///
    /// It is similar to the [Window::local_storage](struct.Window.html#method.local_storage),
    /// The only difference is that, while data stored in `local_storage` has
    /// no expiration time, data stored in `session_storage` gets cleared when
    /// the browsing session ends.
    ///
    /// A page session lasts for as long as the browser is open and survives over
    /// page reloads and restores. Opening a page in a new tab or window will cause
    /// a new session to be initiated, which differs from how session cookies work.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)
    // https://html.spec.whatwg.org/#the-sessionstorage-attribute:dom-sessionstorage
    pub fn session_storage( &self ) -> Storage {
        unsafe {
            js!(
                return @{self.as_ref()}.sessionStorage;
            ).into_reference_unchecked().unwrap()
        }
    }

    /// Returns a [Location](struct.Location.html) object which contains
    /// information about the URL of the document and provides methods
    /// for changing that URL and loading another URL.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/location)
    // https://html.spec.whatwg.org/#the-window-object:dom-location
    pub fn location( &self ) -> Option< Location > {
        unsafe {
            js!(
                return @{self}.location;
            ).into_reference_unchecked()
        }
    }

    /// You should call this method whenever you're ready to update your animation onscreen.
    /// This will request that your animation function be called before the browser performs the next repaint.
    /// The number of callbacks is usually 60 times per second, but will generally match the display refresh
    /// rate in most web browsers as per W3C recommendation. request_animation_frame() calls are paused in most browsers
    /// when running in background tabs or hidden iframes in order to improve performance and battery life.
    ///
    /// The callback method is passed a single argument, a f64, which indicates the current time when
    /// callbacks queued by requestAnimationFrame() begin to fire. Multiple callbacks in a single frame, therefore,
    /// each receive the same timestamp even though time has passed during the computation of every previous callback's workload.
    /// This timestamp is a decimal number, in milliseconds, but with a minimal precision of 1ms (1000 µs).
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
    // https://html.spec.whatwg.org/#the-window-object:dom-window-requestanimationframe
    pub fn request_animation_frame< F: FnOnce(f64) + 'static>( &self, callback: F) -> RequestAnimationFrameHandle {
        let values: Value = js!{
            var callback = @{Once(callback)};
            var request = @{self}.requestAnimationFrame(callback);
            return { request: request, callback: callback, window: @{self} };
        };
        RequestAnimationFrameHandle(values)
    }

    /// Returns the global [History](struct.History.html) object, which provides methods to
    /// manipulate the browser history.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/history)
    // https://html.spec.whatwg.org/#the-window-object:dom-history
    pub fn history(&self) -> History {
        unsafe {
            js!(
                return @{self}.history;
            ).into_reference_unchecked().unwrap()
        }
    }

    /// Returns the width (in pixels) of the browser window viewport including, if rendered,
    /// the vertical scrollbar.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/window/innerWidth)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-innerwidth
    pub fn inner_width(&self) -> i32 {
        js!(
            return @{self}.innerWidth;
        ).try_into().unwrap()
    }

    /// Returns the height (in pixels) of the browser window viewport including, if rendered,
    /// the horizontal scrollbar.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/window/innerHeight)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-innerheight
    pub fn inner_height(&self) -> i32 {
        js!(
            return @{self}.innerHeight;
        ).try_into().unwrap()
    }

    /// Returns the width of the outside of the browser window. It represents the width
    /// of the whole browser window including sidebar (if expanded), window chrome
    /// and window resizing borders/handles.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerWidth)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-outerheight
    pub fn outer_width(&self) -> i32 {
        js!(
            return @{self}.outerWidth;
        ).try_into().unwrap()
    }

    /// Returns the height of the outside of the browser window. It represents the height
    /// of the whole browser window including sidebar (if expanded), window chrome
    /// and window resizing borders/handles.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/outerHeight)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-outerheight
    pub fn outer_height(&self) -> i32 {
        js!(
            return @{self}.outerHeight;
        ).try_into().unwrap()
    }

    /// The read-only Window property pageYOffset is an alias for scrollY; as such, it returns
    /// the number of pixels the document is currently scrolled along the vertical axis (that is,
    /// up or down), with a value of 0.0 indicating that the top edge of the Document is currently
    /// aligned with the top edge of the window's content area.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/pageYOffset)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-pageyoffset
    pub fn page_y_offset(&self) -> f64 {
        js!(
            return @{self}.pageYOffset;
        ).try_into().unwrap()
    }

    /// This is an alias for scrollX.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/pageXOffset)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-pagexoffset
    pub fn page_x_offset(&self) -> f64 {
        js!(
            return @{self}.pageXOffset;
        ).try_into().unwrap()
    }

    /// The ratio in resolution from physical pixels to CSS pixels
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio)
    // https://drafts.csswg.org/cssom-view/#ref-for-dom-window-devicepixelratio
    pub fn device_pixel_ratio(&self) -> f64 {
        js! (
            return @{self}.devicePixelRatio;
        ).try_into().unwrap()
    }
}
<|endoftext|>


<commit_before>//! A graph-like structure used to represent a set of dependencies and in what
//! order they should be built.
//!
//! This structure is used to store the dependency graph and dynamically update
//! it to figure out when a dependency should be built.
//!
//! Dependencies in this queue are represented as a (node, edge) pair. This is
//! used to model nodes which produce multiple outputs at different times but
//! some nodes may only require one of the outputs and can start before the
//! whole node is finished.

use std::collections::{HashMap, HashSet};
use std::hash::Hash;

#[derive(Debug)]
pub struct DependencyQueue<N: Hash + Eq, E: Hash + Eq, V> {
    /// A list of all known keys to build.
    ///
    /// The value of the hash map is list of dependencies which still need to be
    /// built before the package can be built. Note that the set is dynamically
    /// updated as more dependencies are built.
    dep_map: HashMap<N, (HashSet<(N, E)>, V)>,

    /// A reverse mapping of a package to all packages that depend on that
    /// package.
    ///
    /// This map is statically known and does not get updated throughout the
    /// lifecycle of the DependencyQueue.
    ///
    /// This is sort of like a `HashMap<(N, E), HashSet<N>>` map, but more
    /// easily indexable with just an `N`
    reverse_dep_map: HashMap<N, HashMap<E, HashSet<N>>>,

    /// Topological depth of each key
    depth: HashMap<N, usize>,
}

impl<N: Hash + Eq, E: Hash + Eq, V> Default for DependencyQueue<N, E, V> {
    fn default() -> DependencyQueue<N, E, V> {
        DependencyQueue::new()
    }
}

impl<N: Hash + Eq, E: Hash + Eq, V> DependencyQueue<N, E, V> {
    /// Creates a new dependency queue with 0 packages.
    pub fn new() -> DependencyQueue<N, E, V> {
        DependencyQueue {
            dep_map: HashMap::new(),
            reverse_dep_map: HashMap::new(),
            depth: HashMap::new(),
        }
    }
}

impl<N: Hash + Eq + Clone, E: Eq + Hash + Clone, V> DependencyQueue<N, E, V> {
    /// Adds a new ndoe and its dependencies to this queue.
    ///
    /// The `key` specified is a new node in the dependency graph, and the node
    /// depend on all the dependencies iterated by `dependencies`. Each
    /// dependency is a node/edge pair, where edges can be thought of as
    /// productions from nodes (aka if it's just `()` it's just waiting for the
    /// node to finish).
    ///
    /// An optional `value` can also be associated with `key` which is reclaimed
    /// when the node is ready to go.
    pub fn queue(&mut self, key: N, value: V, dependencies: impl IntoIterator<Item = (N, E)>) {
        assert!(!self.dep_map.contains_key(&key));

        let mut my_dependencies = HashSet::new();
        for (dep, edge) in dependencies {
            my_dependencies.insert((dep.clone(), edge.clone()));
            self.reverse_dep_map
                .entry(dep)
                .or_insert_with(HashMap::new)
                .entry(edge)
                .or_insert_with(HashSet::new)
                .insert(key.clone());
        }
        self.dep_map.insert(key, (my_dependencies, value));
    }

    /// All nodes have been added, calculate some internal metadata and prepare
    /// for `dequeue`.
    pub fn queue_finished(&mut self) {
        for key in self.dep_map.keys() {
            depth(key, &self.reverse_dep_map, &mut self.depth);
        }

        fn depth<N: Hash + Eq + Clone, E: Hash + Eq + Clone>(
            key: &N,
            map: &HashMap<N, HashMap<E, HashSet<N>>>,
            results: &mut HashMap<N, usize>,
        ) -> usize {
            const IN_PROGRESS: usize = !0;

            if let Some(&depth) = results.get(key) {
                assert_ne!(depth, IN_PROGRESS, "cycle in DependencyQueue");
                return depth;
            }

            results.insert(key.clone(), IN_PROGRESS);

            let depth = 1 + map
                .get(key)
                .into_iter()
                .flat_map(|it| it.values())
                .flat_map(|set| set)
                .map(|dep| depth(dep, map, results))
                .max()
                .unwrap_or(0);

            *results.get_mut(key).unwrap() = depth;

            depth
        }
    }

    /// Dequeues a package that is ready to be built.
    ///
    /// A package is ready to be built when it has 0 un-built dependencies. If
    /// `None` is returned then no packages are ready to be built.
    pub fn dequeue(&mut self) -> Option<(N, V)> {
        // Look at all our crates and find everything that's ready to build (no
        // deps). After we've got that candidate set select the one which has
        // the maximum depth in the dependency graph. This way we should
        // hopefully keep CPUs hottest the longest by ensuring that long
        // dependency chains are scheduled early on in the build process and the
        // leafs higher in the tree can fill in the cracks later.
        //
        // TODO: it'd be best here to throw in a heuristic of crate size as
        //       well. For example how long did this crate historically take to
        //       compile? How large is its source code? etc.
        let next = self
            .dep_map
            .iter()
            .filter(|(_, (deps, _))| deps.is_empty())
            .map(|(key, _)| key.clone())
            .max_by_key(|k| self.depth[k]);
        let key = match next {
            Some(key) => key,
            None => return None,
        };
        let (_, data) = self.dep_map.remove(&key).unwrap();
        Some((key, data))
    }

    /// Returns `true` if there are remaining packages to be built.
    pub fn is_empty(&self) -> bool {
        self.dep_map.is_empty()
    }

    /// Returns the number of remaining packages to be built.
    pub fn len(&self) -> usize {
        self.dep_map.len()
    }

    /// Indicate that something has finished.
    ///
    /// Calling this function indicates that the `node` has produced `edge`. All
    /// remaining work items which only depend on this node/edge pair are now
    /// candidates to start their job.
    ///
    /// Returns the nodes that are now allowed to be dequeued as a result of
    /// finishing this node.
    pub fn finish(&mut self, node: &N, edge: &E) -> Vec<&N> {
        // hashset<Node>
        let reverse_deps = self.reverse_dep_map.get(node).and_then(|map| map.get(edge));
        let reverse_deps = match reverse_deps {
            Some(deps) => deps,
            None => return Vec::new(),
        };
        let key = (node.clone(), edge.clone());
        let mut result = Vec::new();
        for dep in reverse_deps.iter() {
            let edges = &mut self.dep_map.get_mut(dep).unwrap().0;
            assert!(edges.remove(&key));
            if edges.is_empty() {
                result.push(dep);
            }
        }
        result
    }
}

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

    #[test]
    fn deep_first() {
        let mut q = DependencyQueue::new();

        q.queue(1, (), vec![]);
        q.queue(2, (), vec![(1, ())]);
        q.queue(3, (), vec![]);
        q.queue(4, (), vec![(2, ()), (3, ())]);
        q.queue(5, (), vec![(4, ()), (3, ())]);
        q.queue_finished();

        assert_eq!(q.dequeue(), Some((1, ())));
        assert_eq!(q.dequeue(), Some((3, ())));
        assert_eq!(q.dequeue(), None);
        q.finish(&3, &());
        assert_eq!(q.dequeue(), None);
        q.finish(&1, &());
        assert_eq!(q.dequeue(), Some((2, ())));
        assert_eq!(q.dequeue(), None);
        q.finish(&2, &());
        assert_eq!(q.dequeue(), Some((4, ())));
        assert_eq!(q.dequeue(), None);
        q.finish(&4, &());
        assert_eq!(q.dequeue(), Some((5, ())));
    }
}
<commit_msg>change the priority in witch we build crates<commit_after>//! A graph-like structure used to represent a set of dependencies and in what
//! order they should be built.
//!
//! This structure is used to store the dependency graph and dynamically update
//! it to figure out when a dependency should be built.
//!
//! Dependencies in this queue are represented as a (node, edge) pair. This is
//! used to model nodes which produce multiple outputs at different times but
//! some nodes may only require one of the outputs and can start before the
//! whole node is finished.

use std::collections::{HashMap, HashSet};
use std::hash::Hash;

#[derive(Debug)]
pub struct DependencyQueue<N: Hash + Eq, E: Hash + Eq, V> {
    /// A list of all known keys to build.
    ///
    /// The value of the hash map is list of dependencies which still need to be
    /// built before the package can be built. Note that the set is dynamically
    /// updated as more dependencies are built.
    dep_map: HashMap<N, (HashSet<(N, E)>, V)>,

    /// A reverse mapping of a package to all packages that depend on that
    /// package.
    ///
    /// This map is statically known and does not get updated throughout the
    /// lifecycle of the DependencyQueue.
    ///
    /// This is sort of like a `HashMap<(N, E), HashSet<N>>` map, but more
    /// easily indexable with just an `N`
    reverse_dep_map: HashMap<N, HashMap<E, HashSet<N>>>,

    /// The total number of packages that are transitively waiting on this package
    priority: HashMap<N, usize>,
}

impl<N: Hash + Eq, E: Hash + Eq, V> Default for DependencyQueue<N, E, V> {
    fn default() -> DependencyQueue<N, E, V> {
        DependencyQueue::new()
    }
}

impl<N: Hash + Eq, E: Hash + Eq, V> DependencyQueue<N, E, V> {
    /// Creates a new dependency queue with 0 packages.
    pub fn new() -> DependencyQueue<N, E, V> {
        DependencyQueue {
            dep_map: HashMap::new(),
            reverse_dep_map: HashMap::new(),
            priority: HashMap::new(),
        }
    }
}

impl<N: Hash + Eq + Clone + std::fmt::Debug + PartialEq, E: Eq + Hash + Clone, V>
    DependencyQueue<N, E, V>
{
    /// Adds a new ndoe and its dependencies to this queue.
    ///
    /// The `key` specified is a new node in the dependency graph, and the node
    /// depend on all the dependencies iterated by `dependencies`. Each
    /// dependency is a node/edge pair, where edges can be thought of as
    /// productions from nodes (aka if it's just `()` it's just waiting for the
    /// node to finish).
    ///
    /// An optional `value` can also be associated with `key` which is reclaimed
    /// when the node is ready to go.
    pub fn queue(&mut self, key: N, value: V, dependencies: impl IntoIterator<Item = (N, E)>) {
        assert!(!self.dep_map.contains_key(&key));

        let mut my_dependencies = HashSet::new();
        for (dep, edge) in dependencies {
            my_dependencies.insert((dep.clone(), edge.clone()));
            self.reverse_dep_map
                .entry(dep)
                .or_insert_with(HashMap::new)
                .entry(edge)
                .or_insert_with(HashSet::new)
                .insert(key.clone());
        }
        self.dep_map.insert(key, (my_dependencies, value));
    }

    /// All nodes have been added, calculate some internal metadata and prepare
    /// for `dequeue`.
    pub fn queue_finished(&mut self) {
        let mut out = HashMap::new();
        for key in self.dep_map.keys() {
            depth(key, &self.reverse_dep_map, &mut out);
        }
        self.priority = out.into_iter().map(|(n, set)| (n, set.len())).collect();

        fn depth<N: Hash + Eq + Clone + std::fmt::Debug + PartialEq, E: Hash + Eq + Clone>(
            key: &N,
            map: &HashMap<N, HashMap<E, HashSet<N>>>,
            results: &mut HashMap<N, HashSet<N>>,
        ) -> HashSet<N> {
            let in_progress: HashSet<N> = HashSet::new();
            if let Some(depth) = results.get(key) {
                assert_ne!(depth, &in_progress, "cycle in DependencyQueue");
                return depth.clone();
            }
            results.insert(key.clone(), in_progress);

            let mut set = HashSet::new();
            set.insert(key.clone());

            for dep in map
                .get(key)
                .into_iter()
                .flat_map(|it| it.values())
                .flat_map(|set| set)
            {
                set.extend(depth(dep, map, results).into_iter())
            }

            *results.get_mut(key).unwrap() = set.clone();

            set
        }
    }

    /// Dequeues a package that is ready to be built.
    ///
    /// A package is ready to be built when it has 0 un-built dependencies. If
    /// `None` is returned then no packages are ready to be built.
    pub fn dequeue(&mut self) -> Option<(N, V)> {
        // Look at all our crates and find everything that's ready to build (no
        // deps). After we've got that candidate set select the one which has
        // the maximum priority in the dependency graph. This way we should
        // hopefully keep CPUs hottest the longest by ensuring that long
        // dependency chains are scheduled early on in the build process and the
        // leafs higher in the tree can fill in the cracks later.
        //
        // TODO: it'd be best here to throw in a heuristic of crate size as
        //       well. For example how long did this crate historically take to
        //       compile? How large is its source code? etc.
        let next = self
            .dep_map
            .iter()
            .filter(|(_, (deps, _))| deps.is_empty())
            .map(|(key, _)| key.clone())
            .max_by_key(|k| self.priority[k]);
        let key = match next {
            Some(key) => key,
            None => return None,
        };
        let (_, data) = self.dep_map.remove(&key).unwrap();
        Some((key, data))
    }

    /// Returns `true` if there are remaining packages to be built.
    pub fn is_empty(&self) -> bool {
        self.dep_map.is_empty()
    }

    /// Returns the number of remaining packages to be built.
    pub fn len(&self) -> usize {
        self.dep_map.len()
    }

    /// Indicate that something has finished.
    ///
    /// Calling this function indicates that the `node` has produced `edge`. All
    /// remaining work items which only depend on this node/edge pair are now
    /// candidates to start their job.
    ///
    /// Returns the nodes that are now allowed to be dequeued as a result of
    /// finishing this node.
    pub fn finish(&mut self, node: &N, edge: &E) -> Vec<&N> {
        // hashset<Node>
        let reverse_deps = self.reverse_dep_map.get(node).and_then(|map| map.get(edge));
        let reverse_deps = match reverse_deps {
            Some(deps) => deps,
            None => return Vec::new(),
        };
        let key = (node.clone(), edge.clone());
        let mut result = Vec::new();
        for dep in reverse_deps.iter() {
            let edges = &mut self.dep_map.get_mut(dep).unwrap().0;
            assert!(edges.remove(&key));
            if edges.is_empty() {
                result.push(dep);
            }
        }
        result
    }
}

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

    #[test]
    fn deep_first() {
        let mut q = DependencyQueue::new();

        q.queue(1, (), vec![]);
        q.queue(2, (), vec![(1, ())]);
        q.queue(3, (), vec![]);
        q.queue(4, (), vec![(2, ()), (3, ())]);
        q.queue(5, (), vec![(4, ()), (3, ())]);
        q.queue_finished();

        assert_eq!(q.dequeue(), Some((1, ())));
        assert_eq!(q.dequeue(), Some((3, ())));
        assert_eq!(q.dequeue(), None);
        q.finish(&3, &());
        assert_eq!(q.dequeue(), None);
        q.finish(&1, &());
        assert_eq!(q.dequeue(), Some((2, ())));
        assert_eq!(q.dequeue(), None);
        q.finish(&2, &());
        assert_eq!(q.dequeue(), Some((4, ())));
        assert_eq!(q.dequeue(), None);
        q.finish(&4, &());
        assert_eq!(q.dequeue(), Some((5, ())));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::i32;
use super::calculate_character_brightness::calculate_character_brightness;

#[derive(Debug)]
#[derive(PartialEq)]
/// A CharacterSet represents a set of characters mapped to brightness values
pub struct CharacterSet {
    brightness_table: HashMap<i32, char>,
}

impl CharacterSet {
    /// Generates a new CharacterSet containing `chars`
    pub fn new<T>(chars: T) -> CharacterSet where T: IntoIterator<Item=char> {
        let mut set = CharacterSet { brightness_table: HashMap::new() };
        let mut init_brightness = HashMap::new();
        let mut min = i32::MAX;
        let mut max = 0;
        for c in chars {
            let brightness = calculate_character_brightness(c);
            min = if brightness < min { brightness } else { min };
            max = if brightness > max { brightness } else { max };
            init_brightness.insert(brightness, c);
        }
        for (init_brightness, c) in init_brightness {
            let brightness = (255 * (init_brightness - min)) / (max - min);
            set.brightness_table.insert(brightness, c);
        }
        set
    }

    /// Generates a new character set from the string `string`
    pub fn from(string: &str) -> CharacterSet {
        let chars: Vec<char> = string.chars().collect();
        CharacterSet::new(chars)
    }

    /// Returns the character with brightness closest to `brightness`
    pub fn get(&self, brightness: i32) -> char {
        let mut upper = brightness;
        let mut lower = brightness;
        loop {
            match self.brightness_table.get(&upper) {
                Some(&c) => return c,
                None => upper += 1
            }
            match self.brightness_table.get(&lower) {
                Some(&c) => return c,
                None => lower -= 1
            }
        }
    }

    /// Returns a predefined CharacterSet with few characters
    pub fn preset_small() -> CharacterSet {
        CharacterSet::from("@%#x+=:-. ")
    }

    /// Returns a predefined CharacterSet with a moderate number of characters
    pub fn preset_medium() -> CharacterSet {
        CharacterSet::from("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
    }

    /// Returns a predefined CharacterSet with many characters
    pub fn preset_large() -> CharacterSet {
        CharacterSet::from("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-_=+[{]}\\|;:'\",.<>/?")
    }
}
<commit_msg>Improve CharacterSet docs and add CharacterSet::invert() function<commit_after>use std::collections::HashMap;
use std::i32;
use super::calculate_character_brightness::calculate_character_brightness;

#[derive(Debug)]
#[derive(PartialEq)]
/// A CharacterSet represents a set of characters mapped to brightness values
pub struct CharacterSet {
    brightness_table: HashMap<i32, char>,
}

impl CharacterSet {
    /// Generates a new CharacterSet containing `chars`
    ///
    /// # Example
    /// ```
    /// use txtpic_lib::character_set::CharacterSet;
    ///
    /// let char_set = CharacterSet::new("M ".chars());
    /// ```
    pub fn new<T>(chars: T) -> CharacterSet where T: IntoIterator<Item=char> {
        let mut set = CharacterSet { brightness_table: HashMap::new() };
        let mut init_brightness = HashMap::new();
        let mut min = i32::MAX;
        let mut max = 0;
        for c in chars {
            let brightness = calculate_character_brightness(c);
            min = if brightness < min { brightness } else { min };
            max = if brightness > max { brightness } else { max };
            init_brightness.insert(brightness, c);
        }
        for (init_brightness, c) in init_brightness {
            let brightness = (255 * (init_brightness - min)) / (max - min);
            set.brightness_table.insert(brightness, c);
        }
        set
    }

    /// Convenience method to generate a new CharacterSet from the string `string`
    ///
    /// # Example
    /// ```
    /// use txtpic_lib::character_set::CharacterSet;
    ///
    /// let char_set = CharacterSet::new("M ".chars());
    /// ```
    pub fn from(string: &str) -> CharacterSet {
        CharacterSet::new(string.chars())
    }

    /// Returns a new CharacterSet with the specified brightness map
    fn with_brightness_table(brightness_table: HashMap<i32, char>) -> CharacterSet {
        CharacterSet { brightness_table: brightness_table }
    }

    /// Returns the character with brightness closest to `brightness`
    ///
    /// # Example
    /// ```
    /// use txtpic_lib::character_set::CharacterSet;
    ///
    /// let char_set = CharacterSet::from("M ");
    /// let c = char_set.get(0);
    /// assert_eq!(c, ' ');
    /// ```
    pub fn get(&self, brightness: i32) -> char {
        let mut upper = brightness;
        let mut lower = brightness;
        loop {
            match self.brightness_table.get(&upper) {
                Some(&c) => return c,
                None => upper += 1
            }
            match self.brightness_table.get(&lower) {
                Some(&c) => return c,
                None => lower -= 1
            }
        }
    }

    /// Returns a new CharacterSet with inverted brightness values
    ///
    /// "Inverted" means that brightness values that were previously high are now low, and
    /// vice-versa. This is useful for generate text images that look good as black text on
    /// a white background
    ///
    /// # Example
    /// ```
    /// use txtpic_lib::character_set::CharacterSet;
    ///
    /// let char_set = CharacterSet::from("M ").invert();
    /// let c = char_set.get(0);
    /// assert_eq!(c, 'M');
    /// ```
    pub fn invert(&self) -> CharacterSet {
        let mut inverted_brightness_table = HashMap::new();
        for (brightness, &character) in &self.brightness_table {
            let inverted_brightness = (brightness - 255).abs();
            inverted_brightness_table.insert(inverted_brightness, character);
        }
        CharacterSet::with_brightness_table(inverted_brightness_table)
    }

    /// Returns a predefined CharacterSet with few characters
    pub fn preset_small() -> CharacterSet {
        CharacterSet::from("@%#x+=:-. ")
    }

    /// Returns a predefined CharacterSet with a moderate number of characters
    pub fn preset_medium() -> CharacterSet {
        CharacterSet::from("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
    }

    /// Returns a predefined CharacterSet with many characters
    pub fn preset_large() -> CharacterSet {
        CharacterSet::from("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-_=+[{]}\\|;:'\",.<>/?")
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::path::PathBuf;
use std::str::Split;

use clap::ArgMatches;
use toml::Value;

use libimagstore::store::EntryHeader;
use libimagrt::runtime::Runtime;
use libimagutil::key_value_split::IntoKeyValue;

pub fn build_entry_path(rt: &Runtime, path_elem: &str) -> PathBuf {
    debug!("Building path...");
    let mut path = rt.store().path().clone();

    if path_elem.chars().next() == Some('/') {
        path.push(&path_elem[1..path_elem.len()]);
    } else {
        path.push(path_elem);
    }

    path
}

pub fn build_toml_header(matches: &ArgMatches, mut header: EntryHeader) -> EntryHeader {
    debug!("Building header from cli spec");
    if let Some(headerspecs) = matches.values_of("header") {
        let mut main = header.toml_mut();
        debug!("headerspec = {:?}", headerspecs);
        let kvs = headerspecs.into_iter()
                            .filter_map(|hs| {
                                debug!("- Processing: '{}'", hs);
                                let kv = String::from(hs).into_kv();
                                debug!("-        got: '{:?}'", kv);
                                kv
                            });
        for tpl in kvs {
            let (key, value) = tpl.into();
            debug!("Splitting: {:?}", key);
            let mut split = key.split(".");
            let current = split.next();
            if current.is_some() {
                insert_key_into(String::from(current.unwrap()), &mut split, value, &mut main);
            }
        }
    }
    debug!("Header = {:?}", header);
    header
}

fn insert_key_into(current: String,
                   rest_path: &mut Split<&str>,
                   value: String,
                   map: &mut BTreeMap<String, Value>) {
    let next = rest_path.next();

    if next.is_none() {
        debug!("Inserting into {:?} = {:?}", current, value);
        map.insert(current, parse_value(value));
    } else {
        debug!("Inserting into {:?} ... = {:?}", current, value);
        if map.contains_key(&current) {
            match map.get_mut(&current).unwrap() {
                &mut Value::Table(ref mut t) => {
                    insert_key_into(String::from(next.unwrap()), rest_path, value, t);
                },
                _ => unreachable!(),
            }
        } else {
            let mut submap = BTreeMap::new();
            insert_key_into(String::from(next.unwrap()), rest_path, value, &mut submap);
            debug!("Inserting submap = {:?}", submap);
            map.insert(current, Value::Table(submap));
        }
    }
}

fn parse_value(value: String) -> Value {
    use std::str::FromStr;

    fn is_ary(v: &String) -> bool {
        v.chars().next() == Some('[') && v.chars().last() == Some(']') && v.len() >= 3
    }

    if value == "true" {
        debug!("Building Boolean out of: {:?}...", value);
        Value::Boolean(true)
    } else if value == "false" {
        debug!("Building Boolean out of: {:?}...", value);
        Value::Boolean(false)
    } else if is_ary(&value) {
        debug!("Building Array out of: {:?}...", value);
        let sub = &value[1..(value.len()-1)];
        Value::Array(sub.split(",").map(|v| parse_value(String::from(v))).collect())
    } else {
        FromStr::from_str(&value[..])
            .map(|i: i64| {
                debug!("Building Integer out of: {:?}...", value);
                Value::Integer(i)
            })
            .unwrap_or_else(|_| {
                FromStr::from_str(&value[..])
                    .map(|f: f64| {
                        debug!("Building Float out of: {:?}...", value);
                        Value::Float(f)
                    })
                    .unwrap_or_else(|_| {
                        debug!("Building String out of: {:?}...", value);
                        Value::String(value)
                    })
            })
    }
}

<commit_msg>util: Verify that path contains version, else panic!()<commit_after>use std::collections::BTreeMap;
use std::path::PathBuf;
use std::str::Split;

use clap::ArgMatches;
use semver::Version;
use toml::Value;

use libimagstore::store::EntryHeader;
use libimagrt::runtime::Runtime;
use libimagutil::key_value_split::IntoKeyValue;

pub fn build_entry_path(rt: &Runtime, path_elem: &str) -> PathBuf {
    debug!("Checking path element for version");
    {
        let contains_version = {
            path_elem.split("~")
                .last()
                .map(|version| Version::parse(version).is_ok())
                .unwrap_or(false)
        };

        if !contains_version {
            debug!("Version cannot be parsed inside {:?}", path_elem);
            warn!("Path does not contain version. Will panic now!");
            panic!("No version in path");
        }
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = rt.store().path().clone();

    if path_elem.chars().next() == Some('/') {
        path.push(&path_elem[1..path_elem.len()]);
    } else {
        path.push(path_elem);
    }

    path
}

pub fn build_toml_header(matches: &ArgMatches, mut header: EntryHeader) -> EntryHeader {
    debug!("Building header from cli spec");
    if let Some(headerspecs) = matches.values_of("header") {
        let mut main = header.toml_mut();
        debug!("headerspec = {:?}", headerspecs);
        let kvs = headerspecs.into_iter()
                            .filter_map(|hs| {
                                debug!("- Processing: '{}'", hs);
                                let kv = String::from(hs).into_kv();
                                debug!("-        got: '{:?}'", kv);
                                kv
                            });
        for tpl in kvs {
            let (key, value) = tpl.into();
            debug!("Splitting: {:?}", key);
            let mut split = key.split(".");
            let current = split.next();
            if current.is_some() {
                insert_key_into(String::from(current.unwrap()), &mut split, value, &mut main);
            }
        }
    }
    debug!("Header = {:?}", header);
    header
}

fn insert_key_into(current: String,
                   rest_path: &mut Split<&str>,
                   value: String,
                   map: &mut BTreeMap<String, Value>) {
    let next = rest_path.next();

    if next.is_none() {
        debug!("Inserting into {:?} = {:?}", current, value);
        map.insert(current, parse_value(value));
    } else {
        debug!("Inserting into {:?} ... = {:?}", current, value);
        if map.contains_key(&current) {
            match map.get_mut(&current).unwrap() {
                &mut Value::Table(ref mut t) => {
                    insert_key_into(String::from(next.unwrap()), rest_path, value, t);
                },
                _ => unreachable!(),
            }
        } else {
            let mut submap = BTreeMap::new();
            insert_key_into(String::from(next.unwrap()), rest_path, value, &mut submap);
            debug!("Inserting submap = {:?}", submap);
            map.insert(current, Value::Table(submap));
        }
    }
}

fn parse_value(value: String) -> Value {
    use std::str::FromStr;

    fn is_ary(v: &String) -> bool {
        v.chars().next() == Some('[') && v.chars().last() == Some(']') && v.len() >= 3
    }

    if value == "true" {
        debug!("Building Boolean out of: {:?}...", value);
        Value::Boolean(true)
    } else if value == "false" {
        debug!("Building Boolean out of: {:?}...", value);
        Value::Boolean(false)
    } else if is_ary(&value) {
        debug!("Building Array out of: {:?}...", value);
        let sub = &value[1..(value.len()-1)];
        Value::Array(sub.split(",").map(|v| parse_value(String::from(v))).collect())
    } else {
        FromStr::from_str(&value[..])
            .map(|i: i64| {
                debug!("Building Integer out of: {:?}...", value);
                Value::Integer(i)
            })
            .unwrap_or_else(|_| {
                FromStr::from_str(&value[..])
                    .map(|f: f64| {
                        debug!("Building Float out of: {:?}...", value);
                        Value::Float(f)
                    })
                    .unwrap_or_else(|_| {
                        debug!("Building String out of: {:?}...", value);
                        Value::String(value)
                    })
            })
    }
}

<|endoftext|>