<commit_before>use std::ops::Mul;
use std::sync::Arc;
use std::vec::IntoIter;
use na::{Translate, Cross, Translation, Rotation};
use math::{Scalar, Point, Vect, Isometry};
use utils::data::uid_remap::{UidRemap, FastKey};
use entities::inspection::Repr;
use entities::bounding_volume::{self, AABB};
use queries::ray::{RayCast, Ray, RayIntersection};
use queries::point::PointQuery;
use narrow_phase::{BasicCollisionDispatcher, ContactSignalHandler};
use broad_phase::{BroadPhase, DBVTBroadPhase};
use world::{CollisionObjectsDispatcher, CollisionObject, CollisionGroups, ContactPairs, Contacts};

use na::{Pnt2, Pnt3, Iso2, Iso3};

// FIXME: be generic wrt the BV?
/// Type of the broad phase trait-object used by the collision world.
pub type BroadPhaseObject<P> = Box<BroadPhase<P, AABB<P>, FastKey> + 'static>;

/// A world that handles collision objects.
pub struct CollisionWorld<P, M, T> {
    objects:       UidRemap<CollisionObject<P, M, T>>,
    broad_phase:   BroadPhaseObject<P>,
    narrow_phase:  CollisionObjectsDispatcher<P, M, T>,
    pos_to_update: Vec<(FastKey, M)>,
    timestamp:     usize
    // FIXME: allow modification of the other properties too.
}

impl<P, M, T> CollisionWorld<P, M, T>
    where P: Point,
          P::Vect: Translate<P> + Cross,
          <P::Vect as Cross>::CrossProductType: Vect<Scalar = <P::Vect as Vect>::Scalar> +
                                                Mul<<P::Vect as Vect>::Scalar, Output = <P::Vect as Cross>::CrossProductType>, // FIXME: why do we need this?
          M:  Isometry<P, P::Vect> + Translation<P::Vect> + Rotation<<P::Vect as Cross>::CrossProductType> {
    /// Creates a new collision world.
    // FIXME: use default values for `margin` and `prediction` and allow their modification by the
    // user ?
    pub fn new(margin:     <P::Vect as Vect>::Scalar,
               prediction: <P::Vect as Vect>::Scalar,
               small_uids: bool)
               -> CollisionWorld<P, M, T> {
        let objects = UidRemap::new(small_uids);
        let sdispatcher = Box::new(BasicCollisionDispatcher::new(prediction));
        let broad_phase = Box::new(DBVTBroadPhase::<P, AABB<P>, FastKey>::new(margin, true));
        let narrow_phase = CollisionObjectsDispatcher::new(sdispatcher);

        CollisionWorld {
            objects:       objects,
            broad_phase:   broad_phase,
            narrow_phase:  narrow_phase,
            pos_to_update: Vec::new(),
            timestamp:     0
        }
    }

    /// Adds a collision object to the world.
    pub fn add(&mut self,
               uid: usize,
               position: M,
               shape: Arc<Box<Repr<P, M>>>,
               collision_groups: CollisionGroups,
               data: T) {
        // FIXME: test that we did not add this object already ?

        let mut collision_object = CollisionObject::new(position, shape, collision_groups, data);
        collision_object.timestamp = self.timestamp;
        let aabb = bounding_volume::aabb(&**collision_object.shape, &collision_object.position);
        let fk = self.objects.insert(uid, collision_object).0;
        self.broad_phase.defered_add(fk.uid(), aabb, fk)
    }

    /// Remove a collision object from the world.
    pub fn remove(&mut self, uid: usize) {
        if let Some((fk, _)) = self.objects.remove(uid) {
            self.broad_phase.defered_remove(fk.uid());
        }
    }

    /// Updates the collision world.
    ///
    /// This executes the whole collision detection pipeline: the broad phase first, then the
    /// narrow phase.
    pub fn update(&mut self) {
        self.perform_position_update();
        self.perform_broad_phase();
        self.perform_narrow_phase();
    }

    /// Sets the position the collision object attached to the specified object will have during
    /// the next update.
    pub fn defered_set_position(&mut self, uid: usize, pos: M) {
        if let Some(fk) = self.objects.get_fast_key(uid) {
            self.pos_to_update.push((fk, pos))
        }
    }

    /// Registers a handler for contact start/stop events.
    pub fn register_contact_signal_handler<H>(&mut self, name: &str, handler: H)
        where H: ContactSignalHandler<T> + 'static {
        self.narrow_phase.register_contact_signal_handler(name, Box::new(handler))
    }

    /// Unregisters a handler for contact start/stop events.
    pub fn unregister_contact_signal_handler(&mut self, name: &str) {
        self.narrow_phase.unregister_contact_signal_handler(name)
    }

    /// Executes the position updates.
    pub fn perform_position_update(&mut self) {
        for &(ref fk, ref pos) in self.pos_to_update.iter() {
            if let Some(co) = self.objects.get_fast_mut(fk) {
                co.position = pos.clone();
                co.timestamp = self.timestamp;
                self.broad_phase.defered_set_bounding_volume(fk.uid(), bounding_volume::aabb(&**co.shape, pos));
            }
        }

        self.pos_to_update.clear();
    }

    /// Executes the broad phase of the collision detection pipeline.
    ///
    /// Not that this does not take in account the changes made to the collision updates after the
    /// last `.perform_position_update()` call.
    pub fn perform_broad_phase(&mut self) {
        let bf = &mut self.broad_phase;
        let nf = &mut self.narrow_phase;
        let objs = &self.objects;

        bf.update(
            &mut |b1, b2| CollisionObjectsDispatcher::is_proximity_allowed(objs, b1, b2),
            &mut |b1, b2, started| nf.handle_proximity(objs, b1, b2, started)
        );
    }

    /// Executes the narrow phase of the collision detection pipeline.
    pub fn perform_narrow_phase(&mut self) {
        self.narrow_phase.update(&self.objects, self.timestamp);
        self.timestamp = self.timestamp + 1;
    }

    /// Iterates through all the contact pairs detected since the last update.
    #[inline]
    pub fn contact_pairs(&self) -> ContactPairs<P, M, T> {
        self.narrow_phase.contact_pairs(&self.objects)
    }

    /// Iterates through every contact detected since the last update.
    #[inline]
    pub fn contacts(&self) -> Contacts<P, M, T> {
        self.narrow_phase.contacts(&self.objects)
    }

    /// Computes the interferences between every rigid bodies on this world and a ray.
    #[inline]
    pub fn interferences_with_ray<'a>(&'a self, ray: &'a Ray<P>, groups: &'a CollisionGroups)
        -> InterferencesWithRay<'a, P, M, T> {
        // FIXME: avoid allocation.
        let mut fks = Vec::new();

        self.broad_phase.interferences_with_ray(ray, &mut fks);

        InterferencesWithRay {
            ray:     ray,
            groups:  groups,
            objects: &self.objects,
            idx:     fks.into_iter()
        }
    }

    /// Computes the interferences between every rigid bodies of a given broad phase, and a point.
    #[inline]
    pub fn interferences_with_point<'a>(&'a self, point: &'a P, groups: &'a CollisionGroups)
        -> InterferencesWithPoint<'a, P, M, T> {
        // FIXME: avoid allocation.
        let mut fks = Vec::new();

        self.broad_phase.interferences_with_point(point, &mut fks);

        InterferencesWithPoint {
            point:   point,
            groups:  groups,
            objects: &self.objects,
            idx:     fks.into_iter()
        }
    }

    /// Computes the interferences between every rigid bodies of a given broad phase, and a aabb.
    #[inline]
    pub fn interferences_with_aabb<'a>(&'a self, aabb: &'a AABB<P>, groups: &'a CollisionGroups)
        -> InterferencesWithAABB<'a, P, M, T> {
        // FIXME: avoid allocation.
        let mut fks = Vec::new();

        self.broad_phase.interferences_with_bounding_volume(aabb, &mut fks);

        InterferencesWithAABB {
            groups:  groups,
            objects: &self.objects,
            idx:     fks.into_iter()
        }
    }
}

/// Iterator through all the objects on the world that intersect a specific ray.
pub struct InterferencesWithRay<'a, P: 'a + Point, M: 'a, T: 'a> {
    ray:     &'a Ray<P>,
    objects: &'a UidRemap<CollisionObject<P, M, T>>,
    groups:  &'a CollisionGroups,
    idx:     IntoIter<&'a FastKey>,
}

impl<'a, P, M, T> Iterator for InterferencesWithRay<'a, P, M, T>
    where P: Point,
          M: Isometry<P, P::Vect> + Translation<P::Vect> {
    type Item = (&'a CollisionObject<P, M, T>, RayIntersection<P::Vect>);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(id) = self.idx.next() {
            let co = &self.objects[*id];

            if co.collision_groups.can_collide_with_groups(self.groups) {
                let inter = co.shape.toi_and_normal_with_ray(&co.position, self.ray, true);

                if let Some(inter) = inter {
                    return Some((co, inter))
                }
            }
        }

        None
    }
}

