<commit_before>use crate::printer::Printer;
use crate::vec::Vec2;
use crate::view::{SizeConstraint, View, ViewWrapper};
use crate::With;
use crate::XY;

/// Wrapper around another view, with a controlled size.
///
/// Each axis can independently be set to:
///
/// * Keep a **fixed** size
/// * Use **all** available size
/// * Use **at most** a given size
/// * Use **at least** a given size
/// * Let the wrapped view decide.
///
/// # Examples
///
/// ```
/// # use cursive::views::{BoxView,TextView};
/// // Creates a 20x4 BoxView with a TextView content.
/// let view = BoxView::with_fixed_size((20,4), TextView::new("Hello!"));
/// ```
pub struct BoxView<T: View> {
    /// Constraint on each axis
    size: XY<SizeConstraint>,

    /// `true` if the view can be squished.
    ///
    /// This means if the required size is less than the computed size,
    /// consider returning a smaller size.
    /// For instance, try to return the child's desired size.
    squishable: bool, // TODO: remove?

    /// Set to `true` whenever we change some settings. Means we should re-layout just in case.
    invalidated: bool,

    /// The actual view we're wrapping.
    view: T,
}

impl<T: View> BoxView<T> {
    /// Creates a new `BoxView` with the given width and height requirements.
    ///
    /// `None` values will use the wrapped view's preferences.
    pub fn new(
        width: SizeConstraint,
        height: SizeConstraint,
        view: T,
    ) -> Self {
        BoxView {
            size: (width, height).into(),
            squishable: false,
            invalidated: true,
            view,
        }
    }

    /// Sets the size constraints for this view.
    pub fn set_constraints(
        &mut self,
        width: SizeConstraint,
        height: SizeConstraint,
    ) {
        self.set_width(width);
        self.set_height(height);
    }

    /// Sets the width constraint for this view.
    ///
    /// Leaves the height unchanged.
    pub fn set_width(&mut self, width: SizeConstraint) {
        self.size.x = width;
        self.invalidate();
    }

    /// Sets the height constraint for this view.
    ///
    /// Leaves the width unchanged.
    pub fn set_height(&mut self, height: SizeConstraint) {
        self.size.y = height;
        self.invalidate();
    }

    /// Sets `self` to be squishable.
    ///
    /// A squishable `BoxView` will take a smaller size than it should when
    /// the available space is too small. In that case, it will allow the
    /// child view to contract, if it can.
    ///
    /// More specifically, if the available space is less than the size we
    /// would normally ask for, return the child size.
    pub fn squishable(self) -> Self {
        self.with(|s| s.set_squishable(true))
    }

    /// Controls the "squishability" of `self`.
    pub fn set_squishable(&mut self, squishable: bool) {
        self.squishable = squishable;
        self.invalidate();
    }

    /// Wraps `view` in a new `BoxView` with the given size.
    pub fn with_fixed_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(
            SizeConstraint::Fixed(size.x),
            SizeConstraint::Fixed(size.y),
            view,
        )
    }

    /// Wraps `view` in a new `BoxView` with fixed width.
    pub fn with_fixed_width(width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Fixed(width), SizeConstraint::Free, view)
    }

    /// Wraps `view` in a new `BoxView` with fixed height.
    pub fn with_fixed_height(height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Fixed(height), view)
    }

    /// Wraps `view` in a `BoxView` which will take all available space.
    pub fn with_full_screen(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available width.
    pub fn with_full_width(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Free, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available height.
    pub fn with_full_height(view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will never be bigger than `size`.
    pub fn with_max_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(
            SizeConstraint::AtMost(size.x),
            SizeConstraint::AtMost(size.y),
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum width.
    ///
    /// The resulting width will never be more than `max_width`.
    pub fn with_max_width(max_width: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::AtMost(max_width),
            SizeConstraint::Free,
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum height.
    ///
    /// The resulting height will never be more than `max_height`.
    pub fn with_max_height(max_height: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::Free,
            SizeConstraint::AtMost(max_height),
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will never be smaller than `size`.
    pub fn with_min_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(
            SizeConstraint::AtLeast(size.x),
            SizeConstraint::AtLeast(size.y),
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum width.
    ///
    /// The resulting width will never be less than `min_width`.
    pub fn with_min_width(min_width: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::AtLeast(min_width),
            SizeConstraint::Free,
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum height.
    ///
    /// The resulting height will never be less than `min_height`.
    pub fn with_min_height(min_height: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::Free,
            SizeConstraint::AtLeast(min_height),
            view,
        )
    }

    /// Should be called anytime something changes.
    fn invalidate(&mut self) {
        self.invalidated = true;
    }

    inner_getters!(self.view: T);
}

impl<T: View> ViewWrapper for BoxView<T> {
    wrap_impl!(self.view: T);

    fn wrap_draw(&self, printer: &Printer) {
        self.view.draw(&printer.inner_size(
            self.size.zip_map(printer.size, |c, s| c.result((s, s))),
        ));
    }

    fn wrap_required_size(&mut self, req: Vec2) -> Vec2 {
        // This is what the child will see as request.
        let req = self.size.zip_map(req, SizeConstraint::available);

        // This is the size the child would like to have.
        // Given the constraints of our box.
        let child_size = self.view.required_size(req);

        // Some of this request will be granted, but maybe not all.
        let result = self
            .size
            .zip_map(child_size.zip(req), SizeConstraint::result);

        if self.squishable {
            // When we're squishable, special behaviour:
            //

            // We respect the request if we're less or equal.
            let respect_req = result.zip_map(req, |res, req| res <= req);

            // If we respect the request, keep the result
            // Otherwise, take the child as squish attempt.
            respect_req.select_or(result, child_size)
        } else {
            result
        }
    }

    fn wrap_layout(&mut self, size: Vec2) {
        self.invalidated = false;
        self.view.layout(size);
    }

    fn wrap_needs_relayout(&self) -> bool {
        self.invalidated || self.view.needs_relayout()
    }
}

#[cfg(test)]
mod tests {

    use crate::vec::Vec2;
    use crate::view::{Boxable, View};
    use crate::views::DummyView;

    // No need to test `draw()` method as it's directly forwarded.

    #[test]
    fn min_size() {
        let mut min_w = DummyView.full_screen().min_width(5);

        assert_eq!(Vec2::new(5, 1), min_w.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(5, 10), min_w.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), min_w.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_w.required_size(Vec2::new(10, 10)));

        let mut min_h = DummyView.full_screen().min_height(5);

        assert_eq!(Vec2::new(1, 5), min_h.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), min_h.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 5), min_h.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_h.required_size(Vec2::new(10, 10)));

        let mut min_s = DummyView.full_screen().min_size((5, 5));

        assert_eq!(Vec2::new(5, 5), min_s.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(5, 10), min_s.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 5), min_s.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_s.required_size(Vec2::new(10, 10)));
    }

    #[test]
    fn max_size() {
        let mut max_w = DummyView.full_screen().max_width(5);

        assert_eq!(Vec2::new(1, 1), max_w.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), max_w.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(5, 1), max_w.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(5, 10), max_w.required_size(Vec2::new(10, 10)));

        let mut max_h = DummyView.full_screen().max_height(5);

        assert_eq!(Vec2::new(1, 1), max_h.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 5), max_h.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), max_h.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 5), max_h.required_size(Vec2::new(10, 10)));

        let mut max_s = DummyView.full_screen().max_size((5, 5));

        assert_eq!(Vec2::new(1, 1), max_s.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 5), max_s.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(5, 1), max_s.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(5, 5), max_s.required_size(Vec2::new(10, 10)));
    }

    #[test]
    fn full_screen() {
        let mut full = DummyView.full_screen();

        assert_eq!(Vec2::new(1, 1), full.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), full.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), full.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), full.required_size(Vec2::new(10, 10)));
    }

    #[test]
    fn test_get_inner() {
        use crate::views::TextView;

        let parent = TextView::new("abc").full_screen();
        let child = parent.get_inner();
        assert_eq!(child.get_content().source(), "abc");
    }
    #[test]
    fn test_get_inner_mut() {
        use crate::views::TextView;

        let mut parent = TextView::new("").full_screen();
        let new_value = "new";
        let child = parent.get_inner_mut();

        child.set_content(new_value);

        assert_eq!(child.get_content().source(), new_value);
    }
}
<commit_msg>Remove BoxView::squishable<commit_after>use crate::printer::Printer;
use crate::vec::Vec2;
use crate::view::{SizeConstraint, View, ViewWrapper};
use crate::With;
use crate::XY;

/// Wrapper around another view, with a controlled size.
///
/// Each axis can independently be set to:
///
/// * Keep a **fixed** size
/// * Use **all** available size
/// * Use **at most** a given size
/// * Use **at least** a given size
/// * Let the wrapped view decide.
///
/// # Examples
///
/// ```
/// # use cursive::views::{BoxView,TextView};
/// // Creates a 20x4 BoxView with a TextView content.
/// let view = BoxView::with_fixed_size((20,4), TextView::new("Hello!"));
/// ```
pub struct BoxView<T: View> {
    /// Constraint on each axis
    size: XY<SizeConstraint>,

    /// Set to `true` whenever we change some settings. Means we should re-layout just in case.
    invalidated: bool,

    /// The actual view we're wrapping.
    view: T,
}

impl<T: View> BoxView<T> {
    /// Creates a new `BoxView` with the given width and height requirements.
    ///
    /// `None` values will use the wrapped view's preferences.
    pub fn new(
        width: SizeConstraint,
        height: SizeConstraint,
        view: T,
    ) -> Self {
        BoxView {
            size: (width, height).into(),
            invalidated: true,
            view,
        }
    }

    /// Sets the size constraints for this view.
    pub fn set_constraints(
        &mut self,
        width: SizeConstraint,
        height: SizeConstraint,
    ) {
        self.set_width(width);
        self.set_height(height);
    }

    /// Sets the width constraint for this view.
    ///
    /// Leaves the height unchanged.
    pub fn set_width(&mut self, width: SizeConstraint) {
        self.size.x = width;
        self.invalidate();
    }

    /// Sets the height constraint for this view.
    ///
    /// Leaves the width unchanged.
    pub fn set_height(&mut self, height: SizeConstraint) {
        self.size.y = height;
        self.invalidate();
    }

