<commit_before>use std::default::{Default};
use std::cmp::{min, max};
use std::num::{zero};
use image::{GenericImage, Pixel, ImageBuf, Rgba};
use geom::{V2, Rect};
use rgb::Rgb;

/// Set alpha channel to transparent if pixels have a specific color.
pub fn color_key<P: Pixel<u8>, I: GenericImage<P>>(
    image: &I, color: &Rgb) -> ImageBuf<Rgba<u8>> {
    let (w, h) = image.dimensions();
    let pixels = image.pixels().map(|(_, _, p)| {
            let (pr, pg, pb, mut pa) = p.channels4();
            if pr == color.r && pg == color.g && pb == color.b {
                pa = Default::default();
            }
            Pixel::from_channels(pr, pg, pb, pa)
        }).collect();
    ImageBuf::from_pixels(pixels, w, h)
}

/// Return the rectangle enclosing the parts of the image that aren't fully
/// transparent.
pub fn crop_alpha<T: Primitive+Default, P: Pixel<T>, I: GenericImage<P>>(
    image: &I) -> Rect<int> {
    let (w, h) = image.dimensions();
    let mut p1 = V2(w as int, h as int);
    let mut p2 = V2(0i, 0i);
    let transparent: T = Default::default();
    for y in range(0, h as int) {
        for x in range(0, w as int) {
            let (_, _, _, a) = image.get_pixel(x as u32, y as u32).channels4();
            if a != transparent {
                p1.0 = min(x, p1.0);
                p2.0 = max(x + 1, p2.0);
                p1.1 = min(y, p1.1);
                p2.1 = max(y + 1, p2.1);
            }
        }
    }

    if p1.0 > p2.0 { Rect(V2(0, 0), V2(0, 0)) } // Empty image.
    else { Rect(p1, p2 - p1) }
}

pub fn blit<T: Primitive+Default, P: Pixel<T>, I: GenericImage<P>, J: GenericImage<P>> (
    image: &I, target: &mut J, offset: V2<int>) {
    let (w, h) = image.dimensions();
    // TODO: Check for going over bounds.
    for y in range(0, h) {
        for x in range(0, w) {
            target.put_pixel(x + offset.0 as u32, y + offset.1 as u32, image.get_pixel(x, y));
        }
    }
}

/// Try to pack several small rectangles into one large rectangle. Return
/// offsets for the subrectangles within the container if a packing was found.
pub fn pack_rectangles<T: Primitive+Ord+Clone>(
    container_dim: V2<T>,
    dims: &Vec<V2<T>>)
    -> Option<Vec<V2<T>>> {
    let total_area = dims.iter().map(|dim| dim.0 * dim.1).fold(zero::<T>(), |a, b| a + b);

    // Too much rectangle area to fit in container no matter how you pack it.
    // Fail early.
    if total_area > container_dim.0 * container_dim.1 { return None; }

    // Take enumeration to keep the original indices around.
    let mut largest_first : Vec<(uint, &V2<T>)> = dims.iter().enumerate().collect();
    largest_first.sort_by(|&(_i, a), &(_j, b)| (b.0 * b.1).cmp(&(a.0 * a.1)));

    let mut slots = vec![Rect(V2(zero::<T>(), zero::<T>()), container_dim)];

    let mut ret = Vec::from_elem(dims.len(), V2(zero::<T>(), zero::<T>()));

    for i in range(0, largest_first.len()) {
        let (idx, &dim) = largest_first[i];
        match place(dim, &mut slots) {
            Some(pos) => { *ret.get_mut(idx) = pos; }
            None => { return None; }
        }
    }

    return Some(ret);

    ////////////////////////////////////////////////////////////////////////

    /// Find the smallest slot in the slot vector that will fit the given
    /// item.
    fn place<T: Primitive+Ord>(
        dim: V2<T>, slots: &mut Vec<Rect<T>>) -> Option<V2<T>> {
        for i in range(0, slots.len()) {
            // XXX: Can't use [] indexing on slot because it's mut.
            let &Rect(slot_pos, slot_dim) = slots.get_mut(i);
            if fits(dim, slot_dim) {
                // Remove the original slot, it gets the item. Add the two new
                // rectangles that form around the item.
                let (new_1, new_2) = remaining_rects(dim, Rect(slot_pos, slot_dim));
                slots.swap_remove(i);
                slots.push(new_1);
                slots.push(new_2);
                // Sort by area from smallest to largest.
                slots.sort_by(|&a, &b| a.area().cmp(&b.area()));
                return Some(slot_pos);
            }
        }
        None
    }

    /// Return the two remaining parts of container rect when the dim-sized
    /// item is placed in the top left corner.
    fn remaining_rects<T: Primitive+Ord>(
        dim: V2<T>, Rect(rect_pos, rect_dim): Rect<T>) ->
        (Rect<T>, Rect<T>) {
        assert!(fits(dim, rect_dim));

        // Choose between making a vertical or a horizontal split
        // based on which leaves a bigger open rectangle.
        let vert_vol = max(rect_dim.0 * (rect_dim.1 - dim.1),
            (rect_dim.0 - dim.0) * dim.1);
        let horiz_vol = max(dim.0 * (rect_dim.1 - dim.1),
            (rect_dim.0 - dim.0) * rect_dim.1);

        if vert_vol > horiz_vol {
            //     |AA
            // ----+--
            // BBBBBBB
            // BBBBBBB
            (Rect(V2(rect_pos.0 + dim.0, rect_pos.1), V2(rect_dim.0 - dim.0, dim.1)),
             Rect(V2(rect_pos.0, rect_pos.1 + dim.1), V2(rect_dim.0, rect_dim.1 - dim.1)))
        } else {
            //     |BB
            // ----+BB
            // AAAA|BB
            // AAAA|BB
            (Rect(V2(rect_pos.0, rect_pos.1 + dim.1), V2(dim.0, rect_dim.1 - dim.1)),
             Rect(V2(rect_pos.0 + dim.0, rect_pos.1), V2(rect_dim.0 - dim.0, rect_dim.1)))
        }
    }

    fn fits<T: Ord>(dim: V2<T>, container_dim: V2<T>) -> bool {
        dim.0 <= container_dim.0 && dim.1 <= container_dim.1
    }
}

/*
#[cfg(test)]
mod tests {
    use std::fmt::Show;
    use image::{Rgba, ImageBuf, GenericImage};
    use util;

    #[test]
    fn test_zero_atlas() {
        let empty: Vec<ImageBuf<Rgba<u8>>> = vec![];
        let (canvas, rects) = util::build_atlas(&empty);
        assert!(rects.len() == 0);
    }

    #[test]
    fn test_atlas() {
        let images: Vec<ImageBuf<Rgba<u8>>> = vec![
            ImageBuf::new(6, 4),
            ImageBuf::new(8, 10),
            ImageBuf::new(3, 3),
        ];
        let (canvas, rects) = util::build_atlas(&images);
        assert!(rects.len() == images.len());
        assert!(canvas.dimensions() == (16, 16));
        // Filling the rect starts from top left, and the biggest item goes
        // first.
        rects_equal(&rects.1, &([0, 0], [8, 10]));
        // The next rect goes below the first one since there is a smaller
        // space there.
        rects_equal(&rects.0, &([0, 10], [6, 4]));
        rects_equal(&rects[2], &([8, 0], [3, 3]));
    }

    // XXX: can't compare fixed arrays naively.
    fn rects_equal<T: Primitive+Show>(
        &(ref p1, ref d1): &(V2<T>, V2<T>),
        &(ref p2, ref d2): &(V2<T>, V2<T>)) {
        let (p1, p2, d1, d2) = (
            p1.as_slice(), p2.as_slice(),
            d1.as_slice(), d2.as_slice());
        println!("{}, {}", p1, p2);
        println!("{}, {}", d1, d2);
        assert!(p1 == p2);
        assert!(d1 == d2);
    }
}
*/
<commit_msg>Remove commented out code<commit_after>use std::default::{Default};
use std::cmp::{min, max};
use std::num::{zero};
use image::{GenericImage, Pixel, ImageBuf, Rgba};
use geom::{V2, Rect};
use rgb::Rgb;

/// Set alpha channel to transparent if pixels have a specific color.
pub fn color_key<P: Pixel<u8>, I: GenericImage<P>>(
    image: &I, color: &Rgb) -> ImageBuf<Rgba<u8>> {
    let (w, h) = image.dimensions();
    let pixels = image.pixels().map(|(_, _, p)| {
            let (pr, pg, pb, mut pa) = p.channels4();
            if pr == color.r && pg == color.g && pb == color.b {
                pa = Default::default();
            }
            Pixel::from_channels(pr, pg, pb, pa)
        }).collect();
    ImageBuf::from_pixels(pixels, w, h)
}