/// Iterator through all the objects on the world that intersect a specific point.
pub struct InterferencesWithPoint<'a, P: 'a, M: 'a, T: 'a> {
    point:   &'a P,
    objects: &'a UidRemap<CollisionObject<P, M, T>>,
    groups:  &'a CollisionGroups,
    idx:     IntoIter<&'a FastKey>,
}

impl<'a, P, M, T> Iterator for InterferencesWithPoint<'a, P, M, T>
    where P: Point,
          M: Isometry<P, P::Vect> + Translation<P::Vect> {
    type Item = &'a CollisionObject<P, M, T>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(id) = self.idx.next() {
            let co = &self.objects[*id];

            if co.collision_groups.can_collide_with_groups(self.groups) &&
               co.shape.contains_point(&co.position, self.point) {
                return Some(co)
            }
        }

        None
    }
}

/// Iterator through all the objects on the world which bounding volume intersects a specific AABB.
pub struct InterferencesWithAABB<'a, P: 'a, M: 'a, T: 'a> {
    objects: &'a UidRemap<CollisionObject<P, M, T>>,
    groups:  &'a CollisionGroups,
    idx:     IntoIter<&'a FastKey>,
}

impl<'a, P, M, T> Iterator for InterferencesWithAABB<'a, P, M, T> {
    type Item = &'a CollisionObject<P, M, T>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(id) = self.idx.next() {
            let co = &self.objects[*id];

            if co.collision_groups.can_collide_with_groups(self.groups) {
                return Some(co)
            }
        }

        None
    }
}

/// 2D collision world containing objects of type `T`.
pub type CollisionWorld2<N, T> = CollisionWorld<Pnt2<N>, Iso2<N>, T>;
/// 3D collision world containing objects of type `T`.
pub type CollisionWorld3<N, T> = CollisionWorld<Pnt3<N>, Iso3<N>, T>;
<commit_msg>Fix for Issue #57<commit_after>use std::ops::Mul;
use std::sync::Arc;
use std::vec::IntoIter;
use na::{Translate, Cross, Translation, Rotation};
use math::{Scalar, Point, Vect, Isometry};
use utils::data::uid_remap::{UidRemap, FastKey};
use entities::inspection::Repr;
use entities::bounding_volume::{self, AABB};
use queries::ray::{RayCast, Ray, RayIntersection};
use queries::point::PointQuery;
use narrow_phase::{BasicCollisionDispatcher, ContactSignalHandler};
use broad_phase::{BroadPhase, DBVTBroadPhase};
use world::{CollisionObjectsDispatcher, CollisionObject, CollisionGroups, ContactPairs, Contacts};

use na::{Pnt2, Pnt3, Iso2, Iso3};

// FIXME: be generic wrt the BV?
/// Type of the broad phase trait-object used by the collision world.
pub type BroadPhaseObject<P> = Box<BroadPhase<P, AABB<P>, FastKey> + 'static>;

/// A world that handles collision objects.
pub struct CollisionWorld<P, M, T> {
    objects:       UidRemap<CollisionObject<P, M, T>>,
    broad_phase:   BroadPhaseObject<P>,
    narrow_phase:  CollisionObjectsDispatcher<P, M, T>,
    pos_to_update: Vec<(FastKey, M)>,
    objects_to_remove: Vec<usize>,
    timestamp:     usize
    // FIXME: allow modification of the other properties too.
}

impl<P, M, T> CollisionWorld<P, M, T>
    where P: Point,
          P::Vect: Translate<P> + Cross,
          <P::Vect as Cross>::CrossProductType: Vect<Scalar = <P::Vect as Vect>::Scalar> +
                                                Mul<<P::Vect as Vect>::Scalar, Output = <P::Vect as Cross>::CrossProductType>, // FIXME: why do we need this?
          M:  Isometry<P, P::Vect> + Translation<P::Vect> + Rotation<<P::Vect as Cross>::CrossProductType> {
    /// Creates a new collision world.
    // FIXME: use default values for `margin` and `prediction` and allow their modification by the
    // user ?
    pub fn new(margin:     <P::Vect as Vect>::Scalar,
               prediction: <P::Vect as Vect>::Scalar,
               small_uids: bool)
               -> CollisionWorld<P, M, T> {
        let objects = UidRemap::new(small_uids);
        let sdispatcher = Box::new(BasicCollisionDispatcher::new(prediction));
        let broad_phase = Box::new(DBVTBroadPhase::<P, AABB<P>, FastKey>::new(margin, true));
        let narrow_phase = CollisionObjectsDispatcher::new(sdispatcher);

        CollisionWorld {
            objects:       objects,
            broad_phase:   broad_phase,
            narrow_phase:  narrow_phase,
            pos_to_update: Vec::new(),
            objects_to_remove: Vec::new(),
            timestamp:     0
        }
    }

    /// Adds a collision object to the world.
    pub fn add(&mut self,
               uid: usize,
               position: M,
               shape: Arc<Box<Repr<P, M>>>,
               collision_groups: CollisionGroups,
               data: T) {
        // FIXME: test that we did not add this object already ?

        let mut collision_object = CollisionObject::new(position, shape, collision_groups, data);
        collision_object.timestamp = self.timestamp;
        let aabb = bounding_volume::aabb(&**collision_object.shape, &collision_object.position);
        let fk = self.objects.insert(uid, collision_object).0;
        self.broad_phase.defered_add(fk.uid(), aabb, fk)
    }

    /// Remove a collision object from the world.
    pub fn remove(&mut self, uid: usize) {
        // mark the object to be removed
        self.objects_to_remove.push(uid);
    }

    /// Updates the collision world.
    ///
    /// This executes the whole collision detection pipeline: the broad phase first, then the
    /// narrow phase.
    pub fn update(&mut self) {
        self.perform_position_update();
        self.perform_broad_phase();
        self.perform_narrow_phase();

        // clean up objects that have been marked as removed
        while self.objects_to_remove.len() > 0 {
			let uid = self.objects_to_remove.pop().expect("no uid found to remove");
			// remove objects marked to as removed
			if let Some((fk, _)) = self.objects.remove(uid) {
		        self.broad_phase.defered_remove(fk.uid());
		    }
		}
    }

    /// Sets the position the collision object attached to the specified object will have during
    /// the next update.
    pub fn defered_set_position(&mut self, uid: usize, pos: M) {
        if let Some(fk) = self.objects.get_fast_key(uid) {
            self.pos_to_update.push((fk, pos))
        }
    }

    /// Registers a handler for contact start/stop events.
    pub fn register_contact_signal_handler<H>(&mut self, name: &str, handler: H)
        where H: ContactSignalHandler<T> + 'static {
        self.narrow_phase.register_contact_signal_handler(name, Box::new(handler))
    }

    /// Unregisters a handler for contact start/stop events.
    pub fn unregister_contact_signal_handler(&mut self, name: &str) {
        self.narrow_phase.unregister_contact_signal_handler(name)
    }

    /// Executes the position updates.
    pub fn perform_position_update(&mut self) {
        for &(ref fk, ref pos) in self.pos_to_update.iter() {
            if let Some(co) = self.objects.get_fast_mut(fk) {
                co.position = pos.clone();
                co.timestamp = self.timestamp;
                self.broad_phase.defered_set_bounding_volume(fk.uid(), bounding_volume::aabb(&**co.shape, pos));
            }
        }

        self.pos_to_update.clear();
    }

    /// Executes the broad phase of the collision detection pipeline.
    ///
    /// Not that this does not take in account the changes made to the collision updates after the
    /// last `.perform_position_update()` call.
    pub fn perform_broad_phase(&mut self) {
        let bf = &mut self.broad_phase;
        let nf = &mut self.narrow_phase;
        let objs = &self.objects;

        bf.update(
            &mut |b1, b2| CollisionObjectsDispatcher::is_proximity_allowed(objs, b1, b2),
            &mut |b1, b2, started| nf.handle_proximity(objs, b1, b2, started)
        );
    }

    /// Executes the narrow phase of the collision detection pipeline.
    pub fn perform_narrow_phase(&mut self) {
        self.narrow_phase.update(&self.objects, self.timestamp);
        self.timestamp = self.timestamp + 1;
    }

    /// Iterates through all the contact pairs detected since the last update.
    #[inline]
    pub fn contact_pairs(&self) -> ContactPairs<P, M, T> {
        self.narrow_phase.contact_pairs(&self.objects)
    }

    /// Iterates through every contact detected since the last update.
    #[inline]
    pub fn contacts(&self) -> Contacts<P, M, T> {
        self.narrow_phase.contacts(&self.objects)
    }

    /// Computes the interferences between every rigid bodies on this world and a ray.
    #[inline]
    pub fn interferences_with_ray<'a>(&'a self, ray: &'a Ray<P>, groups: &'a CollisionGroups)
        -> InterferencesWithRay<'a, P, M, T> {
        // FIXME: avoid allocation.
        let mut fks = Vec::new();

        self.broad_phase.interferences_with_ray(ray, &mut fks);

        InterferencesWithRay {
            ray:     ray,
            groups:  groups,
            objects: &self.objects,
            idx:     fks.into_iter()
        }
    }

    /// Computes the interferences between every rigid bodies of a given broad phase, and a point.
    #[inline]
    pub fn interferences_with_point<'a>(&'a self, point: &'a P, groups: &'a CollisionGroups)
        -> InterferencesWithPoint<'a, P, M, T> {
        // FIXME: avoid allocation.
        let mut fks = Vec::new();

        self.broad_phase.interferences_with_point(point, &mut fks);

        InterferencesWithPoint {
            point:   point,
            groups:  groups,
            objects: &self.objects,
            idx:     fks.into_iter()
        }
    }

    /// Computes the interferences between every rigid bodies of a given broad phase, and a aabb.
    #[inline]
    pub fn interferences_with_aabb<'a>(&'a self, aabb: &'a AABB<P>, groups: &'a CollisionGroups)
        -> InterferencesWithAABB<'a, P, M, T> {
        // FIXME: avoid allocation.
        let mut fks = Vec::new();

        self.broad_phase.interferences_with_bounding_volume(aabb, &mut fks);

        InterferencesWithAABB {
            groups:  groups,
            objects: &self.objects,
            idx:     fks.into_iter()
        }
    }
}