    /// Wraps `view` in a new `BoxView` with the given size.
    pub fn with_fixed_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(
            SizeConstraint::Fixed(size.x),
            SizeConstraint::Fixed(size.y),
            view,
        )
    }

    /// Wraps `view` in a new `BoxView` with fixed width.
    pub fn with_fixed_width(width: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Fixed(width), SizeConstraint::Free, view)
    }

    /// Wraps `view` in a new `BoxView` with fixed height.
    pub fn with_fixed_height(height: usize, view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Fixed(height), view)
    }

    /// Wraps `view` in a `BoxView` which will take all available space.
    pub fn with_full_screen(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available width.
    pub fn with_full_width(view: T) -> Self {
        BoxView::new(SizeConstraint::Full, SizeConstraint::Free, view)
    }

    /// Wraps `view` in a `BoxView` which will take all available height.
    pub fn with_full_height(view: T) -> Self {
        BoxView::new(SizeConstraint::Free, SizeConstraint::Full, view)
    }

    /// Wraps `view` in a `BoxView` which will never be bigger than `size`.
    pub fn with_max_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(
            SizeConstraint::AtMost(size.x),
            SizeConstraint::AtMost(size.y),
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum width.
    ///
    /// The resulting width will never be more than `max_width`.
    pub fn with_max_width(max_width: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::AtMost(max_width),
            SizeConstraint::Free,
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a maximum height.
    ///
    /// The resulting height will never be more than `max_height`.
    pub fn with_max_height(max_height: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::Free,
            SizeConstraint::AtMost(max_height),
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will never be smaller than `size`.
    pub fn with_min_size<S: Into<Vec2>>(size: S, view: T) -> Self {
        let size = size.into();

        BoxView::new(
            SizeConstraint::AtLeast(size.x),
            SizeConstraint::AtLeast(size.y),
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum width.
    ///
    /// The resulting width will never be less than `min_width`.
    pub fn with_min_width(min_width: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::AtLeast(min_width),
            SizeConstraint::Free,
            view,
        )
    }

    /// Wraps `view` in a `BoxView` which will enforce a minimum height.
    ///
    /// The resulting height will never be less than `min_height`.
    pub fn with_min_height(min_height: usize, view: T) -> Self {
        BoxView::new(
            SizeConstraint::Free,
            SizeConstraint::AtLeast(min_height),
            view,
        )
    }

    /// Should be called anytime something changes.
    fn invalidate(&mut self) {
        self.invalidated = true;
    }

    inner_getters!(self.view: T);
}

impl<T: View> ViewWrapper for BoxView<T> {
    wrap_impl!(self.view: T);

    fn wrap_draw(&self, printer: &Printer) {
        self.view.draw(&printer.inner_size(
            self.size.zip_map(printer.size, |c, s| c.result((s, s))),
        ));
    }

    fn wrap_required_size(&mut self, req: Vec2) -> Vec2 {
        // This is what the child will see as request.
        let req = self.size.zip_map(req, SizeConstraint::available);

        // This is the size the child would like to have.
        // Given the constraints of our box.
        let child_size = self.view.required_size(req);

        // Some of this request will be granted, but maybe not all.
        self.size
            .zip_map(child_size.zip(req), SizeConstraint::result)
    }

    fn wrap_layout(&mut self, size: Vec2) {
        self.invalidated = false;
        self.view
            .layout(self.size.zip_map(size, |c, s| c.result((s, s))));
    }

    fn wrap_needs_relayout(&self) -> bool {
        self.invalidated || self.view.needs_relayout()
    }
}

#[cfg(test)]
mod tests {

    use crate::vec::Vec2;
    use crate::view::{Boxable, View};
    use crate::views::DummyView;

    // No need to test `draw()` method as it's directly forwarded.

    #[test]
    fn min_size() {
        let mut min_w = DummyView.full_screen().min_width(5);

        assert_eq!(Vec2::new(5, 1), min_w.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(5, 10), min_w.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), min_w.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_w.required_size(Vec2::new(10, 10)));

        let mut min_h = DummyView.full_screen().min_height(5);

        assert_eq!(Vec2::new(1, 5), min_h.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), min_h.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 5), min_h.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_h.required_size(Vec2::new(10, 10)));

        let mut min_s = DummyView.full_screen().min_size((5, 5));

        assert_eq!(Vec2::new(5, 5), min_s.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(5, 10), min_s.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 5), min_s.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), min_s.required_size(Vec2::new(10, 10)));
    }

    #[test]
    fn max_size() {
        let mut max_w = DummyView.full_screen().max_width(5);

        assert_eq!(Vec2::new(1, 1), max_w.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), max_w.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(5, 1), max_w.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(5, 10), max_w.required_size(Vec2::new(10, 10)));

        let mut max_h = DummyView.full_screen().max_height(5);

        assert_eq!(Vec2::new(1, 1), max_h.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 5), max_h.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), max_h.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 5), max_h.required_size(Vec2::new(10, 10)));

        let mut max_s = DummyView.full_screen().max_size((5, 5));

        assert_eq!(Vec2::new(1, 1), max_s.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 5), max_s.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(5, 1), max_s.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(5, 5), max_s.required_size(Vec2::new(10, 10)));
    }

    #[test]
    fn full_screen() {
        let mut full = DummyView.full_screen();

        assert_eq!(Vec2::new(1, 1), full.required_size(Vec2::new(1, 1)));
        assert_eq!(Vec2::new(1, 10), full.required_size(Vec2::new(1, 10)));
        assert_eq!(Vec2::new(10, 1), full.required_size(Vec2::new(10, 1)));
        assert_eq!(Vec2::new(10, 10), full.required_size(Vec2::new(10, 10)));
    }

    #[test]
    fn test_get_inner() {
        use crate::views::TextView;

        let parent = TextView::new("abc").full_screen();
        let child = parent.get_inner();
        assert_eq!(child.get_content().source(), "abc");
    }
    #[test]
    fn test_get_inner_mut() {
        use crate::views::TextView;

        let mut parent = TextView::new("").full_screen();
        let new_value = "new";
        let child = parent.get_inner_mut();

        child.set_content(new_value);

        assert_eq!(child.get_content().source(), new_value);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::{BitSet, HashSet, VecMap};
use std::collections::vec_map::Entry;

use constants::{BLOCK_SIZE, LINE_SIZE, NUM_LINES_PER_BLOCK};
use gc_object::GCObjectRef;

/// A per block object map.
struct ObjectMap {
    set: BitSet,
}

impl ObjectMap {
    /// Create a new `ObjectMap`.
    fn new() -> ObjectMap {
        return ObjectMap {
            set: BitSet::with_capacity(BLOCK_SIZE),
        };
    }

    /// Reduce the objects address to an offset within the block.
    fn index(object: GCObjectRef) -> usize {
        return (object as usize) % BLOCK_SIZE;
    }

    /// Set the address as a valid object.
    fn set_object(&mut self, object: GCObjectRef) {
        self.set.insert(ObjectMap::index(object));
    }

    /// Unset the address as a valid object.
    fn unset_object(&mut self, object: GCObjectRef) {
        self.set.remove(&ObjectMap::index(object));
    }

    /// Return `true` is the address is a valid object.
    fn is_object(&self, object: GCObjectRef) -> bool {
        return self.set.contains(&ObjectMap::index(object));
    }

    /// Update this `ObjectMap` with the difference of this `ObjectMap` and
    /// the other.
    fn difference(&mut self, other: &ObjectMap) {
        self.set.difference_with(&other.set);
    }

    /// Clear all entries.
    fn clear(&mut self) {
        self.set.clear();
    }

    /// Retrieve the values as a `HashSet`.
    fn as_hashset(&self, base: *mut u8) -> HashSet<GCObjectRef> {
        return self.set.iter()
                       .map(|i| unsafe{ base.offset(i as isize) as GCObjectRef})
                       .collect();
    }
}

/// A `BlockInfo` contains management information for the immix garbage
/// collectors.
///
/// It is the first bytes in a chunk of memory of size `BLOCK_SIZE` and must
/// not exeed `LINE_SIZE` bytes in size.
pub struct BlockInfo {
    /// A counter of live objects for every line in this block.
    line_counter: VecMap<usize>,

    /// A set of addresses that are valid objects. Needed for the conservative
    /// part.
    object_map: ObjectMap,

    /// Objects in this block that were never touched by the garbage
    /// collector.
    new_objects: ObjectMap,

    /// If this block is actually in use.
    allocated: bool,

    /// How many holen are in this block.
    hole_count: usize,

    /// If this block is a candidate for opportunistic evacuation.
    evacuation_candidate: bool,
}

impl BlockInfo {
    /// Create a new `BlockInfo`.
    pub fn new() -> BlockInfo {
        let mut line_counter = VecMap::with_capacity(NUM_LINES_PER_BLOCK);
        for index in (0..NUM_LINES_PER_BLOCK) {
            line_counter.insert(index, 0);
        }
        return BlockInfo {
            line_counter: line_counter,
            object_map: ObjectMap::new(),
            new_objects: ObjectMap::new(),
            allocated: false,
            hole_count: 0,
            evacuation_candidate: false,
        };
    }

    /// Set this block as allocated (actually in use).
    pub fn set_allocated(&mut self) {
        self.allocated = true;
    }

    /// Set an address in this block as a valid object.
    pub fn set_gc_object(&mut self, object: GCObjectRef) {
        debug_assert!(self.is_in_block(object),
            "set_gc_object() on invalid block: {:p} (allocated={})",
            self, self.allocated);
        self.object_map.set_object(object);
    }

    /// Unset an address in this block as a valid object.
    pub fn unset_gc_object(&mut self, object: GCObjectRef) {
        debug_assert!(self.is_in_block(object),
            "unset_gc_object() on invalid block: {:p} (allocated={})",
            self, self.allocated);
        self.object_map.unset_object(object);
    }

    /// Return if an address in this block is a valid object.
    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        if self.is_in_block(object) {
            return self.object_map.is_object(object);
        }
        return false;
    }

    /// Get a copy of the object map.
    pub fn get_object_map(&mut self) -> HashSet<GCObjectRef> {
        return self.object_map.as_hashset(self as *mut BlockInfo as *mut u8);
    }

    /// Clear the object map.
    pub fn clear_object_map(&mut self) {
        self.object_map.clear();
    }

    /// Set an object in this block as new (not the `GCHeader.new` bit).
    pub fn set_new_object(&mut self, object: GCObjectRef) {
        debug_assert!(self.is_in_block(object),
            "set_new_object() on invalid block: {:p} (allocated={})",
            self, self.allocated);
        self.new_objects.set_object(object);
    }

    /// Get the new objects in this block.
    pub fn get_new_objects(&mut self) -> HashSet<GCObjectRef> {
        return self.new_objects.as_hashset(self as *mut BlockInfo as *mut u8);
    }

    /// Remove all the new objects from the object map and clear the new
    /// objects set.
    pub fn remove_new_objects_from_map(&mut self) {
        self.object_map.difference(&self.new_objects);
        self.new_objects.clear();
    }

    /// Set as an evacuation candidate if this block has at least `hole_count`
    /// holes.
    pub fn set_evacuation_candidate(&mut self, hole_count: usize) {
        debug!("Set block {:p} to evacuation_candidate={} ({} holes)",
               &self, self.hole_count >= hole_count, self.hole_count);
        self.evacuation_candidate = self.hole_count >= hole_count;
    }

    /// Return if this is an evacuation candidate.
    pub fn is_evacuation_candidate(&self) -> bool{
        return self.evacuation_candidate;
    }

    /// Increment the lines on which the object is allocated.
    pub fn increment_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, true);
    }

    /// Decrement the lines on which the object is allocated.
    pub fn decrement_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, false);
    }

    /// Return the number of holes and marked lines in this block.
    ///
    /// A marked line is a line with a count of at least one.
    ///
    /// _Note_: You must call count_holes() bevorhand to set the number of
    /// holes.
    pub fn count_holes_and_marked_lines(&self) -> (usize, usize) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e != 0).count());
    }

    /// Return the number of holes and available lines in this block.
    ///
    /// An available line is a line with a count of zero.
    ///
    /// _Note_: You must call count_holes() bevorhand to set the number of
    /// holes.
    pub fn count_holes_and_available_lines(&self) -> (usize, usize) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e == 0).count());
    }

    /// Clear the line counter map.
    pub fn clear_line_counts(&mut self) {
        for index in (0..NUM_LINES_PER_BLOCK) {
            self.line_counter.insert(index, 0);
        }
    }

    /// Reset all member field for this block.
    pub fn reset(&mut self) {
        self.clear_line_counts();
        self.clear_object_map();
        self.allocated = false;
        self.hole_count = 0;
        self.evacuation_candidate = false;
    }

    /// Return true if no line is marked (every line has a count of zero).
    pub fn is_empty(&self) -> bool {
        return self.line_counter.values().all(|v| *v == 0);
    }

    /// Get a pointer to an address `offset` bytes into this block.
    pub fn offset(&mut self, offset: usize) -> GCObjectRef {
        let self_ptr = self as *mut BlockInfo;
        let object = unsafe { (self_ptr as *mut u8).offset(offset as isize) };
        return object as GCObjectRef;
    }

    /// Scan the block for a hole to allocate into.
    ///
    /// The scan will start at `last_high_offset` bytes into the block and
    /// return a tuple of `low_offset`, `high_offset` as the lowest and
    /// highest usable offsets for a hole.
    ///
    /// `None` is returned if no hole was found.
    pub fn scan_block(&self, last_high_offset: u16) -> Option<(u16, u16)> {
        let last_high_index = last_high_offset as usize / LINE_SIZE;
        debug!("Scanning block {:p} for a hole with last_high_offset {}",
               self, last_high_index);
        let mut low_index = NUM_LINES_PER_BLOCK - 1;
        for index in ((last_high_index + 1)..NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(true, |c| *c == 0) {
                // +1 to skip the next line in case an object straddles lines
                low_index = index + 1;
                break;
            }
        }
        let mut high_index = NUM_LINES_PER_BLOCK;
        for index in (low_index..NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(false, |c| *c != 0) {
                high_index = index;
                break;
            }
        }
        if low_index == high_index && high_index != (NUM_LINES_PER_BLOCK - 1) {
            debug!("Rescan: Found single line hole? in block {:p}", self);
            return self.scan_block((high_index * LINE_SIZE - 1) as u16);
        } else if low_index < (NUM_LINES_PER_BLOCK - 1) {
            debug!("Found low index {} and high index {} in block {:p}",
                   low_index, high_index, self);
            return Some(((low_index * LINE_SIZE) as u16,
                         (high_index * LINE_SIZE - 1) as u16));
        }
        debug!("Found no hole in block {:p}", self);
        return None;
    }

    /// Count the holes in this block.
    ///
    /// Holes are lines with no objects allocated.
    pub fn count_holes(&mut self) {
        let holes = self.line_counter.values()
            .fold((0, false), |(holes, in_hole), &elem|
                  match (in_hole, elem) {
                    (false, 0) => (holes + 1, true),
                    (_, _) => (holes, false),
                  }).0;
        self.hole_count = holes;
    }
}