/// Return the rectangle enclosing the parts of the image that aren't fully
/// transparent.
pub fn crop_alpha<T: Primitive+Default, P: Pixel<T>, I: GenericImage<P>>(
    image: &I) -> Rect<int> {
    let (w, h) = image.dimensions();
    let mut p1 = V2(w as int, h as int);
    let mut p2 = V2(0i, 0i);
    let transparent: T = Default::default();
    for y in range(0, h as int) {
        for x in range(0, w as int) {
            let (_, _, _, a) = image.get_pixel(x as u32, y as u32).channels4();
            if a != transparent {
                p1.0 = min(x, p1.0);
                p2.0 = max(x + 1, p2.0);
                p1.1 = min(y, p1.1);
                p2.1 = max(y + 1, p2.1);
            }
        }
    }

    if p1.0 > p2.0 { Rect(V2(0, 0), V2(0, 0)) } // Empty image.
    else { Rect(p1, p2 - p1) }
}

pub fn blit<T: Primitive+Default, P: Pixel<T>, I: GenericImage<P>, J: GenericImage<P>> (
    image: &I, target: &mut J, offset: V2<int>) {
    let (w, h) = image.dimensions();
    // TODO: Check for going over bounds.
    for y in range(0, h) {
        for x in range(0, w) {
            target.put_pixel(x + offset.0 as u32, y + offset.1 as u32, image.get_pixel(x, y));
        }
    }
}

/// Try to pack several small rectangles into one large rectangle. Return
/// offsets for the subrectangles within the container if a packing was found.
pub fn pack_rectangles<T: Primitive+Ord+Clone>(
    container_dim: V2<T>,
    dims: &Vec<V2<T>>)
    -> Option<Vec<V2<T>>> {
    let total_area = dims.iter().map(|dim| dim.0 * dim.1).fold(zero::<T>(), |a, b| a + b);

    // Too much rectangle area to fit in container no matter how you pack it.
    // Fail early.
    if total_area > container_dim.0 * container_dim.1 { return None; }

    // Take enumeration to keep the original indices around.
    let mut largest_first : Vec<(uint, &V2<T>)> = dims.iter().enumerate().collect();
    largest_first.sort_by(|&(_i, a), &(_j, b)| (b.0 * b.1).cmp(&(a.0 * a.1)));

    let mut slots = vec![Rect(V2(zero::<T>(), zero::<T>()), container_dim)];

    let mut ret = Vec::from_elem(dims.len(), V2(zero::<T>(), zero::<T>()));

    for i in range(0, largest_first.len()) {
        let (idx, &dim) = largest_first[i];
        match place(dim, &mut slots) {
            Some(pos) => { *ret.get_mut(idx) = pos; }
            None => { return None; }
        }
    }

    return Some(ret);

    ////////////////////////////////////////////////////////////////////////

    /// Find the smallest slot in the slot vector that will fit the given
    /// item.
    fn place<T: Primitive+Ord>(
        dim: V2<T>, slots: &mut Vec<Rect<T>>) -> Option<V2<T>> {
        for i in range(0, slots.len()) {
            // XXX: Can't use [] indexing on slot because it's mut.
            let &Rect(slot_pos, slot_dim) = slots.get_mut(i);
            if fits(dim, slot_dim) {
                // Remove the original slot, it gets the item. Add the two new
                // rectangles that form around the item.
                let (new_1, new_2) = remaining_rects(dim, Rect(slot_pos, slot_dim));
                slots.swap_remove(i);
                slots.push(new_1);
                slots.push(new_2);
                // Sort by area from smallest to largest.
                slots.sort_by(|&a, &b| a.area().cmp(&b.area()));
                return Some(slot_pos);
            }
        }
        None
    }

    /// Return the two remaining parts of container rect when the dim-sized
    /// item is placed in the top left corner.
    fn remaining_rects<T: Primitive+Ord>(
        dim: V2<T>, Rect(rect_pos, rect_dim): Rect<T>) ->
        (Rect<T>, Rect<T>) {
        assert!(fits(dim, rect_dim));

        // Choose between making a vertical or a horizontal split
        // based on which leaves a bigger open rectangle.
        let vert_vol = max(rect_dim.0 * (rect_dim.1 - dim.1),
            (rect_dim.0 - dim.0) * dim.1);
        let horiz_vol = max(dim.0 * (rect_dim.1 - dim.1),
            (rect_dim.0 - dim.0) * rect_dim.1);

        if vert_vol > horiz_vol {
            //     |AA
            // ----+--
            // BBBBBBB
            // BBBBBBB
            (Rect(V2(rect_pos.0 + dim.0, rect_pos.1), V2(rect_dim.0 - dim.0, dim.1)),
             Rect(V2(rect_pos.0, rect_pos.1 + dim.1), V2(rect_dim.0, rect_dim.1 - dim.1)))
        } else {
            //     |BB
            // ----+BB
            // AAAA|BB
            // AAAA|BB
            (Rect(V2(rect_pos.0, rect_pos.1 + dim.1), V2(dim.0, rect_dim.1 - dim.1)),
             Rect(V2(rect_pos.0 + dim.0, rect_pos.1), V2(rect_dim.0 - dim.0, rect_dim.1)))
        }
    }

    fn fits<T: Ord>(dim: V2<T>, container_dim: V2<T>) -> bool {
        dim.0 <= container_dim.0 && dim.1 <= container_dim.1
    }
}
<|endoftext|>


<commit_before>
/// Rounding modes for round()
#[derive(Copy,Clone,Debug,PartialEq)]
pub enum Rounding {
    Up(f32),
    Down(f32),
    Half(f32),
    None,
}

/// Round f64 with Rounding mode
pub fn round(seconds: f64, rounding: Rounding) -> f64 {
    let res = match rounding {
        Rounding::Up(r) => (seconds / r as f64).ceil() * r as f64,
        Rounding::Down(r) => (seconds / r as f64).floor() * r as f64,
        Rounding::Half(r) => (seconds / r as f64).round() * r as f64,
        Rounding::None => seconds,
    };
    // don't return NaN
    if res.is_nan() { seconds } else { res }
}

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

    #[test]
    fn round_up_test() {
        const TIME_ACTUAL: f64 = 38160.12345; // ~10:36am in seconds
        const TIME_UP: f64 = 38700.0; // 10:45am in seconds
        const TIME_DOWN: f64 = 37800.0; // 10:30am in seconds

        // round up
        let res = round(TIME_ACTUAL, Rounding::Up(900.0));
        assert_eq!(res, TIME_UP);
        let res = round(TIME_UP, Rounding::Up(900.0));
        assert_eq!(res, TIME_UP);
        let res = round(TIME_UP - 1.0, Rounding::Up(900.0));
        assert_eq!(res, TIME_UP);

        // round down
        let res = round(TIME_ACTUAL, Rounding::Down(900.0));
        assert_eq!(res, TIME_DOWN);
        let res = round(TIME_DOWN, Rounding::Down(900.0));
        assert_eq!(res, TIME_DOWN);
        let res = round(TIME_DOWN + 1.0, Rounding::Down(900.0));
        assert_eq!(res, TIME_DOWN);

        // round half
        let res = round(TIME_ACTUAL, Rounding::Half(900.0));
        assert_eq!(res, TIME_DOWN);
        let res = round(TIME_DOWN, Rounding::Half(900.0));
        assert_eq!(res, TIME_DOWN);

        // round to 1/4 sec
        let res = round(TIME_ACTUAL, Rounding::Up(0.25));
        assert_eq!(res, 38160.25);

        // round with zero
        let res = round(TIME_ACTUAL, Rounding::Up(0.0));
        assert_eq!(res, TIME_ACTUAL);

        // round None
        let res = round(TIME_ACTUAL, Rounding::None);
        assert_eq!(res, TIME_ACTUAL);

    }
}
<commit_msg>Cleaned up tests in util.rs<commit_after>
/// Rounding modes for round()
#[derive(Copy,Clone,Debug,PartialEq)]
pub enum Rounding {
    Up(f32),
    Down(f32),
    Half(f32),
    None,
}

/// Round f64 with Rounding mode
pub fn round(seconds: f64, rounding: Rounding) -> f64 {
    let res = match rounding {
        Rounding::Up(r) => (seconds / r as f64).ceil() * r as f64,
        Rounding::Down(r) => (seconds / r as f64).floor() * r as f64,
        Rounding::Half(r) => (seconds / r as f64).round() * r as f64,
        Rounding::None => seconds,
    };
    // don't return NaN
    if res.is_nan() { seconds } else { res }
}

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

    const TIME_ACTUAL: f64 = 38160.12345; // ~10:36am in seconds
    const TIME_UP: f64 = 38700.0; // 10:45am in seconds
    const TIME_DOWN: f64 = 37800.0; // 10:30am in seconds

    #[test]
    fn round_up_test() {
        // round up
        let res = round(TIME_ACTUAL, Rounding::Up(900.0));
        assert_eq!(res, TIME_UP);
        let res = round(TIME_UP, Rounding::Up(900.0));
        assert_eq!(res, TIME_UP);
        let res = round(TIME_UP - 1.0, Rounding::Up(900.0));
        assert_eq!(res, TIME_UP);
    }

    #[test]
    fn round_down_test() {
        // round down
        let res = round(TIME_ACTUAL, Rounding::Down(900.0));
        assert_eq!(res, TIME_DOWN);
        let res = round(TIME_DOWN, Rounding::Down(900.0));
        assert_eq!(res, TIME_DOWN);
        let res = round(TIME_DOWN + 1.0, Rounding::Down(900.0));
        assert_eq!(res, TIME_DOWN);
    }

    #[test]
    fn round_half_test() {
        // round half
        let res = round(TIME_ACTUAL, Rounding::Half(900.0));
        assert_eq!(res, TIME_DOWN);
        let res = round(TIME_DOWN, Rounding::Half(900.0));
        assert_eq!(res, TIME_DOWN);
    }

    #[test]
    fn round_quarter_test() {
        // round to 1/4 sec
        let res = round(TIME_ACTUAL, Rounding::Up(0.25));
        assert_eq!(res, 38160.25);
    }

    #[test]
    fn round_zero_test() {
        // round with zero
        let res = round(TIME_ACTUAL, Rounding::Up(0.0));
        assert_eq!(res, TIME_ACTUAL);
    }

    #[test]
    fn round_none_test() {
        // round None
        let res = round(TIME_ACTUAL, Rounding::None);
        assert_eq!(res, TIME_ACTUAL);

    }
}
<|endoftext|>