/// Iterator through all the objects on the world that intersect a specific ray.
pub struct InterferencesWithRay<'a, P: 'a + Point, M: 'a, T: 'a> {
    ray:     &'a Ray<P>,
    objects: &'a UidRemap<CollisionObject<P, M, T>>,
    groups:  &'a CollisionGroups,
    idx:     IntoIter<&'a FastKey>,
}

impl<'a, P, M, T> Iterator for InterferencesWithRay<'a, P, M, T>
    where P: Point,
          M: Isometry<P, P::Vect> + Translation<P::Vect> {
    type Item = (&'a CollisionObject<P, M, T>, RayIntersection<P::Vect>);

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(id) = self.idx.next() {
            let co = &self.objects[*id];

            if co.collision_groups.can_collide_with_groups(self.groups) {
                let inter = co.shape.toi_and_normal_with_ray(&co.position, self.ray, true);

                if let Some(inter) = inter {
                    return Some((co, inter))
                }
            }
        }

        None
    }
}

/// Iterator through all the objects on the world that intersect a specific point.
pub struct InterferencesWithPoint<'a, P: 'a, M: 'a, T: 'a> {
    point:   &'a P,
    objects: &'a UidRemap<CollisionObject<P, M, T>>,
    groups:  &'a CollisionGroups,
    idx:     IntoIter<&'a FastKey>,
}

impl<'a, P, M, T> Iterator for InterferencesWithPoint<'a, P, M, T>
    where P: Point,
          M: Isometry<P, P::Vect> + Translation<P::Vect> {
    type Item = &'a CollisionObject<P, M, T>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(id) = self.idx.next() {
            let co = &self.objects[*id];

            if co.collision_groups.can_collide_with_groups(self.groups) &&
               co.shape.contains_point(&co.position, self.point) {
                return Some(co)
            }
        }

        None
    }
}

/// Iterator through all the objects on the world which bounding volume intersects a specific AABB.
pub struct InterferencesWithAABB<'a, P: 'a, M: 'a, T: 'a> {
    objects: &'a UidRemap<CollisionObject<P, M, T>>,
    groups:  &'a CollisionGroups,
    idx:     IntoIter<&'a FastKey>,
}

impl<'a, P, M, T> Iterator for InterferencesWithAABB<'a, P, M, T> {
    type Item = &'a CollisionObject<P, M, T>;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(id) = self.idx.next() {
            let co = &self.objects[*id];

            if co.collision_groups.can_collide_with_groups(self.groups) {
                return Some(co)
            }
        }

        None
    }
}

/// 2D collision world containing objects of type `T`.
pub type CollisionWorld2<N, T> = CollisionWorld<Pnt2<N>, Iso2<N>, T>;
/// 3D collision world containing objects of type `T`.
pub type CollisionWorld3<N, T> = CollisionWorld<Pnt3<N>, Iso3<N>, T>;
<|endoftext|>


<commit_before>use libc::{c_uint, c_char, c_uchar};
use std::fmt::{Show, Error, Formatter};
use connection::{mpd_connection, MpdConnection, FromConn};
use error::MpdResult;
use std::str::FromStr;

bitflags! {
    #[deriving(Encodable)]
    #[repr(C)]
    flags MpdEvent: c_uint {
        const DATABASE = 0x1,
        const PLAYLIST = 0x2,
        const QUEUE = 0x4,
        const PLAYER = 0x8,
        const MIXER = 0x10,
        const OUTPUT = 0x20,
        const OPTIONS = 0x40,
        const UPDATE = 0x80,
        const STICKER = 0x100,
        const SUBSCRIPTION = 0x200,
        const MESSAGE = 0x400,
    }
}

impl Show for MpdEvent {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        try!(f.write(b"MpdEvent("));
        let name = unsafe { mpd_idle_name(*self) };
        try!(if name.is_null() {
            self.bits.fmt(f)
        } else {
            unsafe { String::from_raw_buf(name).fmt(f) }
        })
        try!(f.write(b")"));
        Ok(())
    }
}

impl FromStr for MpdEvent {
    fn from_str(s: &str) -> Option<MpdEvent> {
        let ev = s.with_c_str(|s| unsafe { mpd_idle_name_parse(s) });
        if ev.is_empty() {
            None
        } else {
            Some(ev)
        }
    }
}

#[link(name = "mpdclient")]
extern {
    fn mpd_idle_name(idle: MpdEvent) -> *const c_uchar;
    fn mpd_idle_name_parse(name: *const c_char) -> MpdEvent;
    fn mpd_run_idle(connection: *mut mpd_connection) -> MpdEvent;
    fn mpd_run_idle_mask(connection: *mut mpd_connection, mask: MpdEvent) -> MpdEvent;
    fn mpd_run_noidle(connection: *mut mpd_connection) -> bool;
}

pub struct MpdIdle<'a> {
    conn: &'a MpdConnection,
    mask: Option<MpdEvent>
}

impl<'a> Iterator<MpdResult<MpdEvent>> for MpdIdle<'a> {
    fn next(&mut self) -> Option<MpdResult<MpdEvent>> {
        let idle = unsafe {
            match self.mask {
                Some(m) => mpd_run_idle_mask(self.conn.conn, m),
                None => mpd_run_idle(self.conn.conn)
            }
        };

        if idle.is_empty() {
            FromConn::from_conn(self.conn).map(|e| Err(e))
        } else {
            Some(Ok(idle))
        }
    }
}

impl<'a> MpdIdle<'a> {
    pub fn from_conn<'a>(conn: &'a MpdConnection, mask: Option<MpdEvent>) -> MpdIdle<'a> {
        MpdIdle { conn: conn, mask: mask }
    }

    pub fn stop(self) -> MpdResult<()> {
        if unsafe { mpd_run_noidle(self.conn.conn) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }
}

<commit_msg>fix typo<commit_after>use libc::{c_uint, c_char, c_uchar};
use std::fmt::{Show, Error, Formatter};
use connection::{mpd_connection, MpdConnection, FromConn};
use error::MpdResult;
use std::str::FromStr;

bitflags! {
    #[deriving(Encodable)]
    #[repr(C)]
    flags MpdEvent: c_uint {
        const DATABASE = 0x1,
        const PLAYLIST = 0x2,
        const QUEUE = 0x4,
        const PLAYER = 0x8,
        const MIXER = 0x10,
        const OUTPUT = 0x20,
        const OPTIONS = 0x40,
        const UPDATE = 0x80,
        const STICKER = 0x100,
        const SUBSCRIPTION = 0x200,
        const MESSAGE = 0x400,
    }
}

impl Show for MpdEvent {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        try!(f.write(b"MpdEvent("));
        let name = unsafe { mpd_idle_name(*self) };
        try!(if name.is_null() {
            self.bits.fmt(f)
        } else {
            unsafe { String::from_raw_buf(name).fmt(f) }
        });
        try!(f.write(b")"));
        Ok(())
    }
}

impl FromStr for MpdEvent {
    fn from_str(s: &str) -> Option<MpdEvent> {
        let ev = s.with_c_str(|s| unsafe { mpd_idle_name_parse(s) });
        if ev.is_empty() {
            None
        } else {
            Some(ev)
        }
    }
}

#[link(name = "mpdclient")]
extern {
    fn mpd_idle_name(idle: MpdEvent) -> *const c_uchar;
    fn mpd_idle_name_parse(name: *const c_char) -> MpdEvent;
    fn mpd_run_idle(connection: *mut mpd_connection) -> MpdEvent;
    fn mpd_run_idle_mask(connection: *mut mpd_connection, mask: MpdEvent) -> MpdEvent;
    fn mpd_run_noidle(connection: *mut mpd_connection) -> bool;
}