impl BlockInfo{
    /// Returns true if this block is allocated and the address is within the
    /// bounds of this block.
    fn is_in_block(&self, object: GCObjectRef) -> bool {
        // This works because we get zeroed memory from the OS, so
        // self.allocated will be false if this block is not initialized and
        // this method gets only called for objects within the ImmixSpace.
        // After the first initialization the field is properly managed.
        if self.allocated {
            let self_ptr = self as *const BlockInfo as *const u8;
            let self_bound = unsafe{ self_ptr.offset(BLOCK_SIZE as isize)};
            return self_ptr < (object as *const u8)
                && (object as *const u8) <  self_bound;
        }
        return false;
    }

    /// Convert an address on this block into a line number.
    fn object_to_line_num(object: GCObjectRef) -> usize {
        return (object as usize % BLOCK_SIZE) / LINE_SIZE;
    }

    /// Update the line counter for the given object.
    ///
    /// Increment if `increment`, otherwise do a saturating substraction.
    fn update_line_nums(&mut self, object: GCObjectRef, increment: bool) {
        // This calculates how many lines are affected starting from a
        // LINE_SIZE aligned address. So it might not mark enough lines. But
        // that does not matter as we always skip a line in scan_block()
        let line_num = BlockInfo::object_to_line_num(object);
        let object_size = unsafe{ (*object).object_size() };
        for line in line_num..(line_num + (object_size / LINE_SIZE) + 1) {
            match self.line_counter.entry(line) {
                Entry::Vacant(view) => { view.insert(if increment { 1 } else { 0 }); },
                Entry::Occupied(mut view) => {
                    let val = view.get_mut();
                    if increment {
                        *val += 1;
                    } else {
                        *val = (*val).saturating_sub(1);
                    }
                }
            };
            if increment {
                debug!("Incremented line count for line {} to {}", line,
                       self.line_counter.get(&line).unwrap());
            } else {
                debug!("Decremented line count for line {} to {}", line,
                       self.line_counter.get(&line).unwrap());
            }
        }
    }
}
<commit_msg>Fix borrow-checker problem in BlockInfo<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::{BitSet, HashSet, VecMap};
use std::collections::vec_map::Entry;

use constants::{BLOCK_SIZE, LINE_SIZE, NUM_LINES_PER_BLOCK};
use gc_object::GCObjectRef;

/// A per block object map.
struct ObjectMap {
    set: BitSet,
}

impl ObjectMap {
    /// Create a new `ObjectMap`.
    fn new() -> ObjectMap {
        return ObjectMap {
            set: BitSet::with_capacity(BLOCK_SIZE),
        };
    }

    /// Reduce the objects address to an offset within the block.
    fn index(object: GCObjectRef) -> usize {
        return (object as usize) % BLOCK_SIZE;
    }

    /// Set the address as a valid object.
    fn set_object(&mut self, object: GCObjectRef) {
        self.set.insert(ObjectMap::index(object));
    }

    /// Unset the address as a valid object.
    fn unset_object(&mut self, object: GCObjectRef) {
        self.set.remove(&ObjectMap::index(object));
    }

    /// Return `true` is the address is a valid object.
    fn is_object(&self, object: GCObjectRef) -> bool {
        return self.set.contains(&ObjectMap::index(object));
    }

    /// Update this `ObjectMap` with the difference of this `ObjectMap` and
    /// the other.
    fn difference(&mut self, other: &ObjectMap) {
        self.set.difference_with(&other.set);
    }

    /// Clear all entries.
    fn clear(&mut self) {
        self.set.clear();
    }

    /// Retrieve the values as a `HashSet`.
    fn as_hashset(&self, base: *mut u8) -> HashSet<GCObjectRef> {
        return self.set.iter()
                       .map(|i| unsafe{ base.offset(i as isize) as GCObjectRef})
                       .collect();
    }
}

/// A `BlockInfo` contains management information for the immix garbage
/// collectors.
///
/// It is the first bytes in a chunk of memory of size `BLOCK_SIZE` and must
/// not exeed `LINE_SIZE` bytes in size.
pub struct BlockInfo {
    /// A counter of live objects for every line in this block.
    line_counter: VecMap<usize>,

    /// A set of addresses that are valid objects. Needed for the conservative
    /// part.
    object_map: ObjectMap,

    /// Objects in this block that were never touched by the garbage
    /// collector.
    new_objects: ObjectMap,

    /// If this block is actually in use.
    allocated: bool,

    /// How many holen are in this block.
    hole_count: usize,

    /// If this block is a candidate for opportunistic evacuation.
    evacuation_candidate: bool,
}

impl BlockInfo {
    /// Create a new `BlockInfo`.
    pub fn new() -> BlockInfo {
        let mut line_counter = VecMap::with_capacity(NUM_LINES_PER_BLOCK);
        for index in (0..NUM_LINES_PER_BLOCK) {
            line_counter.insert(index, 0);
        }
        return BlockInfo {
            line_counter: line_counter,
            object_map: ObjectMap::new(),
            new_objects: ObjectMap::new(),
            allocated: false,
            hole_count: 0,
            evacuation_candidate: false,
        };
    }

    /// Set this block as allocated (actually in use).
    pub fn set_allocated(&mut self) {
        self.allocated = true;
    }

    /// Set an address in this block as a valid object.
    pub fn set_gc_object(&mut self, object: GCObjectRef) {
        debug_assert!(self.is_in_block(object),
            "set_gc_object() on invalid block: {:p} (allocated={})",
            self, self.allocated);
        self.object_map.set_object(object);
    }

    /// Unset an address in this block as a valid object.
    pub fn unset_gc_object(&mut self, object: GCObjectRef) {
        debug_assert!(self.is_in_block(object),
            "unset_gc_object() on invalid block: {:p} (allocated={})",
            self, self.allocated);
        self.object_map.unset_object(object);
    }