<commit_before>use super::batch_semaphore as ll; // low level implementation
use std::sync::Arc;

/// Counting semaphore performing asynchronous permit acquisition.
///
/// A semaphore maintains a set of permits. Permits are used to synchronize
/// access to a shared resource. A semaphore differs from a mutex in that it
/// can allow more than one concurrent caller to access the shared resource at a
/// time.
///
/// When `acquire` is called and the semaphore has remaining permits, the
/// function immediately returns a permit. However, if no remaining permits are
/// available, `acquire` (asynchronously) waits until an outstanding permit is
/// dropped. At this point, the freed permit is assigned to the caller.
#[derive(Debug)]
pub struct Semaphore {
    /// The low level semaphore
    ll_sem: ll::Semaphore,
}

/// A permit from the semaphore.
///
/// This type is created by the [`acquire`] method.
///
/// [`acquire`]: crate::sync::Semaphore::acquire()
#[must_use]
#[derive(Debug)]
pub struct SemaphorePermit<'a> {
    sem: &'a Semaphore,
    permits: u16,
}

/// An owned permit from the semaphore.
///
/// This type is created by the [`acquire_owned`] method.
///
/// [`acquire_owned`]: crate::sync::Semaphore::acquire_owned()
#[must_use]
#[derive(Debug)]
pub struct OwnedSemaphorePermit {
    sem: Arc<Semaphore>,
    permits: u16,
}

/// Error returned from the [`Semaphore::try_acquire`] function.
///
/// A `try_acquire` operation can only fail if the semaphore has no available
/// permits.
///
/// [`Semaphore::try_acquire`]: Semaphore::try_acquire
#[derive(Debug)]
pub struct TryAcquireError(());

#[test]
#[cfg(not(loom))]
fn bounds() {
    fn check_unpin<T: Unpin>() {}
    // This has to take a value, since the async fn's return type is unnameable.
    fn check_send_sync_val<T: Send + Sync>(_t: T) {}
    fn check_send_sync<T: Send + Sync>() {}
    check_unpin::<Semaphore>();
    check_unpin::<SemaphorePermit<'_>>();
    check_send_sync::<Semaphore>();

    let semaphore = Semaphore::new(0);
    check_send_sync_val(semaphore.acquire());
}

impl Semaphore {
    /// Creates a new semaphore with the initial number of permits.
    pub fn new(permits: usize) -> Self {
        Self {
            ll_sem: ll::Semaphore::new(permits),
        }
    }

    /// Creates a new semaphore with the initial number of permits.
    #[cfg(all(feature = "parking_lot", not(all(loom, test))))]
    #[cfg_attr(docsrs, doc(cfg(feature = "parking_lot")))]
    pub const fn const_new(permits: usize) -> Self {
        Self {
            ll_sem: ll::Semaphore::const_new(permits),
        }
    }

    /// Returns the current number of available permits.
    pub fn available_permits(&self) -> usize {
        self.ll_sem.available_permits()
    }

    /// Adds `n` new permits to the semaphore.
    ///
    /// The maximum number of permits is `usize::MAX >> 3`, and this function will panic if the limit is exceeded.
    pub fn add_permits(&self, n: usize) {
        self.ll_sem.release(n);
    }

    /// Acquires permit from the semaphore.
    pub async fn acquire(&self) -> SemaphorePermit<'_> {
        self.ll_sem.acquire(1).await.unwrap();
        SemaphorePermit {
            sem: &self,
            permits: 1,
        }
    }

    /// Tries to acquire a permit from the semaphore.
    pub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError> {
        match self.ll_sem.try_acquire(1) {
            Ok(_) => Ok(SemaphorePermit {
                sem: self,
                permits: 1,
            }),
            Err(_) => Err(TryAcquireError(())),
        }
    }

    /// Acquires permit from the semaphore.
    ///
    /// The semaphore must be wrapped in an [`Arc`] to call this method.
    ///
    /// [`Arc`]: std::sync::Arc
    pub async fn acquire_owned(self: Arc<Self>) -> OwnedSemaphorePermit {
        self.ll_sem.acquire(1).await.unwrap();
        OwnedSemaphorePermit {
            sem: self,
            permits: 1,
        }
    }

    /// Tries to acquire a permit from the semaphore.
    ///
    /// The semaphore must be wrapped in an [`Arc`] to call this method.
    ///
    /// [`Arc`]: std::sync::Arc
    pub fn try_acquire_owned(self: Arc<Self>) -> Result<OwnedSemaphorePermit, TryAcquireError> {
        match self.ll_sem.try_acquire(1) {
            Ok(_) => Ok(OwnedSemaphorePermit {
                sem: self,
                permits: 1,
            }),
            Err(_) => Err(TryAcquireError(())),
        }
    }
}

impl<'a> SemaphorePermit<'a> {
    /// Forgets the permit **without** releasing it back to the semaphore.
    /// This can be used to reduce the amount of permits available from a
    /// semaphore.
    pub fn forget(mut self) {
        self.permits = 0;
    }
}

impl OwnedSemaphorePermit {
    /// Forgets the permit **without** releasing it back to the semaphore.
    /// This can be used to reduce the amount of permits available from a
    /// semaphore.
    pub fn forget(mut self) {
        self.permits = 0;
    }
}

impl<'a> Drop for SemaphorePermit<'_> {
    fn drop(&mut self) {
        self.sem.add_permits(self.permits as usize);
    }
}

impl Drop for OwnedSemaphorePermit {
    fn drop(&mut self) {
        self.sem.add_permits(self.permits as usize);
    }
}
<commit_msg>sync: add acquire_many and try_acquire_many to `Sempahore` (#3067)<commit_after>use super::batch_semaphore as ll; // low level implementation
use std::sync::Arc;

/// Counting semaphore performing asynchronous permit acquisition.
///
/// A semaphore maintains a set of permits. Permits are used to synchronize
/// access to a shared resource. A semaphore differs from a mutex in that it
/// can allow more than one concurrent caller to access the shared resource at a
/// time.
///
/// When `acquire` is called and the semaphore has remaining permits, the
/// function immediately returns a permit. However, if no remaining permits are
/// available, `acquire` (asynchronously) waits until an outstanding permit is
/// dropped. At this point, the freed permit is assigned to the caller.
#[derive(Debug)]
pub struct Semaphore {
    /// The low level semaphore
    ll_sem: ll::Semaphore,
}

/// A permit from the semaphore.
///
/// This type is created by the [`acquire`] method.
///
/// [`acquire`]: crate::sync::Semaphore::acquire()
#[must_use]
#[derive(Debug)]
pub struct SemaphorePermit<'a> {
    sem: &'a Semaphore,
    permits: u32,
}

/// An owned permit from the semaphore.
///
/// This type is created by the [`acquire_owned`] method.
///
/// [`acquire_owned`]: crate::sync::Semaphore::acquire_owned()
#[must_use]
#[derive(Debug)]
pub struct OwnedSemaphorePermit {
    sem: Arc<Semaphore>,
    permits: u32,
}

/// Error returned from the [`Semaphore::try_acquire`] function.
///
/// A `try_acquire` operation can only fail if the semaphore has no available
/// permits.
///
/// [`Semaphore::try_acquire`]: Semaphore::try_acquire
#[derive(Debug)]
pub struct TryAcquireError(());

#[test]
#[cfg(not(loom))]
fn bounds() {
    fn check_unpin<T: Unpin>() {}
    // This has to take a value, since the async fn's return type is unnameable.
    fn check_send_sync_val<T: Send + Sync>(_t: T) {}
    fn check_send_sync<T: Send + Sync>() {}
    check_unpin::<Semaphore>();
    check_unpin::<SemaphorePermit<'_>>();
    check_send_sync::<Semaphore>();

    let semaphore = Semaphore::new(0);
    check_send_sync_val(semaphore.acquire());
}

impl Semaphore {
    /// Creates a new semaphore with the initial number of permits.
    pub fn new(permits: usize) -> Self {
        Self {
            ll_sem: ll::Semaphore::new(permits),
        }
    }