pub struct MpdIdle<'a> {
    conn: &'a MpdConnection,
    mask: Option<MpdEvent>
}

impl<'a> Iterator<MpdResult<MpdEvent>> for MpdIdle<'a> {
    fn next(&mut self) -> Option<MpdResult<MpdEvent>> {
        let idle = unsafe {
            match self.mask {
                Some(m) => mpd_run_idle_mask(self.conn.conn, m),
                None => mpd_run_idle(self.conn.conn)
            }
        };

        if idle.is_empty() {
            FromConn::from_conn(self.conn).map(|e| Err(e))
        } else {
            Some(Ok(idle))
        }
    }
}

impl<'a> MpdIdle<'a> {
    pub fn from_conn<'a>(conn: &'a MpdConnection, mask: Option<MpdEvent>) -> MpdIdle<'a> {
        MpdIdle { conn: conn, mask: mask }
    }

    pub fn stop(self) -> MpdResult<()> {
        if unsafe { mpd_run_noidle(self.conn.conn) } {
            Ok(())
        } else {
            Err(FromConn::from_conn(self.conn).unwrap())
        }
    }
}

<|endoftext|>


<commit_before>#[macro_export]
macro_rules! timeout_tests {
    ( $TestRegion:path ) => {
        use lucet_runtime::vmctx::{lucet_vmctx, Vmctx};
        use lucet_runtime::{
            lucet_hostcall, lucet_hostcall_terminate, DlModule, Error, FaultDetails, Instance,
            KillError, KillSuccess, Limits, Module, Region, RunResult, SignalBehavior,
            TerminationDetails, TrapCode, YieldedVal,
        };
        use nix::sys::mman::{mmap, MapFlags, ProtFlags};
        use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal};
        use nix::sys::wait::{waitpid, WaitStatus};
        use nix::unistd::{fork, ForkResult};
        use std::ptr;
        use std::sync::{Arc, Mutex};
        use std::thread;
        use std::time::Duration;
        use $TestRegion as TestRegion;
        use $crate::build::test_module_c;
        use $crate::helpers::{FunctionPointer, MockExportBuilder, MockModuleBuilder};

        pub fn mock_timeout_module() -> Arc<dyn Module> {
            extern "C" fn onetwothree(_vmctx: *mut lucet_vmctx) -> std::os::raw::c_int {
                123
            }

            extern "C" fn infinite_loop(_vmctx: *mut lucet_vmctx) -> () {
                loop {}
            }

            extern "C" fn do_nothing(_vmctx: *mut lucet_vmctx) -> () {}

            extern "C" fn run_slow_hostcall(vmctx: *mut lucet_vmctx) -> bool {
                extern "C" {
                    fn slow_hostcall(vmctx: *mut lucet_vmctx) -> bool;
                }
                unsafe { slow_hostcall(vmctx) }
            }

            extern "C" fn run_yielding_hostcall(vmctx: *mut lucet_vmctx) -> () {
                extern "C" {
                    fn yielding_hostcall(vmctx: *mut lucet_vmctx) -> ();
                }
                unsafe { yielding_hostcall(vmctx) }
            }

            MockModuleBuilder::new()
                .with_export_func(MockExportBuilder::new(
                    "infinite_loop",
                    FunctionPointer::from_usize(infinite_loop as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "do_nothing",
                    FunctionPointer::from_usize(do_nothing as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "onetwothree",
                    FunctionPointer::from_usize(onetwothree as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "run_slow_hostcall",
                    FunctionPointer::from_usize(run_slow_hostcall as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "run_yielding_hostcall",
                    FunctionPointer::from_usize(run_yielding_hostcall as usize),
                ))
                .build()
        }

        #[lucet_hostcall]
        #[no_mangle]
        pub fn slow_hostcall(vmctx: &mut Vmctx) -> bool {
            // make a window of time so we can timeout in a hostcall
            thread::sleep(Duration::from_millis(200));
            true
        }

        #[lucet_hostcall]
        #[no_mangle]
        pub fn yielding_hostcall(vmctx: &mut Vmctx) {
            vmctx.yield_();
        }

        fn run_onetwothree(inst: &mut Instance) {
            let retval = inst
                .run("onetwothree", &[])
                .expect("instance runs")
                .unwrap_returned();
            assert_eq!(libc::c_int::from(retval), 123);
        }

        #[test]
        fn timeout_in_guest() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            let kill_switch = inst.kill_switch();

            thread::Builder::new()
                .name("helper".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Signalled));
                })
                .expect("can spawn a thread");

            match inst.run("infinite_loop", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {
                    // this is what we want to see
                }
                res => panic!("unexpected result: {:?}", res),
            }

            // after a timeout, can reset and run a normal function
            inst.reset().expect("instance resets");

            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_before_guest() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            let kill_switch = inst.kill_switch();
            assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Cancelled));

            // if terminated before running, the guest should not start at all
            match inst.run("onetwothree", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }
        }

        #[test]
        fn timeout_after_guest() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            match inst.run("do_nothing", &[]) {
                Ok(_) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            let kill_switch = inst.kill_switch();
            assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Cancelled));

            // if terminated after running, the guest should not run again
            match inst.run("onetwothree", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // after a timeout, can still reset and run a normal function
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_after_guest_fault() {
            let module = test_module_c("timeout", "fault.c").expect("build and load module");
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            match inst.run("main", &[0u32.into(), 0u32.into()]) {
                Err(Error::RuntimeFault(details)) => {
                    assert_eq!(details.trapcode, Some(TrapCode::HeapOutOfBounds));
                }
                res => panic!("unexpected result: {:?}", res),
            }

            let kill_switch = inst.kill_switch();
            assert_eq!(kill_switch.terminate(), Err(KillError::NotTerminable));

            // after a timeout, can reset and run a normal function
            inst.reset().expect("instance resets");

            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_in_hostcall() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            let kill_switch = inst.kill_switch();

            thread::Builder::new()
                .name("helper".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Pending));
                })
                .expect("can spawn a thread");

            match inst.run("run_slow_hostcall", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // after a timeout, can reset and run a normal function
            inst.reset().expect("instance resets");

            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_while_yielded() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            let kill_switch = inst.kill_switch();

            thread::Builder::new()
                .name("helper".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Pending));
                })
                .expect("can spawn a thread");

            match inst.run("run_yielding_hostcall", &[]) {
                Ok(RunResult::Yielded(EmptyYieldVal)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            println!("waiting......");

            // wait for the timeout to expire
            thread::sleep(Duration::from_millis(200));

            match inst.resume() {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // after a timeout, can reset and run a normal function
            inst.reset().expect("instance resets");

            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_killswitch_reuse() {
            let module = test_module_c("timeout", "inf_loop.c").expect("build and load module");

            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            let kill_switch = inst.kill_switch();

            let helper = thread::Builder::new()
                .name("helper".to_owned())
                .spawn(move || {
                    // This fires first, and will work properly, terminating the instance.
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Cancelled));
                    // Next, we will delay for 100ms and try to terminate the instance again.
                    // This should fail, because we have already terminated the instance.
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Err(KillError::NotTerminable));
                })
                .expect("can spawn a thread");

            thread::sleep(Duration::from_millis(10));

            match inst.run("main", &[0u32.into(), 0u32.into()]) {
                // the result we're expecting - the guest has been terminated!
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            };

            helper.join().unwrap();
        }

        /// This test ensures that we see a more informative kill error than `NotTerminable` when
        /// attempting to terminate an instance that has been reset since issuing a kill switch.
        #[test]
        fn timeout_after_reset() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();
            inst.reset().expect("instance resets");
            assert_eq!(kill_switch.terminate(), Err(KillError::Invalid));
            run_onetwothree(&mut inst);
        }

        /// This test ensures that we see an `Invalid` kill error if we are attempting to terminate
        /// an instance that has since been dropped.
        #[test]
        fn timeout_after_drop() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();
            std::mem::drop(inst);
            assert_eq!(kill_switch.terminate(), Err(KillError::Invalid));
        }

        #[test]
        fn double_timeout() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            let kill_switch = inst.kill_switch();
            let second_kill_switch = inst.kill_switch();

            let helper_1 = thread::Builder::new()
                .name("helper-1".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Signalled));
                })
                .expect("can spawn a thread");

            let helper_2 = thread::Builder::new()
                .name("helper-2".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(200));
                    assert_eq!(
                        second_kill_switch.terminate(),
                        Err(KillError::NotTerminable)
                    );
                })
                .expect("can spawn a thread");

            match inst.run("infinite_loop", &[]) {
                // the result we're expecting - the guest has been terminated!
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // Check that neither helper thread panicked.
            helper_1.join().expect("helper_1 did not panic");
            helper_2.join().expect("helper_2 did not panic");

            // Check that we can reset the instance and run a function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }
    };
}
<commit_msg>lucet-runtime: polish timeout tests<commit_after>//! Termination tests.
//!
//! This macro tests that instances within some kind of memory region can be terminated properly
//! using a remote kill switch. See
//! [`KillSwitch::terminate`](struct.KillSwitch.html#method.terminate) for more information.
#[macro_export]
macro_rules! timeout_tests {
    ( $TestRegion:path ) => {
        use lucet_runtime::vmctx::{lucet_vmctx, Vmctx};
        use lucet_runtime::{
            lucet_hostcall, lucet_hostcall_terminate, DlModule, Error, FaultDetails, Instance,
            KillError, KillSuccess, Limits, Module, Region, RunResult, SignalBehavior,
            TerminationDetails, TrapCode, YieldedVal,
        };
        use nix::sys::mman::{mmap, MapFlags, ProtFlags};
        use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal};
        use nix::sys::wait::{waitpid, WaitStatus};
        use nix::unistd::{fork, ForkResult};
        use std::ptr;
        use std::sync::{Arc, Mutex};
        use std::thread;
        use std::time::Duration;
        use $TestRegion as TestRegion;
        use $crate::build::test_module_c;
        use $crate::helpers::{FunctionPointer, MockExportBuilder, MockModuleBuilder};

        /// Return a mock module so that we can test termination behavior.
        ///
        /// See `lucet_runtime_internals::module::mock::MockModuleBuilder` for more information.
        pub fn mock_timeout_module() -> Arc<dyn Module> {
            extern "C" fn onetwothree(_vmctx: *mut lucet_vmctx) -> std::os::raw::c_int {
                123
            }

            extern "C" fn infinite_loop(_vmctx: *mut lucet_vmctx) -> () {
                loop {}
            }

            extern "C" fn do_nothing(_vmctx: *mut lucet_vmctx) -> () {}

            extern "C" fn run_slow_hostcall(vmctx: *mut lucet_vmctx) -> bool {
                extern "C" {
                    fn slow_hostcall(vmctx: *mut lucet_vmctx) -> bool;
                }
                unsafe { slow_hostcall(vmctx) }
            }

            extern "C" fn run_yielding_hostcall(vmctx: *mut lucet_vmctx) -> () {
                extern "C" {
                    fn yielding_hostcall(vmctx: *mut lucet_vmctx) -> ();
                }
                unsafe { yielding_hostcall(vmctx) }
            }

            MockModuleBuilder::new()
                .with_export_func(MockExportBuilder::new(
                    "infinite_loop",
                    FunctionPointer::from_usize(infinite_loop as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "do_nothing",
                    FunctionPointer::from_usize(do_nothing as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "onetwothree",
                    FunctionPointer::from_usize(onetwothree as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "run_slow_hostcall",
                    FunctionPointer::from_usize(run_slow_hostcall as usize),
                ))
                .with_export_func(MockExportBuilder::new(
                    "run_yielding_hostcall",
                    FunctionPointer::from_usize(run_yielding_hostcall as usize),
                ))
                .build()
        }

        /// This test hostcall will wait for 200 milliseconds before returning `true`.
        /// This is used to make a window of time so we can timeout inside of a hostcall.
        #[lucet_hostcall]
        #[no_mangle]
        pub fn slow_hostcall(vmctx: &mut Vmctx) -> bool {
            thread::sleep(Duration::from_millis(200));
            true
        }

        /// This test hostcall will immediately yield. This is used to test termination of a
        /// yielded instance.
        #[lucet_hostcall]
        #[no_mangle]
        pub fn yielding_hostcall(vmctx: &mut Vmctx) {
            vmctx.yield_();
        }

        /// A convenience wrapper around running our mock timeout module's `onetwothree` function,
        /// and asserting that it returned the expected result.
        fn run_onetwothree(inst: &mut Instance) {
            let retval = inst
                .run("onetwothree", &[])
                .expect("instance runs")
                .unwrap_returned();
            assert_eq!(libc::c_int::from(retval), 123);
        }

        #[test]
        fn timeout_in_guest() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();

            // Spawn a thread to terminate the instance after waiting for 100ms.
            let t = thread::Builder::new()
                .name("killswitch".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Signalled));
                })
                .expect("can spawn a thread");

            // Begin running the instance, which should be terminated remotely by the KillSwitch.
            match inst.run("infinite_loop", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {
                    // this is what we want to see
                }
                res => panic!("unexpected result: {:?}", res),
            }
            t.join().unwrap();

            // Another attempt to terminate the instance should fail.
            assert_eq!(
                inst.kill_switch().terminate(),
                Err(KillError::NotTerminable)
            );

            // Check that we can reset the instance and run a normal function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_before_guest_runs() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();

            // If terminated before running, the guest will be cancelled.
            assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Cancelled));

            // Another attempt to terminate the instance should fail.
            assert_eq!(
                inst.kill_switch().terminate(),
                Err(KillError::NotTerminable)
            );

            match inst.run("onetwothree", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // Check that we can reset the instance and run a normal function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }

        /// FIXME: This needs a subtle change.
        #[test]
        fn timeout_after_guest_runs() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();

            // The killswitch should fail if the instance has already finished running.
            match inst.run("do_nothing", &[]) {
                Ok(_) => {}
                res => panic!("unexpected result: {:?}", res),
            }
            assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Cancelled)); // FIXME -> Invalid

            // If terminated after running, the guest should not run again.
            match inst.run("onetwothree", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // Check that we can reset the instance and run a normal function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_after_guest_fault() {
            let module = test_module_c("timeout", "fault.c").expect("build and load module");
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();

            // Run the faulting guest.
            match inst.run("main", &[0u32.into(), 0u32.into()]) {
                Err(Error::RuntimeFault(details)) => {
                    assert_eq!(details.trapcode, Some(TrapCode::HeapOutOfBounds));
                }
                res => panic!("unexpected result: {:?}", res),
            }

            // An instance that has faulted is not terminable.
            assert_eq!(kill_switch.terminate(), Err(KillError::NotTerminable));

            // Check that we can reset the instance and run a normal function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_in_hostcall() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();

            // Spawn a thread to terminate the instance after waiting for 100ms.
            thread::Builder::new()
                .name("killswitch".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Pending));
                })
                .expect("can spawn a thread");

            // Begin running the instance, which should be terminated remotely by the KillSwitch
            // while inside a hostcall. See `slow_hostcall` above for more information.
            match inst.run("run_slow_hostcall", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // Another attempt to terminate the instance should fail.
            assert_eq!(
                inst.kill_switch().terminate(),
                Err(KillError::NotTerminable)
            );

            // Check that we can reset the instance and run a normal function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }

        #[test]
        fn timeout_while_yielded() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();

            // Start the instance, running a function that will yield.
            match inst.run("run_yielding_hostcall", &[]) {
                Ok(RunResult::Yielded(EmptyYieldVal)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // A yielded instance can only be scheduled for termination.
            assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Pending));

            // A second attempt to terminate a yielded instance will fail.
            assert_eq!(
                inst.kill_switch().terminate(),
                Err(KillError::NotTerminable)
            );

            // Once resumed, the terminated instance will be terminated.
            match inst.resume() {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // Check that we can reset the instance and run a normal function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }

        /// This test ensures that we see a more informative kill error than `NotTerminable` when
        /// attempting to terminate an instance that has been reset since issuing a kill switch.
        #[test]
        fn timeout_after_guest_reset() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();
            inst.reset().expect("instance resets");
            assert_eq!(kill_switch.terminate(), Err(KillError::Invalid));
            run_onetwothree(&mut inst);
        }

        /// This test ensures that we see an `Invalid` kill error if we are attempting to terminate
        /// an instance that has since been dropped.
        #[test]
        fn timeout_after_guest_drop() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");
            let kill_switch = inst.kill_switch();
            std::mem::drop(inst);
            assert_eq!(kill_switch.terminate(), Err(KillError::Invalid));
        }

        #[test]
        fn double_timeout() {
            let module = mock_timeout_module();
            let region = TestRegion::create(1, &Limits::default()).expect("region can be created");
            let mut inst = region
                .new_instance(module)
                .expect("instance can be created");

            // Spawn a thread to terminate the instance after waiting for 100ms.
            let kill_switch = inst.kill_switch();
            let helper_1 = thread::Builder::new()
                .name("helper-1".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(100));
                    assert_eq!(kill_switch.terminate(), Ok(KillSuccess::Signalled));
                })
                .expect("can spawn a thread");

            // Spawn a thread to terminate the instance after waiting for 200ms.
            let second_kill_switch = inst.kill_switch();
            let helper_2 = thread::Builder::new()
                .name("helper-2".to_owned())
                .spawn(move || {
                    thread::sleep(Duration::from_millis(200));
                    assert_eq!(
                        second_kill_switch.terminate(),
                        Err(KillError::NotTerminable)
                    );
                })
                .expect("can spawn a thread");

            // Start the instance, which should return an error having been remotely terminated.
            match inst.run("infinite_loop", &[]) {
                Err(Error::RuntimeTerminated(TerminationDetails::Remote)) => {}
                res => panic!("unexpected result: {:?}", res),
            }

            // Explicitly check that each helper thread's assertions succeeded.
            helper_1.join().expect("helper_1 did not panic");
            helper_2.join().expect("helper_2 did not panic");

            // Check that we can reset the instance and run a function.
            inst.reset().expect("instance resets");
            run_onetwothree(&mut inst);
        }
    };
}
<|endoftext|>