    /// Return if an address in this block is a valid object.
    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        if self.is_in_block(object) {
            return self.object_map.is_object(object);
        }
        return false;
    }

    /// Get a copy of the object map.
    pub fn get_object_map(&mut self) -> HashSet<GCObjectRef> {
        let self_ptr = self as *mut BlockInfo;
        return self.object_map.as_hashset(self_ptr as *mut u8);
    }

    /// Clear the object map.
    pub fn clear_object_map(&mut self) {
        self.object_map.clear();
    }

    /// Set an object in this block as new (not the `GCHeader.new` bit).
    pub fn set_new_object(&mut self, object: GCObjectRef) {
        debug_assert!(self.is_in_block(object),
            "set_new_object() on invalid block: {:p} (allocated={})",
            self, self.allocated);
        self.new_objects.set_object(object);
    }

    /// Get the new objects in this block.
    pub fn get_new_objects(&mut self) -> HashSet<GCObjectRef> {
        let self_ptr = self as *mut BlockInfo;
        return self.new_objects.as_hashset(self_ptr as *mut u8);
    }

    /// Remove all the new objects from the object map and clear the new
    /// objects set.
    pub fn remove_new_objects_from_map(&mut self) {
        self.object_map.difference(&self.new_objects);
        self.new_objects.clear();
    }

    /// Set as an evacuation candidate if this block has at least `hole_count`
    /// holes.
    pub fn set_evacuation_candidate(&mut self, hole_count: usize) {
        debug!("Set block {:p} to evacuation_candidate={} ({} holes)",
               &self, self.hole_count >= hole_count, self.hole_count);
        self.evacuation_candidate = self.hole_count >= hole_count;
    }

    /// Return if this is an evacuation candidate.
    pub fn is_evacuation_candidate(&self) -> bool{
        return self.evacuation_candidate;
    }

    /// Increment the lines on which the object is allocated.
    pub fn increment_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, true);
    }

    /// Decrement the lines on which the object is allocated.
    pub fn decrement_lines(&mut self, object: GCObjectRef) {
        self.update_line_nums(object, false);
    }

    /// Return the number of holes and marked lines in this block.
    ///
    /// A marked line is a line with a count of at least one.
    ///
    /// _Note_: You must call count_holes() bevorhand to set the number of
    /// holes.
    pub fn count_holes_and_marked_lines(&self) -> (usize, usize) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e != 0).count());
    }

    /// Return the number of holes and available lines in this block.
    ///
    /// An available line is a line with a count of zero.
    ///
    /// _Note_: You must call count_holes() bevorhand to set the number of
    /// holes.
    pub fn count_holes_and_available_lines(&self) -> (usize, usize) {
        return (self.hole_count,
                self.line_counter.values().filter(|&e| *e == 0).count());
    }

    /// Clear the line counter map.
    pub fn clear_line_counts(&mut self) {
        for index in (0..NUM_LINES_PER_BLOCK) {
            self.line_counter.insert(index, 0);
        }
    }

    /// Reset all member field for this block.
    pub fn reset(&mut self) {
        self.clear_line_counts();
        self.clear_object_map();
        self.allocated = false;
        self.hole_count = 0;
        self.evacuation_candidate = false;
    }

    /// Return true if no line is marked (every line has a count of zero).
    pub fn is_empty(&self) -> bool {
        return self.line_counter.values().all(|v| *v == 0);
    }

    /// Get a pointer to an address `offset` bytes into this block.
    pub fn offset(&mut self, offset: usize) -> GCObjectRef {
        let self_ptr = self as *mut BlockInfo;
        let object = unsafe { (self_ptr as *mut u8).offset(offset as isize) };
        return object as GCObjectRef;
    }

    /// Scan the block for a hole to allocate into.
    ///
    /// The scan will start at `last_high_offset` bytes into the block and
    /// return a tuple of `low_offset`, `high_offset` as the lowest and
    /// highest usable offsets for a hole.
    ///
    /// `None` is returned if no hole was found.
    pub fn scan_block(&self, last_high_offset: u16) -> Option<(u16, u16)> {
        let last_high_index = last_high_offset as usize / LINE_SIZE;
        debug!("Scanning block {:p} for a hole with last_high_offset {}",
               self, last_high_index);
        let mut low_index = NUM_LINES_PER_BLOCK - 1;
        for index in ((last_high_index + 1)..NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(true, |c| *c == 0) {
                // +1 to skip the next line in case an object straddles lines
                low_index = index + 1;
                break;
            }
        }
        let mut high_index = NUM_LINES_PER_BLOCK;
        for index in (low_index..NUM_LINES_PER_BLOCK) {
            if self.line_counter.get(&index).map_or(false, |c| *c != 0) {
                high_index = index;
                break;
            }
        }
        if low_index == high_index && high_index != (NUM_LINES_PER_BLOCK - 1) {
            debug!("Rescan: Found single line hole? in block {:p}", self);
            return self.scan_block((high_index * LINE_SIZE - 1) as u16);
        } else if low_index < (NUM_LINES_PER_BLOCK - 1) {
            debug!("Found low index {} and high index {} in block {:p}",
                   low_index, high_index, self);
            return Some(((low_index * LINE_SIZE) as u16,
                         (high_index * LINE_SIZE - 1) as u16));
        }
        debug!("Found no hole in block {:p}", self);
        return None;
    }

    /// Count the holes in this block.
    ///
    /// Holes are lines with no objects allocated.
    pub fn count_holes(&mut self) {
        let holes = self.line_counter.values()
            .fold((0, false), |(holes, in_hole), &elem|
                  match (in_hole, elem) {
                    (false, 0) => (holes + 1, true),
                    (_, _) => (holes, false),
                  }).0;
        self.hole_count = holes;
    }
}

impl BlockInfo{
    /// Returns true if this block is allocated and the address is within the
    /// bounds of this block.
    fn is_in_block(&self, object: GCObjectRef) -> bool {
        // This works because we get zeroed memory from the OS, so
        // self.allocated will be false if this block is not initialized and
        // this method gets only called for objects within the ImmixSpace.
        // After the first initialization the field is properly managed.
        if self.allocated {
            let self_ptr = self as *const BlockInfo as *const u8;
            let self_bound = unsafe{ self_ptr.offset(BLOCK_SIZE as isize)};
            return self_ptr < (object as *const u8)
                && (object as *const u8) <  self_bound;
        }
        return false;
    }

    /// Convert an address on this block into a line number.
    fn object_to_line_num(object: GCObjectRef) -> usize {
        return (object as usize % BLOCK_SIZE) / LINE_SIZE;
    }