    /// Creates a new semaphore with the initial number of permits.
    #[cfg(all(feature = "parking_lot", not(all(loom, test))))]
    #[cfg_attr(docsrs, doc(cfg(feature = "parking_lot")))]
    pub const fn const_new(permits: usize) -> Self {
        Self {
            ll_sem: ll::Semaphore::const_new(permits),
        }
    }

    /// Returns the current number of available permits.
    pub fn available_permits(&self) -> usize {
        self.ll_sem.available_permits()
    }

    /// Adds `n` new permits to the semaphore.
    ///
    /// The maximum number of permits is `usize::MAX >> 3`, and this function will panic if the limit is exceeded.
    pub fn add_permits(&self, n: usize) {
        self.ll_sem.release(n);
    }

    /// Acquires permit from the semaphore.
    pub async fn acquire(&self) -> SemaphorePermit<'_> {
        self.ll_sem.acquire(1).await.unwrap();
        SemaphorePermit {
            sem: &self,
            permits: 1,
        }
    }

    /// Acquires `n` permits from the semaphore
    pub async fn acquire_many(&self, n: u32) -> SemaphorePermit<'_> {
        self.ll_sem.acquire(n).await.unwrap();
        SemaphorePermit {
            sem: &self,
            permits: n,
        }
    }

    /// Tries to acquire a permit from the semaphore.
    pub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError> {
        match self.ll_sem.try_acquire(1) {
            Ok(_) => Ok(SemaphorePermit {
                sem: self,
                permits: 1,
            }),
            Err(_) => Err(TryAcquireError(())),
        }
    }

    /// Tries to acquire `n` permits from the semaphore.
    pub fn try_acquire_many(&self, n: u32) -> Result<SemaphorePermit<'_>, TryAcquireError> {
        match self.ll_sem.try_acquire(n) {
            Ok(_) => Ok(SemaphorePermit {
                sem: self,
                permits: n,
            }),
            Err(_) => Err(TryAcquireError(())),
        }
    }

    /// Acquires permit from the semaphore.
    ///
    /// The semaphore must be wrapped in an [`Arc`] to call this method.
    ///
    /// [`Arc`]: std::sync::Arc
    pub async fn acquire_owned(self: Arc<Self>) -> OwnedSemaphorePermit {
        self.ll_sem.acquire(1).await.unwrap();
        OwnedSemaphorePermit {
            sem: self,
            permits: 1,
        }
    }

    /// Tries to acquire a permit from the semaphore.
    ///
    /// The semaphore must be wrapped in an [`Arc`] to call this method.
    ///
    /// [`Arc`]: std::sync::Arc
    pub fn try_acquire_owned(self: Arc<Self>) -> Result<OwnedSemaphorePermit, TryAcquireError> {
        match self.ll_sem.try_acquire(1) {
            Ok(_) => Ok(OwnedSemaphorePermit {
                sem: self,
                permits: 1,
            }),
            Err(_) => Err(TryAcquireError(())),
        }
    }
}

impl<'a> SemaphorePermit<'a> {
    /// Forgets the permit **without** releasing it back to the semaphore.
    /// This can be used to reduce the amount of permits available from a
    /// semaphore.
    pub fn forget(mut self) {
        self.permits = 0;
    }
}

impl OwnedSemaphorePermit {
    /// Forgets the permit **without** releasing it back to the semaphore.
    /// This can be used to reduce the amount of permits available from a
    /// semaphore.
    pub fn forget(mut self) {
        self.permits = 0;
    }
}

impl<'a> Drop for SemaphorePermit<'_> {
    fn drop(&mut self) {
        self.sem.add_permits(self.permits as usize);
    }
}

impl Drop for OwnedSemaphorePermit {
    fn drop(&mut self) {
        self.sem.add_permits(self.permits as usize);
    }
}
<|endoftext|>


<commit_before>//! Handle network connections for a varlink service

use std::io;
use std::io::{Error, ErrorKind, Read, Write};
use std::thread;
use std::net::{Shutdown, TcpListener, TcpStream};
// FIXME: abstract unix domains sockets still not in std
// FIXME: https://github.com/rust-lang/rust/issues/14194
use unix_socket::UnixListener as AbstractUnixListener;
use std::fs;
use std::env;
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::time::Duration;

//#![feature(getpid)]
//use std::process;
// FIXME
use libc::getpid;

enum VarlinkListener {
    TCP(TcpListener),
    UNIX(UnixListener),
}

enum VarlinkStream {
    TCP(TcpStream),
    UNIX(UnixStream),
}

impl<'a> VarlinkStream {
    pub fn split(&mut self) -> io::Result<(Box<Read + Send + Sync>, Box<Write + Send + Sync>)> {
        match *self {
            VarlinkStream::TCP(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
            VarlinkStream::UNIX(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
        }
    }
    pub fn shutdown(&mut self) -> io::Result<()> {
        match *self {
            VarlinkStream::TCP(ref mut s) => s.shutdown(Shutdown::Both),
            VarlinkStream::UNIX(ref mut s) => s.shutdown(Shutdown::Both),
        }
    }
}

fn activation_listener() -> io::Result<Option<UnixListener>> {
    /*
	FIXME: only working on nightly https://github.com/rust-lang/rust/pull/45059
*/

    let spid = env::var("LISTEN_PID");
    if let Ok(pid) = spid {
        //FIXME:
        //let mypid = process::id();
        unsafe {
            let mypid = getpid();
            match pid.parse::<i32>() {
                Ok(p) => if p != mypid {
                    return Ok(None);
                },
                _ => return Ok(None),
            }
        }
    } else {
        return Ok(None);
    }
    let snfds = env::var("LISTEN_FDS");
    if let Ok(nfds) = snfds {
        match nfds.parse::<u32>() {
            Ok(1) => {}
            _ => return Ok(None),
        }
    } else {
        return Ok(None);
    }
    unsafe {
        //syscall.CloseOnExec(3)
        let listener = UnixListener::from_raw_fd(3);
        env::remove_var("LISTEN_PID");
        env::remove_var("LISTEN_FDS");

        Ok(Some(listener))
    }
}

//FIXME: add Drop with shutdown() and unix file removal
impl VarlinkListener {
    pub fn new(address: &str) -> io::Result<Self> {
        if let Some(l) = activation_listener()? {
            return Ok(VarlinkListener::UNIX(l));
        }

        if address.starts_with("tcp:") {
            Ok(VarlinkListener::TCP(TcpListener::bind(&address[4..])?))
        } else if address.starts_with("unix:") {
            let mut addr = String::from(address[5..].split(";").next().unwrap());
            if addr.starts_with("@") {
                addr = addr.replacen("@", "\0", 1);
                let l = AbstractUnixListener::bind(addr)?;
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(
                        l.into_raw_fd(),
                    )));
                }
            }
            // ignore error on non-existant file
            let _ = fs::remove_file(addr.clone());
            Ok(VarlinkListener::UNIX(UnixListener::bind(addr)?))
        } else {
            Err(Error::new(ErrorKind::Other, "unknown varlink address"))
        }
    }

    pub fn accept(&self) -> io::Result<VarlinkStream> {
        match self {
            &VarlinkListener::TCP(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::TCP(s))
            }
            &VarlinkListener::UNIX(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::UNIX(s))
            }
        }
    }
    pub fn set_nonblocking(&self, b: bool) -> io::Result<()> {
        match self {
            &VarlinkListener::TCP(ref l) => l.set_nonblocking(b),
            &VarlinkListener::UNIX(ref l) => l.set_nonblocking(b),
        }
    }
}

enum Message {
    NewJob(Job),
    Terminate,
}

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Job = Box<FnBox + Send + 'static>;