<commit_before>use graphics::Graphics;
use graphics::character::CharacterCache;
use color::Color;
use point::Point;
use ui_context::UiContext;

pub type FontSize = u32;

/// An enum for passing in label information to widget arguments.
pub enum Labeling<'a> {
    Label(&'a str, FontSize, Color),
    NoLabel,
}

/// Determine the pixel width of the final text bitmap.
#[inline]
pub fn width<C: CharacterCache>(uic: &mut UiContext<C>, size: FontSize, text: &str) -> f64 {
    text.chars().fold(0u32, |a, ch| {
        let character = uic.get_character(size, ch);
        a + character.width() as u32
    }) as f64
}

/// Determine a suitable FontSize from a given rectangle height.
#[inline]
pub fn auto_size_from_rect_height(rect_height: f64) -> FontSize {
    let size = rect_height as u32 - 832;
    if size % 2 == 0 { size } else { size - 1u32 }
}

/// A trait used for widget types that take a label.
pub trait Labelable<'a> {
    fn label(self, text: &'a str) -> Self;
    fn label_color(self, color: Color) -> Self;
    fn label_rgba(self, r: f32, g: f32, b: f32, a: f32) -> Self;
    fn label_font_size(self, size: FontSize) -> Self;
    fn small_font<C>(self, uic: &UiContext<C>) -> Self;
    fn medium_font<C>(self, uic: &UiContext<C>) -> Self;
    fn large_font<C>(self, uic: &UiContext<C>) -> Self;
}