    /// Update the line counter for the given object.
    ///
    /// Increment if `increment`, otherwise do a saturating substraction.
    fn update_line_nums(&mut self, object: GCObjectRef, increment: bool) {
        // This calculates how many lines are affected starting from a
        // LINE_SIZE aligned address. So it might not mark enough lines. But
        // that does not matter as we always skip a line in scan_block()
        let line_num = BlockInfo::object_to_line_num(object);
        let object_size = unsafe{ (*object).object_size() };
        for line in line_num..(line_num + (object_size / LINE_SIZE) + 1) {
            match self.line_counter.entry(line) {
                Entry::Vacant(view) => { view.insert(if increment { 1 } else { 0 }); },
                Entry::Occupied(mut view) => {
                    let val = view.get_mut();
                    if increment {
                        *val += 1;
                    } else {
                        *val = (*val).saturating_sub(1);
                    }
                }
            };
            if increment {
                debug!("Incremented line count for line {} to {}", line,
                       self.line_counter.get(&line).unwrap());
            } else {
                debug!("Decremented line count for line {} to {}", line,
                       self.line_counter.get(&line).unwrap());
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::prelude::*;
use winapi::shared::guiddef;

#[cfg(feature = "guid")]
impl Uuid {
    /// Converts a little endian winapi `GUID` into a [`Uuid`]
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn from_guid(guid: guiddef::GUID) -> Self {
        Uuid::from_fields_le(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        ).unwrap() // Note: The result in this particular instance is always Ok, so we can
                   //       safely unwrap.
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.to_fields_le();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(feature = "guid")]
#[cfg(test)]
mod tests {
    use super::*;

    use crate::std::string::ToString;
    use winapi::shared::guiddef;

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid).unwrap();
        assert_eq!(
            "9d22354a-2755-304f-8647-9dc54e1ee1e8",
            uuid.to_hyphenated().to_string()
        );
    }

    #[test]
    fn test_guid_roundtrip() {
        let guid_in = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid_in).unwrap();
        let guid_out = uuid.to_guid();

        assert_eq!(
            (guid_in.Data1, guid_in.Data2, guid_in.Data3, guid_in.Data4),
            (
                guid_out.Data1,
                guid_out.Data2,
                guid_out.Data3,
                guid_out.Data4
            )
        );
    }
}
<commit_msg>fix fmt<commit_after>use crate::prelude::*;
use winapi::shared::guiddef;

#[cfg(feature = "guid")]
impl Uuid {
    /// Converts a little endian winapi `GUID` into a [`Uuid`]
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn from_guid(guid: guiddef::GUID) -> Self {
        Uuid::from_fields_le(
            guid.Data1 as u32,
            guid.Data2 as u16,
            guid.Data3 as u16,
            &(guid.Data4 as [u8; 8]),
        )
        .unwrap() // Note: The result in this particular instance is always Ok, so we can
                  //       safely unwrap.
    }

    /// Converts a [`Uuid`] into a little endian winapi `GUID`
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn to_guid(&self) -> guiddef::GUID {
        let (data1, data2, data3, data4) = self.to_fields_le();

        guiddef::GUID {
            Data1: data1,
            Data2: data2,
            Data3: data3,
            Data4: *data4,
        }
    }
}

#[cfg(feature = "guid")]
#[cfg(test)]
mod tests {
    use super::*;

    use crate::std::string::ToString;
    use winapi::shared::guiddef;

    #[test]
    fn test_from_guid() {
        let guid = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid).unwrap();
        assert_eq!(
            "9d22354a-2755-304f-8647-9dc54e1ee1e8",
            uuid.to_hyphenated().to_string()
        );
    }

    #[test]
    fn test_guid_roundtrip() {
        let guid_in = guiddef::GUID {
            Data1: 0x4a35229d,
            Data2: 0x5527,
            Data3: 0x4f30,
            Data4: [0x86, 0x47, 0x9d, 0xc5, 0x4e, 0x1e, 0xe1, 0xe8],
        };

        let uuid = Uuid::from_guid(guid_in).unwrap();
        let guid_out = uuid.to_guid();

        assert_eq!(
            (guid_in.Data1, guid_in.Data2, guid_in.Data3, guid_in.Data4),
            (
                guid_out.Data1,
                guid_out.Data2,
                guid_out.Data3,
                guid_out.Data4
            )
        );
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "serde")]

#[macro_use]
extern crate enum_map;
#[macro_use]
extern crate serde;
extern crate serde_json;
extern crate serde_test;

use enum_map::EnumMap;

use serde_test::{assert_tokens, Token};

#[derive(Debug, EnumMap, Deserialize, Serialize)]
enum Example {
    A,
    B,
}

#[test]
fn serialization() {
    let map = enum_map! { Example::A => 5, Example::B => 10 };
    assert_tokens(
        &map,
        &[
            Token::Map { len: Some(2) },
            Token::UnitVariant {
                name: "Example",
                variant: "A",
            },
            Token::I32(5),
            Token::UnitVariant {
                name: "Example",
                variant: "B",
            },
            Token::I32(10),
            Token::MapEnd,
        ],
    );
}

const JSON: &str = r#"{"A":5,"B":10}"#;

#[test]
fn json_serialization() {
    let map = enum_map! { Example::A => 5, Example::B => 10 };
    assert_eq!(serde_json::to_string(&map).unwrap(), String::from(JSON));
}

#[test]
fn json_deserialization() {
    let example: EnumMap<Example, i32> = serde_json::from_str(JSON).unwrap();
    assert_eq!(example, enum_map! { Example::A => 5, Example::B => 10 });
}

#[test]
fn json_invalid_deserialization() {
    let example: Result<EnumMap<Example, i32>, _> = serde_json::from_str(r"{}");
    assert!(example.is_err());
}

#[test]
fn json_invalid_type() {
    let example: Result<EnumMap<Example, i32>, _> = serde::json::from_str("4");
    assert!(example.is_err());
}

#[test]
fn json_invalid_key() {
    let example: Result<EnumMap<Example, i32>, _> =
        serde_json::from_str(r#"{"a": 5, "b": 10, "c": 6}"#);
    assert!(example.is_err());
}
<commit_msg>Fix wrong module name in json_invalid_type test<commit_after>#![cfg(feature = "serde")]

#[macro_use]
extern crate enum_map;
#[macro_use]
extern crate serde;
extern crate serde_json;
extern crate serde_test;

use enum_map::EnumMap;

use serde_test::{assert_tokens, Token};

#[derive(Debug, EnumMap, Deserialize, Serialize)]
enum Example {
    A,
    B,
}

#[test]
fn serialization() {
    let map = enum_map! { Example::A => 5, Example::B => 10 };
    assert_tokens(
        &map,
        &[
            Token::Map { len: Some(2) },
            Token::UnitVariant {
                name: "Example",
                variant: "A",
            },
            Token::I32(5),
            Token::UnitVariant {
                name: "Example",
                variant: "B",
            },
            Token::I32(10),
            Token::MapEnd,
        ],
    );
}

const JSON: &str = r#"{"A":5,"B":10}"#;

#[test]
fn json_serialization() {
    let map = enum_map! { Example::A => 5, Example::B => 10 };
    assert_eq!(serde_json::to_string(&map).unwrap(), String::from(JSON));
}

#[test]
fn json_deserialization() {
    let example: EnumMap<Example, i32> = serde_json::from_str(JSON).unwrap();
    assert_eq!(example, enum_map! { Example::A => 5, Example::B => 10 });
}

#[test]
fn json_invalid_deserialization() {
    let example: Result<EnumMap<Example, i32>, _> = serde_json::from_str(r"{}");
    assert!(example.is_err());
}

#[test]
fn json_invalid_type() {
    let example: Result<EnumMap<Example, i32>, _> = serde_json::from_str("4");
    assert!(example.is_err());
}

#[test]
fn json_invalid_key() {
    let example: Result<EnumMap<Example, i32>, _> =
        serde_json::from_str(r#"{"a": 5, "b": 10, "c": 6}"#);
    assert!(example.is_err());
}
<|endoftext|>


<commit_before>use ide_db::base_db::Upcast;
use ide_db::RootDatabase;
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};

use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};

// Feature: Go to Type Definition
//
// Navigates to the type of an identifier.
//
// |===
// | Editor  | Action Name
//
// | VS Code | **Go to Type Definition*
// |===
//
// image::https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif[]
pub(crate) fn goto_type_definition(
    db: &RootDatabase,
    position: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
    let sema = hir::Semantics::new(db);

    let file: ast::SourceFile = sema.parse(position.file_id);
    let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?;
    let token: SyntaxToken = sema.descend_into_macros(token);

    let (ty, node) = sema.token_ancestors_with_macros(token).find_map(|node| {
        let ty = match_ast! {
            match node {
                ast::Expr(it) => sema.type_of_expr(&it)?,
                ast::Pat(it) => sema.type_of_pat(&it)?,
                ast::SelfParam(it) => sema.type_of_self(&it)?,
                ast::Type(it) => sema.resolve_type(&it)?,
                ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?,
                _ => return None,
            }
        };

        Some((ty, node))
    })?;

    let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?;

    let nav = adt_def.try_to_nav(db)?;
    Some(RangeInfo::new(node.text_range(), vec![nav]))
}

fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
    return tokens.max_by_key(priority);
    fn priority(n: &SyntaxToken) -> usize {
        match n.kind() {
            IDENT | INT_NUMBER | T![self] => 2,
            kind if kind.is_trivia() => 0,
            _ => 1,
        }
    }
}

#[cfg(test)]
mod tests {
    use ide_db::base_db::FileRange;

    use crate::fixture;