impl ThreadPool {
    /// Create a new ThreadPool.
    ///
    /// The size is the number of threads in the pool.
    ///
    /// # Panics
    ///
    /// The `new` function will panic if the size is zero.
    pub fn new(size: usize) -> ThreadPool {
        assert!(size > 0);

        let (sender, receiver) = mpsc::channel();

        let receiver = Arc::new(Mutex::new(receiver));

        let mut workers = Vec::with_capacity(size);

        for _ in 0..size {
            workers.push(Worker::new(Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }

    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);

        self.sender.send(Message::NewJob(job)).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &mut self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }

        for worker in &mut self.workers {
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

struct Worker {
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new(receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let message = receiver.lock().unwrap().recv().unwrap();

            match message {
                Message::NewJob(job) => {
                    job.call_box();
                }
                Message::Terminate => {
                    break;
                }
            }
        });

        Worker {
            thread: Some(thread),
        }
    }
}

pub enum ServerError {
    IoError(Error),
    AcceptTimeout,
}

impl From<Error> for ServerError {
    fn from(e: Error) -> Self {
        ServerError::IoError(e)
    }
}

pub fn do_listen(
    service: ::VarlinkService,
    addr: &str,
    workers: usize,
    accept_timeout: u64,
) -> Result<(), ServerError> {
    let service = Arc::new(service);
    let listener = Arc::new(VarlinkListener::new(addr)?);
    listener.set_nonblocking(false)?;
    let pool = ThreadPool::new(workers);

    loop {
        let mut stream: VarlinkStream;
        if accept_timeout != 0 {
            let listener = listener.clone();
            let (sender, receiver) = mpsc::channel();
            let _t = thread::spawn(move || {
                match sender.send(listener.accept()) {
                    Ok(()) => {} // everything good
                    Err(_) => {} // we have been released, don't panic
                }
            });

            stream = match receiver.recv_timeout(Duration::from_secs(accept_timeout)) {
                Ok(s) => s?,
                Err(_) => return Err(ServerError::AcceptTimeout),
            };
        } else {
            stream = listener.accept()?;
        }
        let service = service.clone();
        pool.execute(move || {
            let (mut r, mut w) = stream.split().expect("Could not split stream");
            if let Err(_e) = service.handle(&mut r, &mut w) {
                //println!("Handle Error: {}", e);
                let _ = stream.shutdown();
            }
        });
    }
}
<commit_msg>simplify<commit_after>//! Handle network connections for a varlink service

use std::io;
use std::io::{Error, ErrorKind, Read, Write};
use std::thread;
use std::net::{Shutdown, TcpListener, TcpStream};
// FIXME: abstract unix domains sockets still not in std
// FIXME: https://github.com/rust-lang/rust/issues/14194
use unix_socket::UnixListener as AbstractUnixListener;
use std::fs;
use std::env;
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::net::{UnixListener, UnixStream};
use std::sync::mpsc;
use std::sync::{Arc, Mutex};
use std::time::Duration;

//#![feature(getpid)]
//use std::process;
// FIXME
use libc::getpid;

enum VarlinkListener {
    TCP(TcpListener),
    UNIX(UnixListener),
}

enum VarlinkStream {
    TCP(TcpStream),
    UNIX(UnixStream),
}

impl<'a> VarlinkStream {
    pub fn split(&mut self) -> io::Result<(Box<Read + Send + Sync>, Box<Write + Send + Sync>)> {
        match *self {
            VarlinkStream::TCP(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
            VarlinkStream::UNIX(ref mut s) => {
                Ok((Box::new(s.try_clone()?), Box::new(s.try_clone()?)))
            }
        }
    }
    pub fn shutdown(&mut self) -> io::Result<()> {
        match *self {
            VarlinkStream::TCP(ref mut s) => s.shutdown(Shutdown::Both),
            VarlinkStream::UNIX(ref mut s) => s.shutdown(Shutdown::Both),
        }
    }
}

fn activation_listener() -> io::Result<Option<UnixListener>> {
    /*
	FIXME: only working on nightly https://github.com/rust-lang/rust/pull/45059
*/

    let spid = env::var("LISTEN_PID");
    if let Ok(pid) = spid {
        //FIXME:
        //let mypid = process::id();
        unsafe {
            let mypid = getpid();
            match pid.parse::<i32>() {
                Ok(p) => if p != mypid {
                    return Ok(None);
                },
                _ => return Ok(None),
            }
        }
    } else {
        return Ok(None);
    }
    let snfds = env::var("LISTEN_FDS");
    if let Ok(nfds) = snfds {
        match nfds.parse::<u32>() {
            Ok(1) => {}
            _ => return Ok(None),
        }
    } else {
        return Ok(None);
    }
    unsafe {
        //syscall.CloseOnExec(3)
        let listener = UnixListener::from_raw_fd(3);
        env::remove_var("LISTEN_PID");
        env::remove_var("LISTEN_FDS");

        Ok(Some(listener))
    }
}

//FIXME: add Drop with shutdown() and unix file removal
impl VarlinkListener {
    pub fn new(address: &str) -> io::Result<Self> {
        if let Some(l) = activation_listener()? {
            return Ok(VarlinkListener::UNIX(l));
        }

        if address.starts_with("tcp:") {
            Ok(VarlinkListener::TCP(TcpListener::bind(&address[4..])?))
        } else if address.starts_with("unix:") {
            let mut addr = String::from(address[5..].split(";").next().unwrap());
            if addr.starts_with("@") {
                addr = addr.replacen("@", "\0", 1);
                let l = AbstractUnixListener::bind(addr)?;
                unsafe {
                    return Ok(VarlinkListener::UNIX(UnixListener::from_raw_fd(
                        l.into_raw_fd(),
                    )));
                }
            }
            // ignore error on non-existant file
            let _ = fs::remove_file(&*addr);
            Ok(VarlinkListener::UNIX(UnixListener::bind(addr)?))
        } else {
            Err(Error::new(ErrorKind::Other, "unknown varlink address"))
        }
    }

    pub fn accept(&self) -> io::Result<VarlinkStream> {
        match self {
            &VarlinkListener::TCP(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::TCP(s))
            }
            &VarlinkListener::UNIX(ref l) => {
                let (mut s, _addr) = l.accept()?;
                Ok(VarlinkStream::UNIX(s))
            }
        }
    }
    pub fn set_nonblocking(&self, b: bool) -> io::Result<()> {
        match self {
            &VarlinkListener::TCP(ref l) => l.set_nonblocking(b),
            &VarlinkListener::UNIX(ref l) => l.set_nonblocking(b),
        }
    }
}

enum Message {
    NewJob(Job),
    Terminate,
}

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Message>,
}

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Job = Box<FnBox + Send + 'static>;

impl ThreadPool {
    /// Create a new ThreadPool.
    ///
    /// The size is the number of threads in the pool.
    ///
    /// # Panics
    ///
    /// The `new` function will panic if the size is zero.
    pub fn new(size: usize) -> ThreadPool {
        assert!(size > 0);

        let (sender, receiver) = mpsc::channel();

        let receiver = Arc::new(Mutex::new(receiver));

        let mut workers = Vec::with_capacity(size);

        for _ in 0..size {
            workers.push(Worker::new(Arc::clone(&receiver)));
        }

        ThreadPool { workers, sender }
    }

    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);

        self.sender.send(Message::NewJob(job)).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &mut self.workers {
            self.sender.send(Message::Terminate).unwrap();
        }

        for worker in &mut self.workers {
            if let Some(thread) = worker.thread.take() {
                thread.join().unwrap();
            }
        }
    }
}

struct Worker {
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new(receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
        let thread = thread::spawn(move || loop {
            let message = receiver.lock().unwrap().recv().unwrap();

            match message {
                Message::NewJob(job) => {
                    job.call_box();
                }
                Message::Terminate => {
                    break;
                }
            }
        });

        Worker {
            thread: Some(thread),
        }
    }
}

pub enum ServerError {
    IoError(Error),
    AcceptTimeout,
}

impl From<Error> for ServerError {
    fn from(e: Error) -> Self {
        ServerError::IoError(e)
    }
}

pub fn do_listen(
    service: ::VarlinkService,
    addr: &str,
    workers: usize,
    accept_timeout: u64,
) -> Result<(), ServerError> {
    let service = Arc::new(service);
    let listener = Arc::new(VarlinkListener::new(addr)?);
    listener.set_nonblocking(false)?;
    let pool = ThreadPool::new(workers);

    loop {
        let mut stream: VarlinkStream;
        if accept_timeout != 0 {
            let listener = listener.clone();
            let (sender, receiver) = mpsc::channel();
            let _t = thread::spawn(move || {
                match sender.send(listener.accept()) {
                    Ok(()) => {} // everything good
                    Err(_) => {} // we have been released, don't panic
                }
            });

            stream = match receiver.recv_timeout(Duration::from_secs(accept_timeout)) {
                Ok(s) => s?,
                Err(_) => return Err(ServerError::AcceptTimeout),
            };
        } else {
            stream = listener.accept()?;
        }
        let service = service.clone();
        pool.execute(move || {
            let (mut r, mut w) = stream.split().expect("Could not split stream");
            if let Err(_e) = service.handle(&mut r, &mut w) {
                //println!("Handle Error: {}", e);
                let _ = stream.shutdown();
            }
        });
    }
}
<|endoftext|>


<commit_before>use futures::sync::mpsc::{self, Sender};
use godcoin::{blockchain::ReindexOpts, net::*, prelude::*};
use log::{error, info, warn};
use std::{io::Cursor, net::SocketAddr, path::PathBuf, sync::Arc};
use tokio::{net::TcpListener, prelude::*};
use tokio_tungstenite::tungstenite::{protocol, Message};

mod block_range;
mod forever;
pub mod minter;
pub mod pool;

pub mod prelude {
    pub use super::minter::*;
    pub use super::pool::SubscriptionPool;
}

use block_range::AsyncBlockRange;
use prelude::*;

pub struct ServerOpts {
    pub blocklog_loc: PathBuf,
    pub index_loc: PathBuf,
    pub minter_key: KeyPair,
    pub bind_addr: String,
    pub reindex: Option<ReindexOpts>,
    pub enable_stale_production: bool,
}

#[derive(Clone)]
pub struct ServerData {
    pub chain: Arc<Blockchain>,
    pub minter: Minter,
    pub sub_pool: SubscriptionPool,
}