/// Label text property.
#[derive(Copy, Clone)]
pub struct LabelText<'a>(pub &'a str);

/// Label color property.
#[derive(Copy, Clone)]
pub struct LabelColor(pub Color);

/// Label font size property.
#[derive(Copy, Clone)]
pub struct LabelFontSize(pub FontSize);

/*
impl<'a, T: 'a> Labelable<'a> for T
    where
        (LabelText<'a>, T): Pair<Data = LabelText<'a>, Object = T> + SetAt,
        (LabelColor, T): Pair<Data = LabelColor, Object = T> + SetAt,
        (LabelFontSize, T): Pair<Data = LabelFontSize, Object = T> + SetAt
{
    fn label(self, text: &'a str) -> Self {
        self.set(LabelText(text))
    }

    fn label_color(self, color: Color) -> Self {
        self.set(LabelColor(color))
    }

    fn label_rgba(self, r: f32, g: f32, b: f32, a: f32) -> Self {
        self.set(LabelColor(Color([r, g, b, a])))
    }

    fn label_font_size(self, size: FontSize) -> Self {
        self.set(LabelFontSize(size))
    }

    fn small_font<C>(self, uic: &UiContext<C>) -> Self {
        self.set(LabelFontSize(uic.theme.font_size_small))
    }

    fn medium_font<C>(self, uic: &UiContext<C>) -> Self {
        self.set(LabelFontSize(uic.theme.font_size_medium))
    }

    fn large_font<C>(self, uic: &UiContext<C>) -> Self {
        self.set(LabelFontSize(uic.theme.font_size_large))
    }
}
*/

/// A context on which the builder pattern can be implemented.
pub struct Label<'a> {
    text: &'a str,
    pos: Point,
    size: FontSize,
    maybe_color: Option<Color>,
}

impl<'a> Label<'a> {
    /// A builder method for specifying font_size.
    pub fn size(self, size: FontSize) -> Label<'a> {
        Label { size: size, ..self }
    }
}

impl<'a> Label<'a> {

    /// A label builder method to be implemented on the UiContext.
    pub fn new(text: &'a str) -> Label<'a> {
        Label {
            text: text,
            pos: [0.0, 0.0],
            size: 24u32,
            maybe_color: None,
        }
    }

}

/*
quack! {
    label: Label['a]
    get:
    set:
        fn (val: Color) [] { label.maybe_color = Some(val) }
        fn (val: Position) [] { label.pos = val.0 }
    action:
}
*/

impl<'a> ::draw::Drawable for Label<'a> {
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let color = self.maybe_color.unwrap_or(Color::black());
        uic.draw_text(graphics, self.pos, self.size, color, self.text);
    }
}
<commit_msg>Implemented `Colorable` for `Label`<commit_after>use graphics::Graphics;
use graphics::character::CharacterCache;
use color::{ Color, Colorable };
use point::Point;
use ui_context::UiContext;

pub type FontSize = u32;

/// An enum for passing in label information to widget arguments.
pub enum Labeling<'a> {
    Label(&'a str, FontSize, Color),
    NoLabel,
}

/// Determine the pixel width of the final text bitmap.
#[inline]
pub fn width<C: CharacterCache>(uic: &mut UiContext<C>, size: FontSize, text: &str) -> f64 {
    text.chars().fold(0u32, |a, ch| {
        let character = uic.get_character(size, ch);
        a + character.width() as u32
    }) as f64
}

/// Determine a suitable FontSize from a given rectangle height.
#[inline]
pub fn auto_size_from_rect_height(rect_height: f64) -> FontSize {
    let size = rect_height as u32 - 832;
    if size % 2 == 0 { size } else { size - 1u32 }
}

/// A trait used for widget types that take a label.
pub trait Labelable<'a> {
    fn label(self, text: &'a str) -> Self;
    fn label_color(self, color: Color) -> Self;
    fn label_rgba(self, r: f32, g: f32, b: f32, a: f32) -> Self;
    fn label_font_size(self, size: FontSize) -> Self;
    fn small_font<C>(self, uic: &UiContext<C>) -> Self;
    fn medium_font<C>(self, uic: &UiContext<C>) -> Self;
    fn large_font<C>(self, uic: &UiContext<C>) -> Self;
}

/// Label text property.
#[derive(Copy, Clone)]
pub struct LabelText<'a>(pub &'a str);

/// Label color property.
#[derive(Copy, Clone)]
pub struct LabelColor(pub Color);

/// Label font size property.
#[derive(Copy, Clone)]
pub struct LabelFontSize(pub FontSize);

/*
impl<'a, T: 'a> Labelable<'a> for T
    where
        (LabelText<'a>, T): Pair<Data = LabelText<'a>, Object = T> + SetAt,
        (LabelColor, T): Pair<Data = LabelColor, Object = T> + SetAt,
        (LabelFontSize, T): Pair<Data = LabelFontSize, Object = T> + SetAt
{
    fn label(self, text: &'a str) -> Self {
        self.set(LabelText(text))
    }

    fn label_color(self, color: Color) -> Self {
        self.set(LabelColor(color))
    }

    fn label_rgba(self, r: f32, g: f32, b: f32, a: f32) -> Self {
        self.set(LabelColor(Color([r, g, b, a])))
    }

    fn label_font_size(self, size: FontSize) -> Self {
        self.set(LabelFontSize(size))
    }

    fn small_font<C>(self, uic: &UiContext<C>) -> Self {
        self.set(LabelFontSize(uic.theme.font_size_small))
    }

    fn medium_font<C>(self, uic: &UiContext<C>) -> Self {
        self.set(LabelFontSize(uic.theme.font_size_medium))
    }

    fn large_font<C>(self, uic: &UiContext<C>) -> Self {
        self.set(LabelFontSize(uic.theme.font_size_large))
    }
}
*/

/// A context on which the builder pattern can be implemented.
pub struct Label<'a> {
    text: &'a str,
    pos: Point,
    size: FontSize,
    maybe_color: Option<Color>,
}

impl<'a> Label<'a> {
    /// A builder method for specifying font_size.
    pub fn size(self, size: FontSize) -> Label<'a> {
        Label { size: size, ..self }
    }
}

impl<'a> Label<'a> {