    fn check(ra_fixture: &str) {
        let (analysis, position, mut annotations) = fixture::annotations(ra_fixture);
        let (expected, data) = annotations.pop().unwrap();
        assert!(data.is_empty());

        let mut navs = analysis.goto_type_definition(position).unwrap().unwrap().info;
        assert_eq!(navs.len(), 1);
        let nav = navs.pop().unwrap();
        assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() });
    }

    #[test]
    fn goto_type_definition_works_simple() {
        check(
            r#"
struct Foo;
     //^^^
fn foo() {
    let f: Foo; f$0
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_works_simple_ref() {
        check(
            r#"
struct Foo;
     //^^^
fn foo() {
    let f: &Foo; f$0
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_works_through_macro() {
        check(
            r#"
macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
struct Foo {}
     //^^^
id! {
    fn bar() { let f$0 = Foo {}; }
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_for_param() {
        check(
            r#"
struct Foo;
     //^^^
fn foo($0f: Foo) {}
"#,
        );
    }

    #[test]
    fn goto_type_definition_for_tuple_field() {
        check(
            r#"
struct Foo;
     //^^^
struct Bar(Foo);
fn foo() {
    let bar = Bar(Foo);
    bar.$00;
}
"#,
        );
    }

    #[test]
    fn goto_def_for_self_param() {
        check(
            r#"
struct Foo;
     //^^^
impl Foo {
    fn f(&self$0) {}
}
"#,
        )
    }

    #[test]
    fn goto_def_for_type_fallback() {
        check(
            r#"
struct Foo;
     //^^^
impl Foo$0 {}
"#,
        )
    }

    #[test]
    fn goto_def_for_struct_field() {
        check(
            r#"
struct Bar;
     //^^^

struct Foo {
    bar$0: Bar,
}
"#,
        );
    }

    #[test]
    fn goto_def_for_enum_struct_field() {
        check(
            r#"
struct Bar;
     //^^^

enum Foo {
    Bar {
        bar$0: Bar
    },
}
"#,
        );
    }
}
<commit_msg>Support goto type for field expressions and patterns<commit_after>use ide_db::base_db::Upcast;
use ide_db::RootDatabase;
use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T};

use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};

// Feature: Go to Type Definition
//
// Navigates to the type of an identifier.
//
// |===
// | Editor  | Action Name
//
// | VS Code | **Go to Type Definition*
// |===
//
// image::https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif[]
pub(crate) fn goto_type_definition(
    db: &RootDatabase,
    position: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
    let sema = hir::Semantics::new(db);

    let file: ast::SourceFile = sema.parse(position.file_id);
    let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?;
    let token: SyntaxToken = sema.descend_into_macros(token);

    let (ty, node) = sema.token_ancestors_with_macros(token.clone()).find_map(|node| {
        let ty = match_ast! {
            match node {
                ast::Expr(it) => sema.type_of_expr(&it)?,
                ast::Pat(it) => sema.type_of_pat(&it)?,
                ast::SelfParam(it) => sema.type_of_self(&it)?,
                ast::Type(it) => sema.resolve_type(&it)?,
                ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?,
                ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?,
                // can't match on RecordExprField directly as `ast::Expr` will match an iteration too early otherwise
                ast::NameRef(it) => {
                    if let Some(record_field) = ast::RecordExprField::for_name_ref(&it) {
                        let (_, _, ty) = sema.resolve_record_field(&record_field)?;
                        ty
                    } else {
                        let record_field = ast::RecordPatField::for_field_name_ref(&it)?;
                        sema.resolve_record_pat_field(&record_field)?.ty(db)
                    }
                },
                _ => return None,
            }
        };

        Some((ty, node))
    })?;
    let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?;

    let nav = adt_def.try_to_nav(db)?;
    Some(RangeInfo::new(node.text_range(), vec![nav]))
}

fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
    return tokens.max_by_key(priority);
    fn priority(n: &SyntaxToken) -> usize {
        match n.kind() {
            IDENT | INT_NUMBER | T![self] => 2,
            kind if kind.is_trivia() => 0,
            _ => 1,
        }
    }
}

#[cfg(test)]
mod tests {
    use ide_db::base_db::FileRange;

    use crate::fixture;

    fn check(ra_fixture: &str) {
        let (analysis, position, mut annotations) = fixture::annotations(ra_fixture);
        let (expected, data) = annotations.pop().unwrap();
        assert!(data.is_empty());

        let mut navs = analysis.goto_type_definition(position).unwrap().unwrap().info;
        assert_eq!(navs.len(), 1);
        let nav = navs.pop().unwrap();
        assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() });
    }

    #[test]
    fn goto_type_definition_works_simple() {
        check(
            r#"
struct Foo;
     //^^^
fn foo() {
    let f: Foo; f$0
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_record_expr_field() {
        check(
            r#"
struct Bar;
    // ^^^
struct Foo { foo: Bar }
fn foo() {
    Foo { foo$0 }
}
"#,
        );
        check(
            r#"
struct Bar;
    // ^^^
struct Foo { foo: Bar }
fn foo() {
    Foo { foo$0: Bar }
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_record_pat_field() {
        check(
            r#"
struct Bar;
    // ^^^
struct Foo { foo: Bar }
fn foo() {
    let Foo { foo$0 };
}
"#,
        );
        check(
            r#"
struct Bar;
    // ^^^
struct Foo { foo: Bar }
fn foo() {
    let Foo { foo$0: bar };
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_works_simple_ref() {
        check(
            r#"
struct Foo;
     //^^^
fn foo() {
    let f: &Foo; f$0
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_works_through_macro() {
        check(
            r#"
macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
struct Foo {}
     //^^^
id! {
    fn bar() { let f$0 = Foo {}; }
}
"#,
        );
    }

    #[test]
    fn goto_type_definition_for_param() {
        check(
            r#"
struct Foo;
     //^^^
fn foo($0f: Foo) {}
"#,
        );
    }

    #[test]
    fn goto_type_definition_for_tuple_field() {
        check(
            r#"
struct Foo;
     //^^^
struct Bar(Foo);
fn foo() {
    let bar = Bar(Foo);
    bar.$00;
}
"#,
        );
    }

    #[test]
    fn goto_def_for_self_param() {
        check(
            r#"
struct Foo;
     //^^^
impl Foo {
    fn f(&self$0) {}
}
"#,
        )
    }

    #[test]
    fn goto_def_for_type_fallback() {
        check(
            r#"
struct Foo;
     //^^^
impl Foo$0 {}
"#,
        )
    }

    #[test]
    fn goto_def_for_struct_field() {
        check(
            r#"
struct Bar;
     //^^^

struct Foo {
    bar$0: Bar,
}
"#,
        );
    }

    #[test]
    fn goto_def_for_enum_struct_field() {
        check(
            r#"
struct Bar;
     //^^^

enum Foo {
    Bar {
        bar$0: Bar
    },
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>// run-pass

#![feature(option_expect_none, option_unwrap_none)]

//! Test that panic locations for `#[track_caller]` functions in std have the correct
//! location reported.

fn main() {
    // inspect the `PanicInfo` we receive to ensure the right file is the source
    std::panic::set_hook(Box::new(|info| {
        let actual = info.location().unwrap();
        if actual.file() != file!(){
            eprintln!("expected a location in the test file, found {:?}", actual);
            panic!();
        }
    }));

    fn assert_panicked(f: impl FnOnce() + std::panic::UnwindSafe) {
        std::panic::catch_unwind(f).unwrap_err();
    }

    let nope: Option<()> = None;
    assert_panicked(|| nope.unwrap());
    assert_panicked(|| nope.expect(""));

    let yep: Option<()> = Some(());
    assert_panicked(|| yep.unwrap_none());
    assert_panicked(|| yep.expect_none(""));

    let oops: Result<(), ()> = Err(());
    assert_panicked(|| oops.unwrap());
    assert_panicked(|| oops.expect(""));

    let fine: Result<(), ()> = Ok(());
    assert_panicked(|| fine.unwrap_err());
    assert_panicked(|| fine.expect_err(""));
}
<commit_msg>Fix typo<commit_after>// run-pass

#![feature(option_expect_none, option_unwrap_none)]

//! Test that panic locations for `#[track_caller]` functions in std have the correct
//! location reported.

fn main() {
    // inspect the `PanicInfo` we receive to ensure the right file is the source
    std::panic::set_hook(Box::new(|info| {
        let actual = info.location().unwrap();
        if actual.file() != file!() {
            eprintln!("expected a location in the test file, found {:?}", actual);
            panic!();
        }
    }));

    fn assert_panicked(f: impl FnOnce() + std::panic::UnwindSafe) {
        std::panic::catch_unwind(f).unwrap_err();
    }

    let nope: Option<()> = None;
    assert_panicked(|| nope.unwrap());
    assert_panicked(|| nope.expect(""));

    let yep: Option<()> = Some(());
    assert_panicked(|| yep.unwrap_none());
    assert_panicked(|| yep.expect_none(""));

    let oops: Result<(), ()> = Err(());
    assert_panicked(|| oops.unwrap());
    assert_panicked(|| oops.expect(""));

    let fine: Result<(), ()> = Ok(());
    assert_panicked(|| fine.unwrap_err());
    assert_panicked(|| fine.expect_err(""));
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2016-2017, Robert Ou <rqou@robertou.com> and contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//! Contains functions pertaining to the I/O pins

use std::io;
use std::io::Write;

use *;

/// Mux selection for the ZIA input from this I/O pin's input. The ZIA input can be chosen to come from either the
/// input pin directly or from the output of the register in the macrocell corresponding to this I/O pin. The latter
/// is used to allow for buried combinatorial feedback in a macrocell without "wasting" the register.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum XC2IOBZIAMode {
    Disabled,
    PAD,
    REG,
}

/// Mode selection for the I/O pin's output buffer. See the Xilinx Coolrunner-II documentation for more information.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum XC2IOBOBufMode {
    Disabled,
    PushPull,
    OpenDrain,
    TriStateGTS0,
    TriStateGTS1,
    TriStateGTS2,
    TriStateGTS3,
    TriStatePTB,
    TriStateCTE,
    CGND,
}

/// Represents an I/O pin on "small" (32 and 64 macrocell) devices.
#[derive(Copy, Clone)]
pub struct XC2MCSmallIOB {
    /// Mux selection for the ZIA input for this pin
    pub zia_mode: XC2IOBZIAMode,
    /// Whether the Schmitt trigger is being used on this pin's input
    pub schmitt_trigger: bool,
    /// Selects the source used to drive this pin's output (if the output is enabled).
    /// `false` selects the XOR gate in the macrocell (combinatorial output), and `true` selects the register output
    /// (registered output).
    pub obuf_uses_ff: bool,
    /// Selects the output mode for this pin
    pub obuf_mode: XC2IOBOBufMode,
    /// Selects if the global termination (bus hold or pull-up) is enabled on this pin
    pub termination_enabled: bool,
    /// Selects if fast slew rate is used on this pin
    pub slew_is_fast: bool,
}

impl Default for XC2MCSmallIOB {
    /// Returns a "default" I/O pin configuration. The default state is for the output and the input into the ZIA
    /// to be disabled.

    // FIXME: Do the other defaults come from the particular way I invoked the Xilinx tools??
    fn default() -> XC2MCSmallIOB {
        XC2MCSmallIOB {
            zia_mode: XC2IOBZIAMode::Disabled,
            schmitt_trigger: true,
            obuf_uses_ff: false,
            obuf_mode: XC2IOBOBufMode::Disabled,
            termination_enabled: true,
            slew_is_fast: true,
        }
    }
}

impl XC2MCSmallIOB {
    /// Dump a human-readable explanation of the settings for this pin to the given `writer` object.
    /// `my_idx` must be the index of this I/O pin in the internal numbering scheme.
    pub fn dump_human_readable(&self, my_idx: u32, writer: &mut Write) -> Result<(), io::Error> {
        write!(writer, "\n")?;
        let (fb, ff) = iob_num_to_fb_ff_num_32(my_idx).unwrap();
        write!(writer, "I/O configuration for FB{}_{}\n", fb + 1, ff + 1)?;
        write!(writer, "output mode: {}\n", match self.obuf_mode {
            XC2IOBOBufMode::Disabled => "disabled",
            XC2IOBOBufMode::PushPull => "push-pull",
            XC2IOBOBufMode::OpenDrain => "open-drain",
            XC2IOBOBufMode::TriStateGTS0 => "GTS0-controlled tri-state",
            XC2IOBOBufMode::TriStateGTS1 => "GTS1-controlled tri-state",
            XC2IOBOBufMode::TriStateGTS2 => "GTS2-controlled tri-state",
            XC2IOBOBufMode::TriStateGTS3 => "GTS3-controlled tri-state",
            XC2IOBOBufMode::TriStatePTB => "PTB-controlled tri-state",
            XC2IOBOBufMode::TriStateCTE => "CTE-controlled tri-state",
            XC2IOBOBufMode::CGND => "CGND",
        })?;
        write!(writer, "output comes from {}\n", if self.obuf_uses_ff {"FF"} else {"XOR gate"})?;
        write!(writer, "slew rate: {}\n", if self.slew_is_fast {"fast"} else {"slow"})?;
        write!(writer, "ZIA driven from: {}\n", match self.zia_mode {
            XC2IOBZIAMode::Disabled => "disabled",
            XC2IOBZIAMode::PAD => "input pad",
            XC2IOBZIAMode::REG => "register",
        })?;
        write!(writer, "Schmitt trigger input: {}\n", if self.schmitt_trigger {"yes"} else {"no"})?;
        write!(writer, "termination: {}\n", if self.termination_enabled {"yes"} else {"no"})?;

        Ok(())
    }
}

/// Represents the one additional special input-only pin on 32-macrocell devices.
pub struct XC2ExtraIBuf {
    pub schmitt_trigger: bool,
    pub termination_enabled: bool,
}

impl Default for XC2ExtraIBuf {
    /// Returns a "default" pin configuration.

    // FIXME: Do the other defaults come from the particular way I invoked the Xilinx tools??
    fn default() -> XC2ExtraIBuf {
        XC2ExtraIBuf {
            schmitt_trigger: true,
            termination_enabled: true,
        }
    }
}

impl XC2ExtraIBuf {
    /// Dump a human-readable explanation of the settings for this pin to the given `writer` object.
    pub fn dump_human_readable(&self, writer: &mut Write) -> Result<(), io::Error> {
        write!(writer, "\n")?;
        write!(writer, "I/O configuration for input-only pin\n")?;
        write!(writer, "Schmitt trigger input: {}\n", if self.schmitt_trigger {"yes"} else {"no"})?;
        write!(writer, "termination: {}\n", if self.termination_enabled {"yes"} else {"no"})?;

        Ok(())
    }
}

/// Function to map from the internal numbering scheme for I/O pins to a function block and macrocell number.
/// This function is for the 32-macrocell devices.
pub fn iob_num_to_fb_ff_num_32(iob: u32) -> Option<(u32, u32)> {
    if iob >= 32 {
        None
    } else {
        Some((iob / MCS_PER_FB as u32, iob % MCS_PER_FB as u32))
    }
}

/// Function to map from a function block and macrocell number to the internal numbering scheme for I/O pins.
/// This function is for the 32-macrocell devices.
pub fn fb_ff_num_to_iob_num_32(fb: u32, ff: u32) -> Option<u32> {
    if fb >= 2 || ff >= MCS_PER_FB as u32 {
        None
    } else {
        Some(fb * MCS_PER_FB as u32 + ff)
    }
}

/// Function to map from the internal numbering scheme for I/O pins to a function block and macrocell number.
/// This function is for the 64-macrocell devices.
pub fn iob_num_to_fb_ff_num_64(iob: u32) -> Option<(u32, u32)> {
    if iob >= 64 {
        None
    } else {
        Some((iob / MCS_PER_FB as u32, iob % MCS_PER_FB as u32))
    }
}

/// Function to map from a function block and macrocell number to the internal numbering scheme for I/O pins.
/// This function is for the 64-macrocell devices.
pub fn fb_ff_num_to_iob_num_64(fb: u32, ff: u32) -> Option<u32> {
    if fb >= 4 || ff >= MCS_PER_FB as u32 {
        None
    } else {
        Some(fb * MCS_PER_FB as u32 + ff)
    }
}

/// Internal function that reads only the IO-related bits from the macrocell configuration
pub fn read_small_iob_logical(fuses: &[bool], block_idx: usize, io_idx: usize) -> Result<XC2MCSmallIOB, &'static str> {
    let inz = (fuses[block_idx + io_idx * 27 + 11],
               fuses[block_idx + io_idx * 27 + 12]);
    let input_to_zia = match inz {
        (false, false) => XC2IOBZIAMode::PAD,
        (true, false) => XC2IOBZIAMode::REG,
        (_, true) => XC2IOBZIAMode::Disabled,
    };

    let st = fuses[block_idx + io_idx * 27 + 16];
    let regcom = fuses[block_idx + io_idx * 27 + 19];

    let oe = (fuses[block_idx + io_idx * 27 + 20],
              fuses[block_idx + io_idx * 27 + 21],
              fuses[block_idx + io_idx * 27 + 22],
              fuses[block_idx + io_idx * 27 + 23]);
    let output_mode = match oe {
        (false, false, false, false) => XC2IOBOBufMode::PushPull,
        (false, false, false, true)  => XC2IOBOBufMode::OpenDrain,
        (false, false, true, false)  => XC2IOBOBufMode::TriStateGTS1,
        (false, true, false, false)  => XC2IOBOBufMode::TriStatePTB,
        (false, true, true, false)   => XC2IOBOBufMode::TriStateGTS3,
        (true, false, false, false)  => XC2IOBOBufMode::TriStateCTE,
        (true, false, true, false)   => XC2IOBOBufMode::TriStateGTS2,
        (true, true, false, false)   => XC2IOBOBufMode::TriStateGTS0,
        (true, true, true, false)    => XC2IOBOBufMode::CGND,
        (true, true, true, true)     => XC2IOBOBufMode::Disabled,
        _ => return Err("unknown Oe mode used"),
    };

    let tm = fuses[block_idx + io_idx * 27 + 24];
    let slw = fuses[block_idx + io_idx * 27 + 25];

    Ok(XC2MCSmallIOB {
        zia_mode: input_to_zia,
        schmitt_trigger: st,
        obuf_uses_ff: !regcom,
        obuf_mode: output_mode,
        termination_enabled: tm,
        slew_is_fast: !slw,
    })
}

/// Internal function that reads only the input-only pin configuration
pub fn read_32_extra_ibuf_logical(fuses: &[bool]) -> XC2ExtraIBuf {
    let st = fuses[12272];
    let tm = fuses[12273];

    XC2ExtraIBuf {
        schmitt_trigger: st,
        termination_enabled: tm,
    }
}
<commit_msg>xc2bit: Obviously incorrect fix to dump 64 bitstreams<commit_after>/*
Copyright (c) 2016-2017, Robert Ou <rqou@robertou.com> and contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//! Contains functions pertaining to the I/O pins

use std::io;
use std::io::Write;

use *;

/// Mux selection for the ZIA input from this I/O pin's input. The ZIA input can be chosen to come from either the
/// input pin directly or from the output of the register in the macrocell corresponding to this I/O pin. The latter
/// is used to allow for buried combinatorial feedback in a macrocell without "wasting" the register.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum XC2IOBZIAMode {
    Disabled,
    PAD,
    REG,
}

/// Mode selection for the I/O pin's output buffer. See the Xilinx Coolrunner-II documentation for more information.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum XC2IOBOBufMode {
    Disabled,
    PushPull,
    OpenDrain,
    TriStateGTS0,
    TriStateGTS1,
    TriStateGTS2,
    TriStateGTS3,
    TriStatePTB,
    TriStateCTE,
    CGND,
}

/// Represents an I/O pin on "small" (32 and 64 macrocell) devices.
#[derive(Copy, Clone)]
pub struct XC2MCSmallIOB {
    /// Mux selection for the ZIA input for this pin
    pub zia_mode: XC2IOBZIAMode,
    /// Whether the Schmitt trigger is being used on this pin's input
    pub schmitt_trigger: bool,
    /// Selects the source used to drive this pin's output (if the output is enabled).
    /// `false` selects the XOR gate in the macrocell (combinatorial output), and `true` selects the register output
    /// (registered output).
    pub obuf_uses_ff: bool,
    /// Selects the output mode for this pin
    pub obuf_mode: XC2IOBOBufMode,
    /// Selects if the global termination (bus hold or pull-up) is enabled on this pin
    pub termination_enabled: bool,
    /// Selects if fast slew rate is used on this pin
    pub slew_is_fast: bool,
}

impl Default for XC2MCSmallIOB {
    /// Returns a "default" I/O pin configuration. The default state is for the output and the input into the ZIA
    /// to be disabled.

    // FIXME: Do the other defaults come from the particular way I invoked the Xilinx tools??
    fn default() -> XC2MCSmallIOB {
        XC2MCSmallIOB {
            zia_mode: XC2IOBZIAMode::Disabled,
            schmitt_trigger: true,
            obuf_uses_ff: false,
            obuf_mode: XC2IOBOBufMode::Disabled,
            termination_enabled: true,
            slew_is_fast: true,
        }
    }
}

impl XC2MCSmallIOB {
    /// Dump a human-readable explanation of the settings for this pin to the given `writer` object.
    /// `my_idx` must be the index of this I/O pin in the internal numbering scheme.
    pub fn dump_human_readable(&self, my_idx: u32, writer: &mut Write) -> Result<(), io::Error> {
        write!(writer, "\n")?;
        let (fb, ff) = iob_num_to_fb_ff_num_64(my_idx).unwrap();
        write!(writer, "I/O configuration for FB{}_{}\n", fb + 1, ff + 1)?;
        write!(writer, "output mode: {}\n", match self.obuf_mode {
            XC2IOBOBufMode::Disabled => "disabled",
            XC2IOBOBufMode::PushPull => "push-pull",
            XC2IOBOBufMode::OpenDrain => "open-drain",
            XC2IOBOBufMode::TriStateGTS0 => "GTS0-controlled tri-state",
            XC2IOBOBufMode::TriStateGTS1 => "GTS1-controlled tri-state",
            XC2IOBOBufMode::TriStateGTS2 => "GTS2-controlled tri-state",
            XC2IOBOBufMode::TriStateGTS3 => "GTS3-controlled tri-state",
            XC2IOBOBufMode::TriStatePTB => "PTB-controlled tri-state",
            XC2IOBOBufMode::TriStateCTE => "CTE-controlled tri-state",
            XC2IOBOBufMode::CGND => "CGND",
        })?;
        write!(writer, "output comes from {}\n", if self.obuf_uses_ff {"FF"} else {"XOR gate"})?;
        write!(writer, "slew rate: {}\n", if self.slew_is_fast {"fast"} else {"slow"})?;
        write!(writer, "ZIA driven from: {}\n", match self.zia_mode {
            XC2IOBZIAMode::Disabled => "disabled",
            XC2IOBZIAMode::PAD => "input pad",
            XC2IOBZIAMode::REG => "register",
        })?;
        write!(writer, "Schmitt trigger input: {}\n", if self.schmitt_trigger {"yes"} else {"no"})?;
        write!(writer, "termination: {}\n", if self.termination_enabled {"yes"} else {"no"})?;

        Ok(())
    }
}

/// Represents the one additional special input-only pin on 32-macrocell devices.
pub struct XC2ExtraIBuf {
    pub schmitt_trigger: bool,
    pub termination_enabled: bool,
}

impl Default for XC2ExtraIBuf {
    /// Returns a "default" pin configuration.

    // FIXME: Do the other defaults come from the particular way I invoked the Xilinx tools??
    fn default() -> XC2ExtraIBuf {
        XC2ExtraIBuf {
            schmitt_trigger: true,
            termination_enabled: true,
        }
    }
}

impl XC2ExtraIBuf {
    /// Dump a human-readable explanation of the settings for this pin to the given `writer` object.
    pub fn dump_human_readable(&self, writer: &mut Write) -> Result<(), io::Error> {
        write!(writer, "\n")?;
        write!(writer, "I/O configuration for input-only pin\n")?;
        write!(writer, "Schmitt trigger input: {}\n", if self.schmitt_trigger {"yes"} else {"no"})?;
        write!(writer, "termination: {}\n", if self.termination_enabled {"yes"} else {"no"})?;

        Ok(())
    }
}

/// Function to map from the internal numbering scheme for I/O pins to a function block and macrocell number.
/// This function is for the 32-macrocell devices.
pub fn iob_num_to_fb_ff_num_32(iob: u32) -> Option<(u32, u32)> {
    if iob >= 32 {
        None
    } else {
        Some((iob / MCS_PER_FB as u32, iob % MCS_PER_FB as u32))
    }
}

/// Function to map from a function block and macrocell number to the internal numbering scheme for I/O pins.
/// This function is for the 32-macrocell devices.
pub fn fb_ff_num_to_iob_num_32(fb: u32, ff: u32) -> Option<u32> {
    if fb >= 2 || ff >= MCS_PER_FB as u32 {
        None
    } else {
        Some(fb * MCS_PER_FB as u32 + ff)
    }
}

/// Function to map from the internal numbering scheme for I/O pins to a function block and macrocell number.
/// This function is for the 64-macrocell devices.
pub fn iob_num_to_fb_ff_num_64(iob: u32) -> Option<(u32, u32)> {
    if iob >= 64 {
        None
    } else {
        Some((iob / MCS_PER_FB as u32, iob % MCS_PER_FB as u32))
    }
}

/// Function to map from a function block and macrocell number to the internal numbering scheme for I/O pins.
/// This function is for the 64-macrocell devices.
pub fn fb_ff_num_to_iob_num_64(fb: u32, ff: u32) -> Option<u32> {
    if fb >= 4 || ff >= MCS_PER_FB as u32 {
        None
    } else {
        Some(fb * MCS_PER_FB as u32 + ff)
    }
}

/// Internal function that reads only the IO-related bits from the macrocell configuration
pub fn read_small_iob_logical(fuses: &[bool], block_idx: usize, io_idx: usize) -> Result<XC2MCSmallIOB, &'static str> {
    let inz = (fuses[block_idx + io_idx * 27 + 11],
               fuses[block_idx + io_idx * 27 + 12]);
    let input_to_zia = match inz {
        (false, false) => XC2IOBZIAMode::PAD,
        (true, false) => XC2IOBZIAMode::REG,
        (_, true) => XC2IOBZIAMode::Disabled,
    };

    let st = fuses[block_idx + io_idx * 27 + 16];
    let regcom = fuses[block_idx + io_idx * 27 + 19];

    let oe = (fuses[block_idx + io_idx * 27 + 20],
              fuses[block_idx + io_idx * 27 + 21],
              fuses[block_idx + io_idx * 27 + 22],
              fuses[block_idx + io_idx * 27 + 23]);
    let output_mode = match oe {
        (false, false, false, false) => XC2IOBOBufMode::PushPull,
        (false, false, false, true)  => XC2IOBOBufMode::OpenDrain,
        (false, false, true, false)  => XC2IOBOBufMode::TriStateGTS1,
        (false, true, false, false)  => XC2IOBOBufMode::TriStatePTB,
        (false, true, true, false)   => XC2IOBOBufMode::TriStateGTS3,
        (true, false, false, false)  => XC2IOBOBufMode::TriStateCTE,
        (true, false, true, false)   => XC2IOBOBufMode::TriStateGTS2,
        (true, true, false, false)   => XC2IOBOBufMode::TriStateGTS0,
        (true, true, true, false)    => XC2IOBOBufMode::CGND,
        (true, true, true, true)     => XC2IOBOBufMode::Disabled,
        _ => return Err("unknown Oe mode used"),
    };

    let tm = fuses[block_idx + io_idx * 27 + 24];
    let slw = fuses[block_idx + io_idx * 27 + 25];

    Ok(XC2MCSmallIOB {
        zia_mode: input_to_zia,
        schmitt_trigger: st,
        obuf_uses_ff: !regcom,
        obuf_mode: output_mode,
        termination_enabled: tm,
        slew_is_fast: !slw,
    })
}

/// Internal function that reads only the input-only pin configuration
pub fn read_32_extra_ibuf_logical(fuses: &[bool]) -> XC2ExtraIBuf {
    let st = fuses[12272];
    let tm = fuses[12273];

    XC2ExtraIBuf {
        schmitt_trigger: st,
        termination_enabled: tm,
    }
}
<|endoftext|>


<commit_before>extern crate winit;

fn main() {
    let mut events_loop = winit::EventsLoop::new();

    let window1 = winit::Window::new(&events_loop).unwrap();
    let window2 = winit::Window::new(&events_loop).unwrap();
    let window3 = winit::Window::new(&events_loop).unwrap();
    let window4 = winit::Window::new(&events_loop).unwrap();

    let window4_id = window4.id();
    let mut window4_opt = Some(window4);

    let mut num_windows = 4;

    println!("Press any key on any window to drop the 4th window explicitly. (Testing impl Drop for Window)");

    if cfg!(target_os = "linux") {
        println!("Running this example under wayland may not display a window at all.\n\
                  This is normal and because this example does not actually draw anything in the window,\
                  thus the compositor does not display it.");
    }

    events_loop.run_forever(|event| {
        match event {
            winit::Event::WindowEvent { event: winit::WindowEvent::Closed, window_id } => {
                if window_id == window1.id() {
                    println!("Window 1 has been closed")
                } else if window_id == window2.id() {
                    println!("Window 2 has been closed")
                } else if window_id == window3.id() {
                    println!("Window 3 has been closed");
                } else if window_id == window4_id {
                    println!("Window 4 has been closed");
                } else {
                    unreachable!()
                }

                num_windows -= 1;
                if num_windows == 0 {
                    return winit::ControlFlow::Break;
                }
            },

            winit::Event::WindowEvent { event: winit::WindowEvent::KeyboardInput{..}, .. } => {
                println!("Dropping window 4 explicitly");
                window4_opt = None;
            },

            _ => (),
        }
        winit::ControlFlow::Continue
    })
}
<commit_msg>Revert "test explicit drop"<commit_after>extern crate winit;

fn main() {
    let mut events_loop = winit::EventsLoop::new();

    let window1 = winit::Window::new(&events_loop).unwrap();
    let window2 = winit::Window::new(&events_loop).unwrap();
    let window3 = winit::Window::new(&events_loop).unwrap();

    let mut num_windows = 3;

    if cfg!(target_os = "linux") {
        println!("Running this example under wayland may not display a window at all.\n\
                  This is normal and because this example does not actually draw anything in the window,\
                  thus the compositor does not display it.");
    }

    events_loop.run_forever(|event| {
        match event {
            winit::Event::WindowEvent { event: winit::WindowEvent::Closed, window_id } => {
                if window_id == window1.id() {
                    println!("Window 1 has been closed")
                } else if window_id == window2.id() {
                    println!("Window 2 has been closed")
                } else if window_id == window3.id() {
                    println!("Window 3 has been closed");
                } else {
                    unreachable!()
                }

                num_windows -= 1;
                if num_windows == 0 {
                    return winit::ControlFlow::Break;
                }
            },
            _ => (),
        }
        winit::ControlFlow::Continue
    })
}
<|endoftext|>


<commit_before>extern crate image;
extern crate texture_packer;

use std::{fs::File, path::Path};
use texture_packer::{
    exporter::ImageExporter, importer::ImageImporter, texture::Texture, MultiTexturePacker,
    TexturePacker, TexturePackerConfig,
};

fn main() {
    //
    // Perform texture packing
    //
    let config = TexturePackerConfig {
        max_width: 400,
        max_height: 400,
        allow_rotation: false,
        texture_outlines: true,
        border_padding: 2,
        ..Default::default()
    };

    // single atlas
    {
        let mut packer = TexturePacker::new_skyline(config);

        for i in 1..11 {
            let name = format!("{}.png", i);
            let path = format!("examples/assets/{}", name);
            let path = Path::new(&path);
            let texture = ImageImporter::import_from_file(&path).unwrap();

            packer.pack_own(name, texture).unwrap();
        }

        //
        // Print the information
        //
        println!("Dimensions : {}x{}", packer.width(), packer.height());
        for (name, frame) in packer.get_frames() {
            println!("  {:7} : {:?}", name, frame.frame);
        }

        //
        // Save the result
        //
        let exporter = ImageExporter::export(&packer).unwrap();
        let mut file = File::create("examples/output/skyline-packer-output.png").unwrap();
        exporter
            .write_to(&mut file, image::ImageFormat::Png)
            .unwrap();
    }

    // multiple atlases
    {
        let mut packer = MultiTexturePacker::new_skyline(config);

        for i in 1..11 {
            let name = format!("{}.png", i);
            let path = format!("examples/assets/{}", name);
            let path = Path::new(&path);
            let texture = ImageImporter::import_from_file(&path).unwrap();

            packer.pack_own(format!("A{}", i), texture.clone()).unwrap();
            packer.pack_own(format!("B{}", i), texture).unwrap();
        }

        for (i, page) in packer.get_pages().into_iter().enumerate() {
            //
            // Print the information
            //
            println!("#{} | Dimensions : {}x{}", i, page.width(), page.height());
            for (name, frame) in page.get_frames() {
                println!("#{} |   {:7} : {:?}", i, name, frame.frame);
            }

            //
            // Save the result
            //
            let exporter = ImageExporter::export(page).unwrap();
            let mut file = File::create(&format!(
                "examples/output/skyline-multi-packer-output-{}.png",
                i
            ))
            .unwrap();
            exporter
                .write_to(&mut file, image::ImageFormat::Png)
                .unwrap();
        }
    }
}
<commit_msg>example: Issue a panic message to enable the png feature<commit_after>extern crate image;
extern crate texture_packer;

use std::{fs::File, path::Path};
use texture_packer::{
    exporter::ImageExporter, importer::ImageImporter, texture::Texture, MultiTexturePacker,
    TexturePacker, TexturePackerConfig,
};

fn main() {
    //
    // Perform texture packing
    //
    let config = TexturePackerConfig {
        max_width: 400,
        max_height: 400,
        allow_rotation: false,
        texture_outlines: true,
        border_padding: 2,
        ..Default::default()
    };

    // single atlas
    {
        let mut packer = TexturePacker::new_skyline(config);

        for i in 1..11 {
            let name = format!("{}.png", i);
            let path = format!("examples/assets/{}", name);
            let path = Path::new(&path);
            let texture = ImageImporter::import_from_file(&path)
                .expect("Unable to import file. Run this example with --features=\"png\"");

            packer.pack_own(name, texture).unwrap();
        }

        //
        // Print the information
        //
        println!("Dimensions : {}x{}", packer.width(), packer.height());
        for (name, frame) in packer.get_frames() {
            println!("  {:7} : {:?}", name, frame.frame);
        }

        //
        // Save the result
        //
        let exporter = ImageExporter::export(&packer).unwrap();
        let mut file = File::create("examples/output/skyline-packer-output.png").unwrap();
        exporter
            .write_to(&mut file, image::ImageFormat::Png)
            .unwrap();
    }

    // multiple atlases
    {
        let mut packer = MultiTexturePacker::new_skyline(config);

        for i in 1..11 {
            let name = format!("{}.png", i);
            let path = format!("examples/assets/{}", name);
            let path = Path::new(&path);
            let texture = ImageImporter::import_from_file(&path).unwrap();

            packer.pack_own(format!("A{}", i), texture.clone()).unwrap();
            packer.pack_own(format!("B{}", i), texture).unwrap();
        }

        for (i, page) in packer.get_pages().into_iter().enumerate() {
            //
            // Print the information
            //
            println!("#{} | Dimensions : {}x{}", i, page.width(), page.height());
            for (name, frame) in page.get_frames() {
                println!("#{} |   {:7} : {:?}", i, name, frame.frame);
            }

            //
            // Save the result
            //
            let exporter = ImageExporter::export(page).unwrap();
            let mut file = File::create(&format!(
                "examples/output/skyline-multi-packer-output-{}.png",
                i
            ))
            .unwrap();
            exporter
                .write_to(&mut file, image::ImageFormat::Png)
                .unwrap();
        }
    }
}
<|endoftext|>