pub fn start(opts: ServerOpts) {
    let blockchain = Arc::new(Blockchain::new(&opts.blocklog_loc, &opts.index_loc));

    let is_empty = blockchain.is_empty();
    if !is_empty && blockchain.index_status() != IndexStatus::Complete {
        warn!(
            "Indexing not complete (status = {:?})",
            blockchain.index_status()
        );
        match opts.reindex {
            Some(opts) => blockchain.reindex(opts),
            None => panic!("index incomplete, aborting..."),
        }
    }

    if is_empty {
        let info = blockchain.create_genesis_block(opts.minter_key.clone());
        info!("=> Generated new block chain");
        info!("=> {:?}", info.script);
        for (index, key) in info.wallet_keys.iter().enumerate() {
            info!("=> Wallet key {}: {}", index + 1, key.1.to_wif());
        }
    }

    info!(
        "Using height in block log at {}",
        blockchain.get_chain_height()
    );

    let sub_pool = SubscriptionPool::new();
    let minter = Minter::new(
        Arc::clone(&blockchain),
        opts.minter_key,
        sub_pool.clone(),
        opts.enable_stale_production,
    );
    minter.clone().start_production_loop();

    let data = Arc::new(ServerData {
        chain: Arc::clone(&blockchain),
        minter,
        sub_pool,
    });

    let addr = opts.bind_addr.parse::<SocketAddr>().unwrap();
    start_server(addr, data);
}

fn start_server(server_addr: SocketAddr, data: Arc<ServerData>) {
    let server = TcpListener::bind(&server_addr).unwrap();
    let incoming = forever::ListenForever::new(server.incoming());
    tokio::spawn(incoming.for_each(move |stream| {
        let peer_addr = stream.peer_addr().unwrap();
        let data = Arc::clone(&data);
        tokio::spawn(
            tokio_tungstenite::accept_async(stream)
                .and_then(move |ws| {
                    info!("[{}] Connection opened", peer_addr);

                    let (tx, rx) = mpsc::channel(32);
                    let (sink, stream) = ws.split();
                    let mut state = WsState::new(peer_addr, tx.clone());

                    let ws_reader = stream.for_each({
                        let data = Arc::clone(&data);
                        move |msg| {
                            let res = process_message(&data, &mut state, msg);
                            if let Some(res) = res {
                                let peer_addr = peer_addr.clone();
                                future::Either::A(tx.clone().send(res).then(move |res| {
                                    if let Err(_) = res {
                                        error!("[{}] Failed to send message", peer_addr);
                                    }
                                    Ok(())
                                }))
                            } else {
                                future::Either::B(future::ok(()))
                            }
                        }
                    });
                    let ws_writer = rx.forward(sink.sink_map_err(move |e| {
                        error!("[{}] Sink send error: {:?}", peer_addr, e);
                    }));

                    let conn = ws_reader
                        .map_err(|_| ())
                        .select(ws_writer.map(|_| ()).map_err(|_| ()));
                    tokio::spawn(conn.then(move |_| {
                        info!("[{}] Connection closed", peer_addr);
                        // Remove block subscriptions if there are any
                        data.sub_pool.remove(peer_addr);
                        Ok(())
                    }));

                    Ok(())
                })
                .map_err(move |e| {
                    error!("[{}] WS accept error = {:?}", peer_addr, e);
                }),
        );
        Ok(())
    }));
}

pub fn process_message(data: &ServerData, state: &mut WsState, msg: Message) -> Option<Message> {
    match msg {
        Message::Binary(buf) => {
            let mut cur = Cursor::<&[u8]>::new(&buf);
            let res = match Request::deserialize(&mut cur) {
                Ok(req) => {
                    let id = req.id;
                    if id == u32::max_value() {
                        // Max value is reserved
                        Response {
                            id: u32::max_value(),
                            body: ResponseBody::Error(ErrorKind::Io),
                        }
                    } else if cur.position() != buf.len() as u64 {
                        Response {
                            id,
                            body: ResponseBody::Error(ErrorKind::BytesRemaining),
                        }
                    } else {
                        match handle_request(data, state, req) {
                            Some(res) => Response { id, body: res },
                            None => return None,
                        }
                    }
                }
                Err(e) => {
                    error!("Error occurred during deserialization: {:?}", e);
                    Response {
                        id: u32::max_value(),
                        body: ResponseBody::Error(ErrorKind::Io),
                    }
                }
            };

            let mut buf = Vec::with_capacity(65536);
            res.serialize(&mut buf);
            Some(Message::Binary(buf))
        }
        Message::Text(_) => Some(Message::Close(Some(protocol::CloseFrame {
            code: protocol::frame::coding::CloseCode::Unsupported,
            reason: "text is not supported".into(),
        }))),
        _ => None,
    }
}

fn handle_request(data: &ServerData, state: &mut WsState, req: Request) -> Option<ResponseBody> {
    Some(match req.body {
        RequestBody::Broadcast(tx) => {
            let res = data.minter.push_tx(tx);
            match res {
                Ok(_) => ResponseBody::Broadcast,
                Err(e) => ResponseBody::Error(ErrorKind::TxValidation(e)),
            }
        }
        RequestBody::SetBlockFilter(filter) => {
            if filter.len() > 16 {
                return Some(ResponseBody::Error(ErrorKind::InvalidRequest));
            }
            state.filter = Some(filter);
            ResponseBody::SetBlockFilter
        }
        RequestBody::ClearBlockFilter => {
            state.filter = None;
            ResponseBody::ClearBlockFilter
        }
        RequestBody::Subscribe => {
            data.sub_pool.insert(state.addr(), state.sender());
            ResponseBody::Subscribe
        }
        RequestBody::Unsubscribe => {
            data.sub_pool.remove(state.addr());
            ResponseBody::Unsubscribe
        }
        RequestBody::GetProperties => {
            let props = data.chain.get_properties();
            ResponseBody::GetProperties(props)
        }
        RequestBody::GetBlock(height) => match &state.filter {
            Some(filter) => match data.chain.get_filtered_block(height, filter) {
                Some(block) => ResponseBody::GetBlock(block),
                None => ResponseBody::Error(ErrorKind::InvalidHeight),
            },
            None => match data.chain.get_block(height) {
                Some(block) => ResponseBody::GetBlock(FilteredBlock::Block(block)),
                None => ResponseBody::Error(ErrorKind::InvalidHeight),
            },
        },
        RequestBody::GetFullBlock(height) => match data.chain.get_block(height) {
            Some(block) => ResponseBody::GetFullBlock(block),
            None => ResponseBody::Error(ErrorKind::InvalidHeight),
        },
        RequestBody::GetBlockRange(min_height, max_height) => {
            let range = AsyncBlockRange::try_new(Arc::clone(&data.chain), min_height, max_height);
            match range {
                Some(mut range) => {
                    if let Some(filter) = state.filter() {
                        range.set_filter(Some(filter.clone()));
                    }

                    let peer_addr = state.addr();
                    let tx = state.sender();
                    let id = req.id;

                    tokio::spawn(
                        range
                            .map(move |block| {
                                let msg = Response {
                                    id,
                                    body: ResponseBody::GetBlock(block),
                                };

                                let mut buf = Vec::with_capacity(65536);
                                msg.serialize(&mut buf);
                                Message::Binary(buf)
                            })
                            .forward(tx.clone().sink_map_err(move |_| {
                                error!("[{}] Failed to send block range update", peer_addr);
                            }))
                            .and_then(move |_| {
                                let msg = Response {
                                    id,
                                    body: ResponseBody::GetBlockRange,
                                };

                                let mut buf = Vec::with_capacity(32);
                                msg.serialize(&mut buf);
                                tx.send(Message::Binary(buf))
                                    .map(|_sink| ())
                                    .map_err(move |_| {
                                        error!(
                                            "[{}] Failed to send block range finalizer",
                                            peer_addr
                                        );
                                    })
                            }),
                    );

                    return None;
                }
                None => ResponseBody::Error(ErrorKind::InvalidHeight),
            }
        }
        RequestBody::GetAddressInfo(addr) => {
            let res = data.minter.get_addr_info(&addr);
            match res {
                Ok(info) => ResponseBody::GetAddressInfo(info),
                Err(e) => ResponseBody::Error(ErrorKind::TxValidation(e)),
            }
        }
    })
}

pub struct WsState {
    filter: Option<BlockFilter>,
    addr: SocketAddr,
    tx: Sender<Message>,
}

impl WsState {
    #[inline]
    pub fn new(addr: SocketAddr, tx: Sender<Message>) -> Self {
        Self {
            filter: None,
            addr,
            tx,
        }
    }

    #[inline]
    pub fn addr(&self) -> SocketAddr {
        self.addr
    }

    #[inline]
    pub fn filter(&self) -> Option<&BlockFilter> {
        self.filter.as_ref()
    }

    #[inline]
    pub fn sender(&self) -> Sender<Message> {
        self.tx.clone()
    }
}
<commit_msg>Fix clippy warnings<commit_after>use futures::sync::mpsc::{self, Sender};
use godcoin::{blockchain::ReindexOpts, net::*, prelude::*};
use log::{error, info, warn};
use std::{io::Cursor, net::SocketAddr, path::PathBuf, sync::Arc};
use tokio::{net::TcpListener, prelude::*};
use tokio_tungstenite::tungstenite::{protocol, Message};