    /// A label builder method to be implemented on the UiContext.
    pub fn new(text: &'a str) -> Label<'a> {
        Label {
            text: text,
            pos: [0.0, 0.0],
            size: 24u32,
            maybe_color: None,
        }
    }

}

impl<'a> Colorable for Label<'a> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

/*
quack! {
    label: Label['a]
    get:
    set:
        fn (val: Position) [] { label.pos = val.0 }
    action:
}
*/

impl<'a> ::draw::Drawable for Label<'a> {
    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {
        let color = self.maybe_color.unwrap_or(Color::black());
        uic.draw_text(graphics, self.pos, self.size, color, self.text);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

use gtk::Inhibit;

#[doc(hidden)]
pub trait IntoOption<T> {
    #[doc(hidden)]
    fn into_option(self) -> Option<T>;
}

impl<T> IntoOption<T> for Option<T> {
    fn into_option(self) -> Option<T> {
        self
    }
}

impl<T> IntoOption<T> for () {
    fn into_option(self) -> Option<T> {
        None
    }
}

#[doc(hidden)]
pub trait IntoPair<A, B> {
    #[doc(hidden)]
    fn into_pair(self) -> (A, B);
}

impl<A> IntoPair<Option<A>, Inhibit> for Inhibit {
    fn into_pair(self) -> (Option<A>, Inhibit) {
        (None, self)
    }
}

impl<A, B> IntoPair<A, B> for (A, B) {
    fn into_pair(self) -> (A, B) {
        self
    }
}
<commit_msg>Generalize the IntoPair impl<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#[doc(hidden)]
pub trait IntoOption<T> {
    #[doc(hidden)]
    fn into_option(self) -> Option<T>;
}

impl<T> IntoOption<T> for Option<T> {
    fn into_option(self) -> Option<T> {
        self
    }
}

impl<T> IntoOption<T> for () {
    fn into_option(self) -> Option<T> {
        None
    }
}

#[doc(hidden)]
pub trait IntoPair<A, B> {
    #[doc(hidden)]
    fn into_pair(self) -> (A, B);
}

impl<A, B> IntoPair<Option<A>, B> for B {
    fn into_pair(self) -> (Option<A>, B) {
        (None, self)
    }
}

impl<A, B> IntoPair<A, B> for (A, B) {
    fn into_pair(self) -> (A, B) {
        self
    }
}
<|endoftext|>


<commit_before>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
    Subslice { base: Arc<[u8]>, offset: usize, len: usize },
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    /// Create a subslice of this `IVec` that shares
    /// the same backing data and reference counter.
    ///
    /// # Panics
    ///
    /// Panics if `self.len() - offset >= len`.
    ///
    /// # Examples
    /// ```
    /// # use sled::IVec;
    /// let iv = IVec::from(vec![1]);
    /// let subslice = iv.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = subslice.subslice(0, 0);
    /// assert_eq!(&subslice, &[]);
    ///
    /// let iv2 = IVec::from(vec![1, 2, 3]);
    /// let subslice = iv2.subslice(3, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = iv2.subslice(2, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = iv2.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = iv2.subslice(0, 3);
    /// assert_eq!(&subslice, &[1, 2, 3]);
    /// let subslice = subslice.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = subslice.subslice(1, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// ```
    pub fn subslice(&self, slice_offset: usize, len: usize) -> Self {
        assert!(self.len().checked_sub(slice_offset).unwrap() >= len);

        let inner = match self.0 {
            IVecInner::Remote(ref base) => IVecInner::Subslice {
                base: base.clone(),
                offset: slice_offset,
                len,
            },
            IVecInner::Inline(_, old_inner) => {
                // old length already checked above in assertion
                let mut new_inner = Inner::default();
                new_inner[..len].copy_from_slice(
                    &old_inner[slice_offset..slice_offset + len],
                );

                IVecInner::Inline(u8::try_from(len).unwrap(), new_inner)
            }
            IVecInner::Subslice { ref base, ref offset, .. } => {
                IVecInner::Subslice {
                    base: base.clone(),
                    offset: offset + slice_offset,
                    len,
                }
            }
        };

        IVec(inner)
    }

    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));
        let mut data = Inner::default();
        data[..slice.len()].copy_from_slice(slice);
        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            IVecInner::Subslice { ref mut base, offset, len }
                if Arc::strong_count(base) != 1 =>
            {
                self.0 = IVecInner::Remote(
                    base[offset..offset + len].to_vec().into(),
                );
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
            IVecInner::Subslice { .. } => self.deref().into(),
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
            IVecInner::Subslice { ref base, offset, len } => {
                &base[*offset..*offset + *len]
            }
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match &mut self.0 {
            IVecInner::Inline(ref sz, ref mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
            IVecInner::Subslice { ref mut base, offset, len } => {
                &mut Arc::get_mut(base).unwrap()[*offset..*offset + *len]
            }
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

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

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
#[should_panic]
fn subslice_usage_00() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(0, 4);
}

#[test]
#[should_panic]
fn subslice_usage_01() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(3, 1);
}

#[test]
fn ivec_as_mut_identity() {
    let initial = &[1];
    let mut iv = IVec::from(initial);
    assert_eq!(&*initial, &*iv);
    assert_eq!(&*initial, &mut *iv);
    assert_eq!(&*initial, iv.as_mut());
}

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

    fn prop_identity(ivec: &IVec) -> bool {
        let mut iv2 = ivec.clone();

        if iv2 != ivec {
            println!("expected clone to equal original");
            return false;
        }

        if *ivec != *iv2 {
            println!("expected AsMut to equal original");
            return false;
        }

        if *ivec != iv2.as_mut() {
            println!("expected AsMut to equal original");
            return false;
        }

        true
    }

    quickcheck::quickcheck! {
        #[cfg_attr(miri, ignore)]
        fn bool(item: IVec) -> bool {
            prop_identity(&item)
        }
    }
}
<commit_msg>implement `From<&String>` for `IVec` (#1199)<commit_after>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
    Subslice { base: Arc<[u8]>, offset: usize, len: usize },
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    /// Create a subslice of this `IVec` that shares
    /// the same backing data and reference counter.
    ///
    /// # Panics
    ///
    /// Panics if `self.len() - offset >= len`.
    ///
    /// # Examples
    /// ```
    /// # use sled::IVec;
    /// let iv = IVec::from(vec![1]);
    /// let subslice = iv.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = subslice.subslice(0, 0);
    /// assert_eq!(&subslice, &[]);
    ///
    /// let iv2 = IVec::from(vec![1, 2, 3]);
    /// let subslice = iv2.subslice(3, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = iv2.subslice(2, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = iv2.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = iv2.subslice(0, 3);
    /// assert_eq!(&subslice, &[1, 2, 3]);
    /// let subslice = subslice.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = subslice.subslice(1, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// ```
    pub fn subslice(&self, slice_offset: usize, len: usize) -> Self {
        assert!(self.len().checked_sub(slice_offset).unwrap() >= len);

        let inner = match self.0 {
            IVecInner::Remote(ref base) => IVecInner::Subslice {
                base: base.clone(),
                offset: slice_offset,
                len,
            },
            IVecInner::Inline(_, old_inner) => {
                // old length already checked above in assertion
                let mut new_inner = Inner::default();
                new_inner[..len].copy_from_slice(
                    &old_inner[slice_offset..slice_offset + len],
                );

                IVecInner::Inline(u8::try_from(len).unwrap(), new_inner)
            }
            IVecInner::Subslice { ref base, ref offset, .. } => {
                IVecInner::Subslice {
                    base: base.clone(),
                    offset: offset + slice_offset,
                    len,
                }
            }
        };

        IVec(inner)
    }

    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));
        let mut data = Inner::default();
        data[..slice.len()].copy_from_slice(slice);
        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            IVecInner::Subslice { ref mut base, offset, len }
                if Arc::strong_count(base) != 1 =>
            {
                self.0 = IVecInner::Remote(
                    base[offset..offset + len].to_vec().into(),
                );
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&String> for IVec {
    fn from(s: &String) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

from_array!(
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
);

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
            IVecInner::Subslice { .. } => self.deref().into(),
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
            IVecInner::Subslice { ref base, offset, len } => {
                &base[*offset..*offset + *len]
            }
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match &mut self.0 {
            IVecInner::Inline(ref sz, ref mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
            IVecInner::Subslice { ref mut base, offset, len } => {
                &mut Arc::get_mut(base).unwrap()[*offset..*offset + *len]
            }
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

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

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
#[should_panic]
fn subslice_usage_00() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(0, 4);
}

#[test]
#[should_panic]
fn subslice_usage_01() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(3, 1);
}

#[test]
fn ivec_as_mut_identity() {
    let initial = &[1];
    let mut iv = IVec::from(initial);
    assert_eq!(&*initial, &*iv);
    assert_eq!(&*initial, &mut *iv);
    assert_eq!(&*initial, iv.as_mut());
}

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

    fn prop_identity(ivec: &IVec) -> bool {
        let mut iv2 = ivec.clone();

        if iv2 != ivec {
            println!("expected clone to equal original");
            return false;
        }

        if *ivec != *iv2 {
            println!("expected AsMut to equal original");
            return false;
        }

        if *ivec != iv2.as_mut() {
            println!("expected AsMut to equal original");
            return false;
        }

        true
    }

    quickcheck::quickcheck! {
        #[cfg_attr(miri, ignore)]
        fn bool(item: IVec) -> bool {
            prop_identity(&item)
        }
    }
}
<|endoftext|>


<commit_before>#[path="../src/configuration.rs"]
mod configuration;

#[path="../src/file.rs"]
mod file;

#[test]
fn test_returns_configuration_with_empty_list_of_packages() {
    let yaml_file = "
    default:
        packages:
    ";
    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.packages.is_empty(), true);
}