mod block_range;
mod forever;
pub mod minter;
pub mod pool;

pub mod prelude {
    pub use super::minter::*;
    pub use super::pool::SubscriptionPool;
}

use block_range::AsyncBlockRange;
use prelude::*;

pub struct ServerOpts {
    pub blocklog_loc: PathBuf,
    pub index_loc: PathBuf,
    pub minter_key: KeyPair,
    pub bind_addr: String,
    pub reindex: Option<ReindexOpts>,
    pub enable_stale_production: bool,
}

#[derive(Clone)]
pub struct ServerData {
    pub chain: Arc<Blockchain>,
    pub minter: Minter,
    pub sub_pool: SubscriptionPool,
}

pub fn start(opts: ServerOpts) {
    let blockchain = Arc::new(Blockchain::new(&opts.blocklog_loc, &opts.index_loc));

    let is_empty = blockchain.is_empty();
    if !is_empty && blockchain.index_status() != IndexStatus::Complete {
        warn!(
            "Indexing not complete (status = {:?})",
            blockchain.index_status()
        );
        match opts.reindex {
            Some(opts) => blockchain.reindex(opts),
            None => panic!("index incomplete, aborting..."),
        }
    }

    if is_empty {
        let info = blockchain.create_genesis_block(opts.minter_key.clone());
        info!("=> Generated new block chain");
        info!("=> {:?}", info.script);
        for (index, key) in info.wallet_keys.iter().enumerate() {
            info!("=> Wallet key {}: {}", index + 1, key.1.to_wif());
        }
    }

    info!(
        "Using height in block log at {}",
        blockchain.get_chain_height()
    );

    let sub_pool = SubscriptionPool::new();
    let minter = Minter::new(
        Arc::clone(&blockchain),
        opts.minter_key,
        sub_pool.clone(),
        opts.enable_stale_production,
    );
    minter.clone().start_production_loop();

    let data = Arc::new(ServerData {
        chain: Arc::clone(&blockchain),
        minter,
        sub_pool,
    });

    let addr = opts.bind_addr.parse::<SocketAddr>().unwrap();
    start_server(addr, data);
}

fn start_server(server_addr: SocketAddr, data: Arc<ServerData>) {
    let server = TcpListener::bind(&server_addr).unwrap();
    let incoming = forever::ListenForever::new(server.incoming());
    tokio::spawn(incoming.for_each(move |stream| {
        let peer_addr = stream.peer_addr().unwrap();
        let data = Arc::clone(&data);
        tokio::spawn(
            tokio_tungstenite::accept_async(stream)
                .and_then(move |ws| {
                    info!("[{}] Connection opened", peer_addr);

                    let (tx, rx) = mpsc::channel(32);
                    let (sink, stream) = ws.split();
                    let mut state = WsState::new(peer_addr, tx.clone());

                    let ws_reader = stream.for_each({
                        let data = Arc::clone(&data);
                        move |msg| {
                            let res = process_message(&data, &mut state, msg);
                            if let Some(res) = res {
                                future::Either::A(tx.clone().send(res).then(move |res| {
                                    if res.is_err() {
                                        error!("[{}] Failed to send message", peer_addr);
                                    }
                                    Ok(())
                                }))
                            } else {
                                future::Either::B(future::ok(()))
                            }
                        }
                    });
                    let ws_writer = rx.forward(sink.sink_map_err(move |e| {
                        error!("[{}] Sink send error: {:?}", peer_addr, e);
                    }));

                    let conn = ws_reader
                        .map_err(|_| ())
                        .select(ws_writer.map(|_| ()).map_err(|_| ()));
                    tokio::spawn(conn.then(move |_| {
                        info!("[{}] Connection closed", peer_addr);
                        // Remove block subscriptions if there are any
                        data.sub_pool.remove(peer_addr);
                        Ok(())
                    }));

                    Ok(())
                })
                .map_err(move |e| {
                    error!("[{}] WS accept error = {:?}", peer_addr, e);
                }),
        );
        Ok(())
    }));
}

pub fn process_message(data: &ServerData, state: &mut WsState, msg: Message) -> Option<Message> {
    match msg {
        Message::Binary(buf) => {
            let mut cur = Cursor::<&[u8]>::new(&buf);
            let res = match Request::deserialize(&mut cur) {
                Ok(req) => {
                    let id = req.id;
                    if id == u32::max_value() {
                        // Max value is reserved
                        Response {
                            id: u32::max_value(),
                            body: ResponseBody::Error(ErrorKind::Io),
                        }
                    } else if cur.position() != buf.len() as u64 {
                        Response {
                            id,
                            body: ResponseBody::Error(ErrorKind::BytesRemaining),
                        }
                    } else {
                        match handle_request(data, state, req) {
                            Some(res) => Response { id, body: res },
                            None => return None,
                        }
                    }
                }
                Err(e) => {
                    error!("Error occurred during deserialization: {:?}", e);
                    Response {
                        id: u32::max_value(),
                        body: ResponseBody::Error(ErrorKind::Io),
                    }
                }
            };

            let mut buf = Vec::with_capacity(65536);
            res.serialize(&mut buf);
            Some(Message::Binary(buf))
        }
        Message::Text(_) => Some(Message::Close(Some(protocol::CloseFrame {
            code: protocol::frame::coding::CloseCode::Unsupported,
            reason: "text is not supported".into(),
        }))),
        _ => None,
    }
}

fn handle_request(data: &ServerData, state: &mut WsState, req: Request) -> Option<ResponseBody> {
    Some(match req.body {
        RequestBody::Broadcast(tx) => {
            let res = data.minter.push_tx(tx);
            match res {
                Ok(_) => ResponseBody::Broadcast,
                Err(e) => ResponseBody::Error(ErrorKind::TxValidation(e)),
            }
        }
        RequestBody::SetBlockFilter(filter) => {
            if filter.len() > 16 {
                return Some(ResponseBody::Error(ErrorKind::InvalidRequest));
            }
            state.filter = Some(filter);
            ResponseBody::SetBlockFilter
        }
        RequestBody::ClearBlockFilter => {
            state.filter = None;
            ResponseBody::ClearBlockFilter
        }
        RequestBody::Subscribe => {
            data.sub_pool.insert(state.addr(), state.sender());
            ResponseBody::Subscribe
        }
        RequestBody::Unsubscribe => {
            data.sub_pool.remove(state.addr());
            ResponseBody::Unsubscribe
        }
        RequestBody::GetProperties => {
            let props = data.chain.get_properties();
            ResponseBody::GetProperties(props)
        }
        RequestBody::GetBlock(height) => match &state.filter {
            Some(filter) => match data.chain.get_filtered_block(height, filter) {
                Some(block) => ResponseBody::GetBlock(block),
                None => ResponseBody::Error(ErrorKind::InvalidHeight),
            },
            None => match data.chain.get_block(height) {
                Some(block) => ResponseBody::GetBlock(FilteredBlock::Block(block)),
                None => ResponseBody::Error(ErrorKind::InvalidHeight),
            },
        },
        RequestBody::GetFullBlock(height) => match data.chain.get_block(height) {
            Some(block) => ResponseBody::GetFullBlock(block),
            None => ResponseBody::Error(ErrorKind::InvalidHeight),
        },
        RequestBody::GetBlockRange(min_height, max_height) => {
            let range = AsyncBlockRange::try_new(Arc::clone(&data.chain), min_height, max_height);
            match range {
                Some(mut range) => {
                    if let Some(filter) = state.filter() {
                        range.set_filter(Some(filter.clone()));
                    }

                    let peer_addr = state.addr();
                    let tx = state.sender();
                    let id = req.id;

                    tokio::spawn(
                        range
                            .map(move |block| {
                                let msg = Response {
                                    id,
                                    body: ResponseBody::GetBlock(block),
                                };

                                let mut buf = Vec::with_capacity(65536);
                                msg.serialize(&mut buf);
                                Message::Binary(buf)
                            })
                            .forward(tx.clone().sink_map_err(move |_| {
                                error!("[{}] Failed to send block range update", peer_addr);
                            }))
                            .and_then(move |_| {
                                let msg = Response {
                                    id,
                                    body: ResponseBody::GetBlockRange,
                                };

                                let mut buf = Vec::with_capacity(32);
                                msg.serialize(&mut buf);
                                tx.send(Message::Binary(buf))
                                    .map(|_sink| ())
                                    .map_err(move |_| {
                                        error!(
                                            "[{}] Failed to send block range finalizer",
                                            peer_addr
                                        );
                                    })
                            }),
                    );

                    return None;
                }
                None => ResponseBody::Error(ErrorKind::InvalidHeight),
            }
        }
        RequestBody::GetAddressInfo(addr) => {
            let res = data.minter.get_addr_info(&addr);
            match res {
                Ok(info) => ResponseBody::GetAddressInfo(info),
                Err(e) => ResponseBody::Error(ErrorKind::TxValidation(e)),
            }
        }
    })
}

pub struct WsState {
    filter: Option<BlockFilter>,
    addr: SocketAddr,
    tx: Sender<Message>,
}

impl WsState {
    #[inline]
    pub fn new(addr: SocketAddr, tx: Sender<Message>) -> Self {
        Self {
            filter: None,
            addr,
            tx,
        }
    }

    #[inline]
    pub fn addr(&self) -> SocketAddr {
        self.addr
    }

    #[inline]
    pub fn filter(&self) -> Option<&BlockFilter> {
        self.filter.as_ref()
    }

    #[inline]
    pub fn sender(&self) -> Sender<Message> {
        self.tx.clone()
    }
}
<|endoftext|>


<commit_before>//! This crate provides the `#[quickcheck]` attribute. Its use is
//! documented in the `quickcheck` crate.

#![crate_name = "quickcheck_macros"]
#![crate_type = "dylib"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")]

#![feature(plugin_registrar, rustc_private)]

extern crate syntax;
extern crate rustc;

use syntax::abi;
use syntax::ast;
use syntax::ast::Ty_::TyBareFn;
use syntax::ast_util;
use syntax::codemap;
use syntax::parse::token;
use syntax::ext::base::{ExtCtxt, MultiModifier, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use rustc::plugin::Registry;

/// For the `#[quickcheck]` attribute. Do not use.
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("quickcheck"),
                                  MultiModifier(Box::new(expand_meta_quickcheck)));
}

/// Expands the `#[quickcheck]` attribute.
///
/// Expands:
/// ```
/// #[quickcheck]
/// fn check_something(_: usize) -> bool {
///     true
/// }
/// ```
/// to:
/// ```
/// #[test]
/// fn check_something() {
///     fn check_something(_: usize) -> bool {
///         true
///     }
///     ::quickcheck::quickcheck(check_something as fn(usize) -> bool)
/// }
/// ```
fn expand_meta_quickcheck(cx: &mut ExtCtxt,
                          span: codemap::Span,
                          _: &ast::MetaItem,
                          annot_item: Annotatable) -> Annotatable {
    let item = annot_item.expect_item();
    match item.node {
        ast::ItemFn(ref decl, unsafety, _constness, abi, _, _) => {
            let prop_ident = cx.expr_ident(span, item.ident);
            let prop_ty = cx.ty(span, TyBareFn(P(ast::BareFnTy {
                unsafety: unsafety,
                abi: abi,
                lifetimes: vec![],
                decl: decl.clone(),
            })));
            let inner_ident = cx.expr_cast(span, prop_ident, prop_ty);
            return wrap_item(cx, span, &*item, inner_ident);
        },
        ast::ItemStatic(..) => {
            let inner_ident = cx.expr_ident(span, item.ident);
            return wrap_item(cx, span, &*item, inner_ident);
        },
        _ => {
            cx.span_err(
                span, "#[quickcheck] only supported on statics and functions");
        }
    }
    Annotatable::Item(item)
}

fn wrap_item(cx: &mut ExtCtxt,
             span: codemap::Span,
             item: &ast::Item,
             inner_ident: P<ast::Expr>) -> Annotatable {
    // Copy original function without attributes
    let prop = P(ast::Item {attrs: Vec::new(), ..item.clone()});
    // ::quickcheck::quickcheck
    let check_ident = token::str_to_ident("quickcheck");
    let check_path = vec!(check_ident, check_ident);
    // Wrap original function in new outer function,
    // calling ::quickcheck::quickcheck()
    let fn_decl = P(codemap::respan(span, ast::DeclItem(prop.clone())));
    let inner_fn =
        P(codemap::respan(span, ast::StmtDecl(fn_decl, ast::DUMMY_NODE_ID)));
    let check_call = cx.expr_call_global(span, check_path, vec![inner_ident]);
    let body = cx.block(span, vec![inner_fn], Some(check_call));
    let test = item_fn(cx, span, item, body);

    // Copy attributes from original function
    let mut attrs = item.attrs.clone();
    // Add #[test] attribute
    attrs.push(cx.attribute(
        span, cx.meta_word(span, token::intern_and_get_ident("test"))));
    // Attach the attributes to the outer function
    Annotatable::Item(P(ast::Item {attrs: attrs, ..(*test).clone()}))
}

fn item_fn(cx: &mut ExtCtxt, span: codemap::Span,
           towrap_item: &ast::Item, body: P<ast::Block>) -> P<ast::Item> {
    let decl = P(ast::FnDecl {
        inputs: vec![],
        output: ast::FunctionRetTy::DefaultReturn(span),
        variadic: false,
    });
    let item = ast::ItemFn(decl,
                           ast::Unsafety::Normal,
                           ast::Constness::NotConst,
                           abi::Rust,
                           ast_util::empty_generics(),
                           body);
    cx.item(span, towrap_item.ident, vec![], item)
}
<commit_msg>Fix the travis build on nightly<commit_after>//! This crate provides the `#[quickcheck]` attribute. Its use is
//! documented in the `quickcheck` crate.

#![crate_name = "quickcheck_macros"]
#![crate_type = "dylib"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")]

#![feature(plugin_registrar, rustc_private)]

extern crate syntax;
extern crate rustc_plugin;

use syntax::abi;
use syntax::ast;
use syntax::ast::Ty_::TyBareFn;
use syntax::ast_util;
use syntax::codemap;
use syntax::parse::token;
use syntax::ext::base::{ExtCtxt, MultiModifier, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use rustc_plugin::Registry;

/// For the `#[quickcheck]` attribute. Do not use.
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("quickcheck"),
                                  MultiModifier(Box::new(expand_meta_quickcheck)));
}

/// Expands the `#[quickcheck]` attribute.
///
/// Expands:
/// ```
/// #[quickcheck]
/// fn check_something(_: usize) -> bool {
///     true
/// }
/// ```
/// to:
/// ```
/// #[test]
/// fn check_something() {
///     fn check_something(_: usize) -> bool {
///         true
///     }
///     ::quickcheck::quickcheck(check_something as fn(usize) -> bool)
/// }
/// ```
fn expand_meta_quickcheck(cx: &mut ExtCtxt,
                          span: codemap::Span,
                          _: &ast::MetaItem,
                          annot_item: Annotatable) -> Annotatable {
    let item = annot_item.expect_item();
    match item.node {
        ast::ItemFn(ref decl, unsafety, _constness, abi, _, _) => {
            let prop_ident = cx.expr_ident(span, item.ident);
            let prop_ty = cx.ty(span, TyBareFn(P(ast::BareFnTy {
                unsafety: unsafety,
                abi: abi,
                lifetimes: vec![],
                decl: decl.clone(),
            })));
            let inner_ident = cx.expr_cast(span, prop_ident, prop_ty);
            return wrap_item(cx, span, &*item, inner_ident);
        },
        ast::ItemStatic(..) => {
            let inner_ident = cx.expr_ident(span, item.ident);
            return wrap_item(cx, span, &*item, inner_ident);
        },
        _ => {
            cx.span_err(
                span, "#[quickcheck] only supported on statics and functions");
        }
    }
    Annotatable::Item(item)
}

fn wrap_item(cx: &mut ExtCtxt,
             span: codemap::Span,
             item: &ast::Item,
             inner_ident: P<ast::Expr>) -> Annotatable {
    // Copy original function without attributes
    let prop = P(ast::Item {attrs: Vec::new(), ..item.clone()});
    // ::quickcheck::quickcheck
    let check_ident = token::str_to_ident("quickcheck");
    let check_path = vec!(check_ident, check_ident);
    // Wrap original function in new outer function,
    // calling ::quickcheck::quickcheck()
    let fn_decl = P(codemap::respan(span, ast::DeclItem(prop.clone())));
    let inner_fn =
        P(codemap::respan(span, ast::StmtDecl(fn_decl, ast::DUMMY_NODE_ID)));
    let check_call = cx.expr_call_global(span, check_path, vec![inner_ident]);
    let body = cx.block(span, vec![inner_fn], Some(check_call));
    let test = item_fn(cx, span, item, body);

    // Copy attributes from original function
    let mut attrs = item.attrs.clone();
    // Add #[test] attribute
    attrs.push(cx.attribute(
        span, cx.meta_word(span, token::intern_and_get_ident("test"))));
    // Attach the attributes to the outer function
    Annotatable::Item(P(ast::Item {attrs: attrs, ..(*test).clone()}))
}

fn item_fn(cx: &mut ExtCtxt, span: codemap::Span,
           towrap_item: &ast::Item, body: P<ast::Block>) -> P<ast::Item> {
    let decl = P(ast::FnDecl {
        inputs: vec![],
        output: ast::FunctionRetTy::DefaultReturn(span),
        variadic: false,
    });
    let item = ast::ItemFn(decl,
                           ast::Unsafety::Normal,
                           ast::Constness::NotConst,
                           abi::Rust,
                           ast_util::empty_generics(),
                           body);
    cx.item(span, towrap_item.ident, vec![], item)
}
<|endoftext|>