#[test]
fn test_returns_configuration_with_list_of_packages() {
    let yaml_file = "
    default:
      packages:
        - vim
        - git
        - build-essential
    ";

    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.packages, vec!["vim", "git", "build-essential"]);
}

#[test]
fn test_returns_configuration_with_install_command() {
    let yaml_file = "
    default:
      packages:
        - vim
        - git
      package_install_cmd: apt-get install -y
      ";
    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.install_command, Some("apt-get install -y".to_string()));
}

#[test]
fn test_returns_configuration_without_install_command() {
    let yaml_file = "
    default:
      packages:
        - vim
        - git
  ";
  let configuration = configuration::from_yaml(yaml_file.to_string());
  assert_eq!(configuration.install_command, None);

}

#[test]
fn test_returns_configuration_with_a_file_resource() {
    let yaml_file = "
    default:
      files:
        -
          path: '/home/Jane/hello.txt'
          content: 'Hi from John'
    ";

    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.files.len(), 1);
}

#[test]
fn test_returns_configuration_with_a_file_resource_has_all_properties() {
    let yaml_file = "
    default:
      files:
        -
          path: '/home/Jane/hello.txt'
          content: 'Hi from John'
    ";

    let configuration = configuration::from_yaml(yaml_file.to_string());
    let file = configuration.files.first().unwrap();
    assert_eq!(file.path, "/home/Jane/hello.txt");
    assert_eq!(file.content, "Hi from John");
}

#[test]
fn test_valid_configuration() {
    let configuration = configuration::Configuration {
        packages: vec![],
        files: vec![file::FileResource{
            path: "/home/john/hello.txt".to_string(),
            content: "hello".to_string()
        }],
        install_command: Some("yum install -y".to_string())
    };

    assert_eq!(configuration.is_valid(), true);
}
<commit_msg>Add testcase for invalid configuration<commit_after>#[path="../src/configuration.rs"]
mod configuration;

#[path="../src/file.rs"]
mod file;

#[test]
fn test_returns_configuration_with_empty_list_of_packages() {
    let yaml_file = "
    default:
        packages:
    ";
    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.packages.is_empty(), true);
}

#[test]
fn test_returns_configuration_with_list_of_packages() {
    let yaml_file = "
    default:
      packages:
        - vim
        - git
        - build-essential
    ";

    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.packages, vec!["vim", "git", "build-essential"]);
}

#[test]
fn test_returns_configuration_with_install_command() {
    let yaml_file = "
    default:
      packages:
        - vim
        - git
      package_install_cmd: apt-get install -y
      ";
    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.install_command, Some("apt-get install -y".to_string()));
}

#[test]
fn test_returns_configuration_without_install_command() {
    let yaml_file = "
    default:
      packages:
        - vim
        - git
  ";
  let configuration = configuration::from_yaml(yaml_file.to_string());
  assert_eq!(configuration.install_command, None);

}

#[test]
fn test_returns_configuration_with_a_file_resource() {
    let yaml_file = "
    default:
      files:
        -
          path: '/home/Jane/hello.txt'
          content: 'Hi from John'
    ";

    let configuration = configuration::from_yaml(yaml_file.to_string());
    assert_eq!(configuration.files.len(), 1);
}

#[test]
fn test_returns_configuration_with_a_file_resource_has_all_properties() {
    let yaml_file = "
    default:
      files:
        -
          path: '/home/Jane/hello.txt'
          content: 'Hi from John'
    ";

    let configuration = configuration::from_yaml(yaml_file.to_string());
    let file = configuration.files.first().unwrap();
    assert_eq!(file.path, "/home/Jane/hello.txt");
    assert_eq!(file.content, "Hi from John");
}

#[test]
fn test_valid_configuration() {
    let configuration = configuration::Configuration {
        packages: vec![],
        files: vec![file::FileResource{
            path: "/home/john/hello.txt".to_string(),
            content: "hello".to_string()
        }],
        install_command: Some("yum install -y".to_string())
    };

    assert_eq!(configuration.is_valid(), true);
}

#[test]
fn test_invalid_configuration() {
    let configuration = configuration::Configuration {
        packages: vec![],
        files: vec![file::FileResource{
            path: "/home/john/hello.txt".to_string(),
            content: "hello".to_string()
        }],
        install_command: None
    };

    assert_eq!(configuration.is_valid(), false);
}
<|endoftext|>


<commit_before>#![feature(box_syntax)]

// A unit struct without resources
#[derive(Debug, Copy)]
struct Nil;

// A tuple struct with resources that implements the `Clone` trait
#[derive(Clone,Debug)]
struct Pair(Box<i32>, Box<i32>);

fn main() {
    // Instantiate `Nil`
    let nil = Nil;
    // Copy `Nil`, there are no resources to move
    let copied_nil = nil;

    // Both `Nil`s can be used independently
    println!("original: {:?}", nil);
    println!("copy: {:?}", copied_nil);

    // Instantiate a `Pair`
    let pair = Pair(box 1, box 2);
    println!("original: {:?}", pair);

    // Copy `pair` into `moved_pair`, moves resources
    let moved_pair = pair;
    println!("copy: {:?}", moved_pair);

    // Error! `pair` has lost it resources
    //println!("original: {}", pair);
    // TODO ^ Try uncommenting this line

    // "Clone" `moved_pair` into `cloned_pair` (resources included)
    let cloned_pair = moved_pair.clone();

    // `Drop` the original pair
    drop(moved_pair);

    // Error! `moved_pair` has been `drop`ed
    //println!("copy: {}", moved_pair);
    // TODO ^ Try uncommenting this line

    // Clone can still be used
    println!("clone: {:?}", cloned_pair);
}
<commit_msg>clone: Use newer Box syntax and Debug trait for printing<commit_after>#![feature(box_syntax)]

// A unit struct without resources
#[derive(Debug, Copy)]
struct Nil;

// A tuple struct with resources that implements the `Clone` trait
#[derive(Clone,Debug)]
struct Pair(Box<i32>, Box<i32>);

fn main() {
    // Instantiate `Nil`
    let nil = Nil;
    // Copy `Nil`, there are no resources to move
    let copied_nil = nil;

    // Both `Nil`s can be used independently
    println!("original: {:?}", nil);
    println!("copy: {:?}", copied_nil);

    // Instantiate a `Pair`
    let pair = Pair(Box::new(1), Box::new(2));
    println!("original: {:?}", pair);

    // Copy `pair` into `moved_pair`, moves resources
    let moved_pair = pair;
    println!("copy: {:?}", moved_pair);

    // Error! `pair` has lost it resources
    println!("original: {:?}", pair);
    // TODO ^ Try uncommenting this line

    // "Clone" `moved_pair` into `cloned_pair` (resources included)
    let cloned_pair = moved_pair.clone();

    // `Drop` the original pair
    drop(moved_pair);

    // Error! `moved_pair` has been `drop`ed
    //println!("copy: {}", moved_pair);
    // TODO ^ Try uncommenting this line

    // Clone can still be used
    println!("clone: {:?}", cloned_pair);
}
<|endoftext|>


<commit_before>/*
extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };
    let mut gl = gitlab::GitLab::new(&hostname, &token);
    gl.set_pagination(gitlab::Pagination {
        page: 1,
        per_page: 100,
    });
    println!("gl: {:?}", gl);

    // let groups = gl.groups(Default::default());
    let groups = gl.groups(gitlab::groups::Listing::new().skip_groups(vec![1, 2, 3]).clone());
    println!("groups: {:?}", groups);

    let owned_groups = gl.owned_groups();
    println!("owned_groups: {:?}", owned_groups);
}
*/

fn main() {
    println!("Groups disabled until API stabilizes. See projects instead.");
}
<commit_msg>Re-enabled `list_groups` example<commit_after>extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let mut gl = gitlab::GitLab::new(&hostname, &token);
    gl.set_pagination(gitlab::Pagination {
        page: 1,
        per_page: 100,
    });
    println!("gl: {:?}", gl);

    let groups = gl.groups().list();
    println!("groups: {:?}", groups);

    // let groups = gl.groups(gitlab::groups::Listing::new().skip_groups(vec![1, 2, 3]).clone());
    // println!("groups: {:?}", groups);
    //
    // let owned_groups = gl.owned_groups();
    // println!("owned_groups: {:?}", owned_groups);
}
<|endoftext|>


<commit_before>//! Special x86_64 instructions.

pub mod interrupts;
pub mod port;
pub mod segmentation;
pub mod tables;
pub mod tlb;
<commit_msg>Add int3 instruction<commit_after>//! Special x86_64 instructions.

pub mod interrupts;
pub mod port;
pub mod segmentation;
pub mod tables;
pub mod tlb;

/// Cause a breakpoint exception by invoking the `int3` instruction.
pub fn int3() {
    unsafe {
        asm!("int3");
    }
}<|endoftext|>