<commit_before>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;

fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (
        theta.sin()*r,
        -theta.cos()*r,
    )
}

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v*dt);
        self.x = (self.x + dx + x_max) % x_max;
        self.y = (self.y + dy + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

const LARGE_ASTROID_BORDER: [[f64; 4]; 4] = [
    [-15.0, 0.0, 0.0, 15.0],
    [0.0, 15.0, 15.0, 0.0],
    [15.0, 0.0, 0.0, -15.0],
    [0.0, -15.0, -15.0, 0.0],
];

const ASTROID_BORDER: [[f64; 4]; 4] = [
    [-10.0, 0.0, 0.0, 10.0],
    [0.0, 10.0, 10.0, 0.0],
    [10.0, 0.0, 0.0, -10.0],
    [0.0, -10.0, -10.0, 0.0],
];

const SMALL_ASTROID_BORDER: [[f64; 4]; 4] = [
    [-5.0, 0.0, 0.0, 5.0],
    [0.0, 5.0, 5.0, 0.0],
    [5.0, 0.0, 0.0, -5.0],
    [0.0, -5.0, -5.0, 0.0],
];

const ASTROID_BORDERS: [&'static[[f64; 4]; 4]; 3] = [&LARGE_ASTROID_BORDER, &ASTROID_BORDER, &SMALL_ASTROID_BORDER];

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    border: &'static[[f64; 4]; 4],
}

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        use rand::sample;
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
            border: sample(rng, ASTROID_BORDERS.iter(), 1)[0],
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }
}<commit_msg>Added random astroids<commit_after>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;

fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (
        theta.sin()*r,
        -theta.cos()*r,
    )
}

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v*dt);
        self.x = (self.x + dx + x_max) % x_max;
        self.y = (self.y + dy + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    border: Vec<[f64; 4]>,
}

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        let radius = (rng.gen_range(1, 3)*5) as f64;
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
            border: Astroid::create_border(rng, radius),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }

    pub fn create_border<R: Rng>(rng: &mut R, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius/5.0;
        let point_count = rng.gen_range(8, 12);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = rng.gen_range(0.0, 2.0*PI);
        for theta in (1..point_count+1).map(|i| theta_0 + 2.0*PI*i as f64/point_count as f64) {
            let distance = radius + rng.gen_range(-spread, spread);
            points.push(to_cartesian(theta, distance));
        };
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }
}<|endoftext|>


<commit_before>use std::fmt;

pub struct RawCodeItem {
    pub name: String,
    pub attributes: Vec<(String, String)>,
    pub children: Vec<RawCodeItem>
}

impl RawCodeItem {
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> RawCodeItem {
        RawCodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<RawCodeItem>::new()
        }
    }
}

pub struct RawCode {
    pub elements: Vec<RawCodeItem>
}

impl RawCode {
    pub fn new() -> RawCode {
        RawCode {
            elements: Vec::<RawCodeItem>::new()
        }
    }

    // convert raw data to cpp code
    pub fn to_cpp(&self) -> u8 {
        0
    }

    // convert raw data to Rust code
    pub fn to_rust(&self) -> u8 {
        0
    }

    // used by Display trait to print the tree of elements
    fn print_element(&self, e: &RawCodeItem, f: &mut fmt::Formatter, depth: u8, empty_spaces: &mut Vec<u8>) {
        // indentation
        for i in 0..depth {
            let mut separator = "|";
            for j in empty_spaces.iter() {
                if i == *j {
                    separator = " ";
                    break;
                }
            }
            let _ = write!(f, "{}  ", separator);
        }

        let _ = write!(f, "|--{}", e.name);
        // print attributes
        if e.attributes.len() > 0 {
            let _ = write!(f, " [");
            for a in 0..e.attributes.len() {
                if a > 0 && a < e.attributes.len() {
                    let _ = write!(f, ", ");
                }
                let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
            }
            let _ = write!(f, "]");
        }
        let _ = write!(f, "\n");

        // child processing
        if e.children.len() > 0 {
            for c in 0..e.children.len() {
                if (e.children.len() - c) == 1 {
                    empty_spaces.push(depth+1);
                }
                self.print_element(&e.children[c], f, depth+1, empty_spaces);
            }

            if depth == 1 {
                empty_spaces.clear();
            }
        }
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "\n");
        for e in 0..self.elements.len() {
            let mut empty_spaces = Vec::<u8>::new();
            let _ = self.print_element(&self.elements[e], f, 0, &mut empty_spaces);
        }
        write!(f, "\n")
    }
}
<commit_msg>simplified tree drawing<commit_after>use std::fmt;

pub struct RawCodeItem {
    pub name: String,
    pub attributes: Vec<(String, String)>,
    pub children: Vec<RawCodeItem>
}

impl RawCodeItem {
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> RawCodeItem {
        RawCodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<RawCodeItem>::new()
        }
    }
}

pub struct RawCode {
    pub elements: Vec<RawCodeItem>
}

impl RawCode {
    pub fn new() -> RawCode {
        RawCode {
            elements: Vec::<RawCodeItem>::new()
        }
    }

    // convert raw data to cpp code
    pub fn to_cpp(&self) -> u8 {
        0
    }

    // convert raw data to Rust code
    pub fn to_rust(&self) -> u8 {
        0
    }

    // used by Display trait to print the tree of elements
    fn print_element(&self, e: &RawCodeItem, f: &mut fmt::Formatter, depth: u8, empty_spaces: &mut Vec<u8>) {
        // indentation
        for i in 0..depth {
            let idx = empty_spaces.binary_search(&i);
            let separator = match idx { Ok(_) => { " " }, _ => { "|" } };
            let _ = write!(f, "{}  ", separator);
        }

        let _ = write!(f, "|--{}", e.name);
        // print attributes
        if e.attributes.len() > 0 {
            let _ = write!(f, " [");
            for a in 0..e.attributes.len() {
                if a > 0 && a < e.attributes.len() {
                    let _ = write!(f, ", ");
                }
                let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
            }
            let _ = write!(f, "]");
        }
        let _ = write!(f, "\n");

        // child processing
        if e.children.len() > 0 {
            for c in 0..e.children.len() {
                if (e.children.len() - c) == 1 {
                    empty_spaces.push(depth+1);
                }
                else {
                    let idx = empty_spaces.binary_search(&(depth+1));
                    match idx { Ok(_) => { empty_spaces.remove(idx.unwrap()); }, _ => {} };
                }
                self.print_element(&e.children[c], f, depth+1, empty_spaces);
            }

            // reset space directory when topmost child is reached
            if depth == 1 {
                empty_spaces.clear();
            }
        }
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "\n");
        for e in 0..self.elements.len() {
            let mut empty_spaces = Vec::<u8>::new();
            let _ = self.print_element(&self.elements[e], f, 0, &mut empty_spaces);
        }
        write!(f, "\n")
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use metric::Metric;
use reporter::Reporter;

pub trait Registry<'a>: Send + Sync {
    fn add_scheduled_reporter(&mut self, reporter: Box<Reporter>);
    fn get(&'a self, name: &'a str) -> &'a Metric;
    fn get_metrics_names(&self) -> Vec<&str>;
    fn insert<T: Metric + 'a>(&mut self, name: &'a str, metric: T);
}

pub struct StdRegistry<'a> {
    metrics: HashMap<&'a str, Box<Metric+ 'a>>,
    reporter: HashMap<&'a str, Box<Reporter>>
}

// Specific stuff for registry goes here
impl<'a> Registry<'a> for StdRegistry<'a> {
    fn add_scheduled_reporter(&mut self, reporter: Box<Reporter>) {
        let reporter_name = reporter.get_unique_reporter_name();
        self.reporter.insert(reporter_name, reporter);
    }

    fn get(&'a self, name: &'a str) -> &'a Metric {
        &*self.metrics[name]
    }

    fn insert<T: Metric + 'a>(&mut self, name: &'a str, metric: T) {
        let boxed = Box::new(metric);
        self.metrics.insert(name, boxed);
    }

    fn get_metrics_names(&self) -> Vec<&str> {
        self.metrics.keys().cloned().collect()
    }
}

// General StdRegistry
impl<'a> StdRegistry<'a> {
    #[allow(dead_code)]
    pub fn new() -> StdRegistry<'a> {
        StdRegistry { metrics: HashMap::new(), reporter: HashMap::new() }
    }
}

#[cfg(test)]
mod test {
    use meter::StdMeter;
    use registry::{Registry, StdRegistry};

    #[test]
    fn meter() {
        let mut r: StdRegistry = StdRegistry::new();
        let m: StdMeter = StdMeter::new();

        r.insert("foo", m);
        r.get("foo");
    }
}
<commit_msg>Repaired registry tests<commit_after>use std::collections::HashMap;
use metric::Metric;
use reporter::Reporter;

pub trait Registry<'a>: Send + Sync {
    fn add_scheduled_reporter(&mut self, reporter: Box<Reporter>);
    fn get(&'a self, name: &'a str) -> &'a Metric;
    fn get_metrics_names(&self) -> Vec<&str>;
    fn insert<T: Metric + 'a>(&mut self, name: &'a str, metric: T);
}

pub struct StdRegistry<'a> {
    metrics: HashMap<&'a str, Box<Metric+ 'a>>,
    reporter: HashMap<&'a str, Box<Reporter>>
}

// Specific stuff for registry goes here
impl<'a> Registry<'a> for StdRegistry<'a> {
    fn add_scheduled_reporter(&mut self, reporter: Box<Reporter>) {
        let reporter_name = reporter.get_unique_reporter_name();
        self.reporter.insert(reporter_name, reporter);
    }

    fn get(&'a self, name: &'a str) -> &'a Metric {
        &*self.metrics[name]
    }

    fn insert<T: Metric + 'a>(&mut self, name: &'a str, metric: T) {
        let boxed = Box::new(metric);
        self.metrics.insert(name, boxed);
    }

    fn get_metrics_names(&self) -> Vec<&str> {
        self.metrics.keys().cloned().collect()
    }
}

// General StdRegistry
impl<'a> StdRegistry<'a> {
    #[allow(dead_code)]
    pub fn new() -> StdRegistry<'a> {
        StdRegistry { metrics: HashMap::new(), reporter: HashMap::new() }
    }
}

#[cfg(test)]
mod test {
    use meter::{Meter, StdMeter};
    use counter::{Counter, StdCounter};
    use gauge::{Gauge, StdGauge};
    use registry::{Registry, StdRegistry};

    #[test]
    fn meter() {
        let mut r = StdRegistry::new();
        let m = StdMeter::new();
        m.mark(100);
        r.insert("meter1", m);

    }

    #[test]
    fn gauge() {
        let mut r = StdRegistry::new();
        let mut g: StdGauge = StdGauge { value: 0f64 };
        g.update(1.2);
        r.insert("gauge1", g);
    }

    #[test]
    fn counter() {
        let mut r = StdRegistry::new();
        let mut c: StdCounter = StdCounter::new();
        c.inc(1);
        r.insert("counter1", c);
    }

}
<|endoftext|>


<commit_before>use devices::{NodeId, ServiceId, ServiceKind};
use util::Exactly;
use values;

use serde::ser::Serializer;
use serde::de::Deserializer;

use std::cmp;

fn merge<T>(mut a: Vec<T>, mut b: Vec<T>) -> Vec<T> where T: Ord {
    a.append(&mut b);
    a.sort();
    a.dedup();
    a
}

/// A request for one or more nodes.
///
///
/// # Example
///
/// ```
/// use fxbox_taxonomy::requests::*;
/// use fxbox_taxonomy::devices::*;
///
/// let request = NodeRequest::new()
///   .with_tags(vec!["entrance".to_owned()])
///   .with_inputs(vec![InputRequest::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct NodeRequest {
    /// If `Exactly(id)`, return only the node with the corresponding id.
    #[serde(default)]
    pub id: Exactly<NodeId>,

    ///  Restrict results to nodes that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// Restrict results to nodes that have all the inputs in `inputs`.
    #[serde(default)]
    pub inputs: Vec<InputRequest>,

    /// Restrict results to nodes that have all the outputs in `outputs`.
    #[serde(default)]
    pub outputs: Vec<OutputRequest>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl NodeRequest {
    /// Create a new request that accepts all nodes.
    pub fn new() -> Self {
        Self::default()
    }

    /// Request for a node with a specific id.
    pub fn with_id(self, id: NodeId) -> Self {
        NodeRequest {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    ///  Restrict results to nodes that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        NodeRequest {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict results to nodes that have all the inputs in `inputs`.
    pub fn with_inputs(mut self, mut inputs: Vec<InputRequest>) -> Self {
        NodeRequest {
            inputs: {self.inputs.append(&mut inputs); self.inputs},
            .. self
        }
    }

    /// Restrict results to nodes that have all the outputs in `outputs`.
    pub fn with_outputs(mut self, mut outputs: Vec<OutputRequest>) -> Self {
        NodeRequest {
            outputs: {self.outputs.append(&mut outputs); self.outputs},
            .. self
        }
    }

    /// Restrict results to nodes that are accepted by two requests.
    pub fn and(mut self, mut other: NodeRequest) -> Self {
        NodeRequest {
            id: self.id.and(other.id),
            tags: merge(self.tags, other.tags),
            inputs: {self.inputs.append(&mut other.inputs); self.inputs},
            outputs: {self.outputs.append(&mut other.outputs); self.outputs},
            private: (),
        }
    }
}

/// A request for one or more input services.
///
///
/// # Example
///
/// ```
/// use fxbox_taxonomy::requests::*;
/// use fxbox_taxonomy::devices::*;
///
/// let request = InputRequest::new()
///   .with_parent(NodeId::new("foxbox".to_owned()))
///   .with_kind(ServiceKind::CurrentTimeOfDay);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct InputRequest {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<ServiceId>,

    /// If `Eactly(id)`, return only services that are children of
    /// node `id`.
    #[serde(default)]
    pub parent: Exactly<NodeId>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exatly(k)`, restrict results to services that produce values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ServiceKind>,

    /// If `Some(r)`, restrict results to services that support polling
    /// with the acceptable period.
    #[serde(default)]
    pub poll: Option<Period>,

    /// If `Some(r)`, restrict results to services that support trigger
    /// with the acceptable period.
    #[serde(default)]
    pub trigger: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl InputRequest {
    /// Create a new request that accepts all input services.
    pub fn new() -> Self {
        Self::default()
    }

    /// Restrict to a service with a specific id.
    pub fn with_id(self, id: ServiceId) -> Self {
        InputRequest {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a service with a specific parent.
    pub fn with_parent(self, id: NodeId) -> Self {
        InputRequest {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a service with a specific kind.
    pub fn with_kind(self, kind: ServiceKind) -> Self {
        InputRequest {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to services that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        InputRequest {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to services that support polling with the acceptable
    /// period
    pub fn with_poll(self, period: Period) -> Self {
        InputRequest {
            poll: Period::and_option(self.poll, Some(period)),
            .. self
        }
    }

    /// Restrict to services that support trigger with the acceptable
    /// period
    pub fn with_trigger(self, period: Period) -> Self {
        InputRequest {
            trigger: Period::and_option(self.trigger, Some(period)),
            .. self
        }
    }

    /// Restrict to services that are accepted by two requests.
    pub fn and(self, other: Self) -> Self {
        InputRequest {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            poll: Period::and_option(self.poll, other.poll),
            trigger: Period::and_option(self.trigger, other.trigger),
            private: (),
        }
    }
}

/// A request for one or more output services.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct OutputRequest {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<ServiceId>,

    /// If `Exactly(id)`, return only services that are immediate children
    /// of node `id`.
    #[serde(default)]
    pub parent: Exactly<NodeId>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exactly(k)`, restrict results to services that accept values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ServiceKind>,

    /// If `Some(r)`, restrict results to services that support pushing
    /// with the acceptable period.
    #[serde(default)]
    pub push: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl OutputRequest {
    /// Create a new request that accepts all input services.
    pub fn new() -> Self {
        OutputRequest::default()
    }

    /// Request to a service with a specific id.
    pub fn with_id(self, id: ServiceId) -> Self {
        OutputRequest {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Request to services with a specific parent.
    pub fn with_parent(self, id: NodeId) -> Self {
        OutputRequest {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Request to services with a specific kind.
    pub fn with_kind(self, kind: ServiceKind) -> Self {
        OutputRequest {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to services that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        OutputRequest {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to services that support push with the acceptable
    /// period
    pub fn with_push(self, period: Period) -> Self {
        OutputRequest {
            push: Period::and_option(self.push, Some(period)),
            .. self
        }
    }

    /// Restrict results to services that are accepted by two requests.
    pub fn and(self, other: Self) -> Self {
        OutputRequest {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            push: Period::and_option(self.push, other.push),
            private: (),
        }
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<values::ValDuration>,
    #[serde(default)]
    pub max: Option<values::ValDuration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(max1), Some(max2)) => Some(cmp::min(max1, max2))
        };
        Period {
            min: min,
            max: max
        }
    }

    pub fn and_option(a: Option<Self>, b: Option<Self>) -> Option<Self> {
        match (a, b) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &values::ValDuration) -> bool {
        if let Some(ref min) = self.min {
            if min > duration {
                return false;
            }
        }
        if let Some(ref max) = self.max {
            if max < duration {
                return false;
            }
        }
        return true;
    }

    pub fn matches_option(period: &Option<Self>, duration: &Option<values::ValDuration>) -> bool {
        match (period, duration) {
            (&Some(ref period), &Some(ref duration))
                if !period.matches(duration) =>
                return false,
            (&None, &Some(_)) => return false,
            _ => return true
        }
    }
}
<commit_msg>InputRequest::matches, OutputRequest::matches<commit_after>use devices::{NodeId, ServiceId, ServiceKind, Service, Input, Output};
use util::Exactly;
use values;

use serde::ser::Serializer;
use serde::de::Deserializer;

use std::cmp;

fn merge<T>(mut a: Vec<T>, mut b: Vec<T>) -> Vec<T> where T: Ord {
    a.append(&mut b);
    a.sort();
    a.dedup();
    a
}

/// A request for one or more nodes.
///
///
/// # Example
///
/// ```
/// use fxbox_taxonomy::requests::*;
/// use fxbox_taxonomy::devices::*;
///
/// let request = NodeRequest::new()
///   .with_tags(vec!["entrance".to_owned()])
///   .with_inputs(vec![InputRequest::new() /* can be more restrictive */]);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct NodeRequest {
    /// If `Exactly(id)`, return only the node with the corresponding id.
    #[serde(default)]
    pub id: Exactly<NodeId>,

    ///  Restrict results to nodes that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// Restrict results to nodes that have all the inputs in `inputs`.
    #[serde(default)]
    pub inputs: Vec<InputRequest>,

    /// Restrict results to nodes that have all the outputs in `outputs`.
    #[serde(default)]
    pub outputs: Vec<OutputRequest>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl NodeRequest {
    /// Create a new request that accepts all nodes.
    pub fn new() -> Self {
        Self::default()
    }

    /// Request for a node with a specific id.
    pub fn with_id(self, id: NodeId) -> Self {
        NodeRequest {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    ///  Restrict results to nodes that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        NodeRequest {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict results to nodes that have all the inputs in `inputs`.
    pub fn with_inputs(mut self, mut inputs: Vec<InputRequest>) -> Self {
        NodeRequest {
            inputs: {self.inputs.append(&mut inputs); self.inputs},
            .. self
        }
    }

    /// Restrict results to nodes that have all the outputs in `outputs`.
    pub fn with_outputs(mut self, mut outputs: Vec<OutputRequest>) -> Self {
        NodeRequest {
            outputs: {self.outputs.append(&mut outputs); self.outputs},
            .. self
        }
    }

    /// Restrict results to nodes that are accepted by two requests.
    pub fn and(mut self, mut other: NodeRequest) -> Self {
        NodeRequest {
            id: self.id.and(other.id),
            tags: merge(self.tags, other.tags),
            inputs: {self.inputs.append(&mut other.inputs); self.inputs},
            outputs: {self.outputs.append(&mut other.outputs); self.outputs},
            private: (),
        }
    }
}

/// A request for one or more input services.
///
///
/// # Example
///
/// ```
/// use fxbox_taxonomy::requests::*;
/// use fxbox_taxonomy::devices::*;
///
/// let request = InputRequest::new()
///   .with_parent(NodeId::new("foxbox".to_owned()))
///   .with_kind(ServiceKind::CurrentTimeOfDay);
/// ```
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct InputRequest {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<ServiceId>,

    /// If `Eactly(id)`, return only services that are children of
    /// node `id`.
    #[serde(default)]
    pub parent: Exactly<NodeId>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exatly(k)`, restrict results to services that produce values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ServiceKind>,

    /// If `Some(r)`, restrict results to services that support polling
    /// with the acceptable period.
    #[serde(default)]
    pub poll: Option<Period>,

    /// If `Some(r)`, restrict results to services that support trigger
    /// with the acceptable period.
    #[serde(default)]
    pub trigger: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl InputRequest {
    /// Create a new request that accepts all input services.
    pub fn new() -> Self {
        Self::default()
    }

    /// Restrict to a service with a specific id.
    pub fn with_id(self, id: ServiceId) -> Self {
        InputRequest {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a service with a specific parent.
    pub fn with_parent(self, id: NodeId) -> Self {
        InputRequest {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Restrict to a service with a specific kind.
    pub fn with_kind(self, kind: ServiceKind) -> Self {
        InputRequest {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to services that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        InputRequest {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to services that support polling with the acceptable
    /// period
    pub fn with_poll(self, period: Period) -> Self {
        InputRequest {
            poll: Period::and_option(self.poll, Some(period)),
            .. self
        }
    }

    /// Restrict to services that support trigger with the acceptable
    /// period
    pub fn with_trigger(self, period: Period) -> Self {
        InputRequest {
            trigger: Period::and_option(self.trigger, Some(period)),
            .. self
        }
    }

    /// Restrict to services that are accepted by two requests.
    pub fn and(self, other: Self) -> Self {
        InputRequest {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            poll: Period::and_option(self.poll, other.poll),
            trigger: Period::and_option(self.trigger, other.trigger),
            private: (),
        }
    }

    /// Determine if a service is matched by this request.
    pub fn matches(&self, service: &Service<Input>) -> bool {
        if !self.id.matches(&service.id) {
            return false;
        }
        if !self.parent.matches(&service.node) {
            return false;
        }
        if !self.kind.matches(&service.mechanism.kind) {
            return false;
        }
        if !Period::matches_option(&self.poll, &service.mechanism.poll) {
            return false;
        }
        if !Period::matches_option(&self.trigger, &service.mechanism.trigger) {
            return false;
        }
        if !has_requested_tags(&self.tags, &service.tags) {
            return false;
        }
        return true;
    }
}

/// A request for one or more output services.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct OutputRequest {
    /// If `Exactly(id)`, return only the service with the corresponding id.
    #[serde(default)]
    pub id: Exactly<ServiceId>,

    /// If `Exactly(id)`, return only services that are immediate children
    /// of node `id`.
    #[serde(default)]
    pub parent: Exactly<NodeId>,

    ///  Restrict results to services that have all the tags in `tags`.
    #[serde(default)]
    pub tags: Vec<String>,

    /// If `Exactly(k)`, restrict results to services that accept values
    /// of kind `k`.
    #[serde(default)]
    pub kind: Exactly<ServiceKind>,

    /// If `Some(r)`, restrict results to services that support pushing
    /// with the acceptable period.
    #[serde(default)]
    pub push: Option<Period>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

impl OutputRequest {
    /// Create a new request that accepts all input services.
    pub fn new() -> Self {
        OutputRequest::default()
    }

    /// Request to a service with a specific id.
    pub fn with_id(self, id: ServiceId) -> Self {
        OutputRequest {
            id: self.id.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Request to services with a specific parent.
    pub fn with_parent(self, id: NodeId) -> Self {
        OutputRequest {
            parent: self.parent.and(Exactly::Exactly(id)),
            .. self
        }
    }

    /// Request to services with a specific kind.
    pub fn with_kind(self, kind: ServiceKind) -> Self {
        OutputRequest {
            kind: self.kind.and(Exactly::Exactly(kind)),
            .. self
        }
    }

    ///  Restrict to services that have all the tags in `tags`.
    pub fn with_tags(self, tags: Vec<String>) -> Self {
        OutputRequest {
            tags: merge(self.tags, tags),
            .. self
        }
    }

    /// Restrict to services that support push with the acceptable
    /// period
    pub fn with_push(self, period: Period) -> Self {
        OutputRequest {
            push: Period::and_option(self.push, Some(period)),
            .. self
        }
    }

    /// Restrict results to services that are accepted by two requests.
    pub fn and(self, other: Self) -> Self {
        OutputRequest {
            id: self.id.and(other.id),
            parent: self.parent.and(other.parent),
            tags: merge(self.tags, other.tags),
            kind: self.kind.and(other.kind),
            push: Period::and_option(self.push, other.push),
            private: (),
        }
    }

    /// Determine if a service is matched by this request.
    pub fn matches(&self, service: &Service<Output>) -> bool {
        if !self.id.matches(&service.id) {
            return false;
        }
        if !self.parent.matches(&service.node) {
            return false;
        }
        if !self.kind.matches(&service.mechanism.kind) {
            return false;
        }
        if !Period::matches_option(&self.push, &service.mechanism.push) {
            return false;
        }
        if !has_requested_tags(&self.tags, &service.tags) {
            return false;
        }
        return true;
    }
}

/// An acceptable interval of time.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Period {
    #[serde(default)]
    pub min: Option<values::ValDuration>,
    #[serde(default)]
    pub max: Option<values::ValDuration>,
}
impl Period {
    pub fn and(self, other: Self) -> Self {
        let min = match (self.min, other.min) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(min1), Some(min2)) => Some(cmp::max(min1, min2))
        };
        let max = match (self.max, other.max) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(max1), Some(max2)) => Some(cmp::min(max1, max2))
        };
        Period {
            min: min,
            max: max
        }
    }

    pub fn and_option(a: Option<Self>, b: Option<Self>) -> Option<Self> {
        match (a, b) {
            (None, x@_) => x,
            (x@_, None) => x,
            (Some(a), Some(b)) => Some(a.and(b))
        }
    }

    pub fn matches(&self, duration: &values::ValDuration) -> bool {
        if let Some(ref min) = self.min {
            if min > duration {
                return false;
            }
        }
        if let Some(ref max) = self.max {
            if max < duration {
                return false;
            }
        }
        return true;
    }

    pub fn matches_option(period: &Option<Self>, duration: &Option<values::ValDuration>) -> bool {
        match (period, duration) {
            (&Some(ref period), &Some(ref duration))
                if !period.matches(duration) =>
                return false,
            (&None, &Some(_)) => return false,
            _ => return true
        }
    }
}

fn has_requested_tags(actual: &Vec<String>, requested: &Vec<String>) -> bool {
    for tag in &*actual {
        if requested.iter().find(|x| *x == tag).is_none() {
            return false;
        }
    }
    return true;
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::rc::Rc;

use futures::Future;
use http::{Method, StatusCode};
use smallvec::SmallVec;

use error::Error;
use handler::{AsyncResult, FromRequest, Handler, Responder};
use httprequest::HttpRequest;
use httpresponse::HttpResponse;
use middleware::Middleware;
use pred;
use route::Route;

/// *Resource* is an entry in route table which corresponds to requested URL.
///
/// Resource in turn has at least one route.
/// Route consists of an object that implements `Handler` trait (handler)
/// and list of predicates (objects that implement `Predicate` trait).
/// Route uses builder-like pattern for configuration.
/// During request handling, resource object iterate through all routes
/// and check all predicates for specific route, if request matches all
/// predicates route route considered matched and route handler get called.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{App, HttpResponse, http};
///
/// fn main() {
///     let app = App::new()
///         .resource(
///             "/", |r| r.method(http::Method::GET).f(|r| HttpResponse::Ok()))
///         .finish();
/// }
pub struct ResourceHandler<S = ()> {
    name: String,
    state: PhantomData<S>,
    routes: SmallVec<[Route<S>; 3]>,
    middlewares: Rc<Vec<Box<Middleware<S>>>>,
}

impl<S> Default for ResourceHandler<S> {
    fn default() -> Self {
        ResourceHandler {
            name: String::new(),
            state: PhantomData,
            routes: SmallVec::new(),
            middlewares: Rc::new(Vec::new()),
        }
    }
}

impl<S> ResourceHandler<S> {
    pub(crate) fn default_not_found() -> Self {
        ResourceHandler {
            name: String::new(),
            state: PhantomData,
            routes: SmallVec::new(),
            middlewares: Rc::new(Vec::new()),
        }
    }

    /// Set resource name
    pub fn name<T: Into<String>>(&mut self, name: T) {
        self.name = name.into();
    }

    pub(crate) fn get_name(&self) -> &str {
        &self.name
    }
}

impl<S: 'static> ResourceHandler<S> {
    /// Register a new route and return mutable reference to *Route* object.
    /// *Route* is used for route configuration, i.e. adding predicates,
    /// setting up handler.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::*;
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .resource("/", |r| {
    ///             r.route()
    ///                 .filter(pred::Any(pred::Get()).or(pred::Put()))
    ///                 .filter(pred::Header("Content-Type", "text/plain"))
    ///                 .f(|r| HttpResponse::Ok())
    ///         })
    ///         .finish();
    /// }
    /// ```
    pub fn route(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap()
    }

    /// Register a new `GET` route.
    pub fn get(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Get())
    }

    /// Register a new `POST` route.
    pub fn post(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Post())
    }

    /// Register a new `PUT` route.
    pub fn put(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Put())
    }

    /// Register a new `DELETE` route.
    pub fn delete(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Delete())
    }

    /// Register a new `HEAD` route.
    pub fn head(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Head())
    }

    /// Register a new route and add method check to route.
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().filter(pred::Get()).f(index));
    /// ```
    pub fn method(&mut self, method: Method) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Method(method))
    }

    /// Register a new route and add handler object.
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn handler(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().h(handler));
    /// ```
    pub fn h<H: Handler<S>>(&mut self, handler: H) {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().h(handler)
    }

    /// Register a new route and add handler function.
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().f(index));
    /// ```
    pub fn f<F, R>(&mut self, handler: F)
    where
        F: Fn(HttpRequest<S>) -> R + 'static,
        R: Responder + 'static,
    {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().f(handler)
    }

    /// Register a new route and add handler.
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().with(index));
    /// ```
    pub fn with<T, F, R>(&mut self, handler: F)
    where
        F: Fn(T) -> R + 'static,
        R: Responder + 'static,
        T: FromRequest<S> + 'static,
    {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().with(handler);
    }

    /// Register a new route and add async handler.
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # extern crate futures;
    /// # use actix_web::*;
    /// # use futures::future::Future;
    /// # fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
    /// #     unimplemented!()
    /// # }
    /// App::new().resource("/", |r| r.route().with_async(index));
    /// ```
    pub fn with_async<T, F, R, I, E>(&mut self, handler: F)
    where
        F: Fn(T) -> R + 'static,
        R: Future<Item = I, Error = E> + 'static,
        I: Responder + 'static,
        E: Into<Error> + 'static,
        T: FromRequest<S> + 'static,
    {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().with_async(handler);
    }

    /// Register a resource middleware
    ///
    /// This is similar to `App's` middlewares, but
    /// middlewares get invoked on resource level.
    ///
    /// *Note* `Middleware::finish()` fires right after response get
    /// prepared. It does not wait until body get sent to peer.
    pub fn middleware<M: Middleware<S>>(&mut self, mw: M) {
        Rc::get_mut(&mut self.middlewares)
            .unwrap()
            .push(Box::new(mw));
    }

    pub(crate) fn handle(
        &mut self, mut req: HttpRequest<S>, default: Option<&mut ResourceHandler<S>>,
    ) -> AsyncResult<HttpResponse> {
        for route in &mut self.routes {
            if route.check(&mut req) {
                return if self.middlewares.is_empty() {
                    route.handle(req)
                } else {
                    route.compose(req, Rc::clone(&self.middlewares))
                };
            }
        }
        if let Some(resource) = default {
            resource.handle(req, None)
        } else {
            AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND))
        }
    }
}
<commit_msg>Add more docs to ResourceHandler API<commit_after>use std::marker::PhantomData;
use std::rc::Rc;

use futures::Future;
use http::{Method, StatusCode};
use smallvec::SmallVec;

use error::Error;
use handler::{AsyncResult, FromRequest, Handler, Responder};
use httprequest::HttpRequest;
use httpresponse::HttpResponse;
use middleware::Middleware;
use pred;
use route::Route;

/// *Resource* is an entry in route table which corresponds to requested URL.
///
/// Resource in turn has at least one route.
/// Route consists of an object that implements `Handler` trait (handler)
/// and list of predicates (objects that implement `Predicate` trait).
/// Route uses builder-like pattern for configuration.
/// During request handling, resource object iterate through all routes
/// and check all predicates for specific route, if request matches all
/// predicates route route considered matched and route handler get called.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{App, HttpResponse, http};
///
/// fn main() {
///     let app = App::new()
///         .resource(
///             "/", |r| r.method(http::Method::GET).f(|r| HttpResponse::Ok()))
///         .finish();
/// }
pub struct ResourceHandler<S = ()> {
    name: String,
    state: PhantomData<S>,
    routes: SmallVec<[Route<S>; 3]>,
    middlewares: Rc<Vec<Box<Middleware<S>>>>,
}

impl<S> Default for ResourceHandler<S> {
    fn default() -> Self {
        ResourceHandler {
            name: String::new(),
            state: PhantomData,
            routes: SmallVec::new(),
            middlewares: Rc::new(Vec::new()),
        }
    }
}

impl<S> ResourceHandler<S> {
    pub(crate) fn default_not_found() -> Self {
        ResourceHandler {
            name: String::new(),
            state: PhantomData,
            routes: SmallVec::new(),
            middlewares: Rc::new(Vec::new()),
        }
    }

    /// Set resource name
    pub fn name<T: Into<String>>(&mut self, name: T) {
        self.name = name.into();
    }

    pub(crate) fn get_name(&self) -> &str {
        &self.name
    }
}

impl<S: 'static> ResourceHandler<S> {
    /// Register a new route and return mutable reference to *Route* object.
    /// *Route* is used for route configuration, i.e. adding predicates,
    /// setting up handler.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::*;
    ///
    /// fn main() {
    ///     let app = App::new()
    ///         .resource("/", |r| {
    ///             r.route()
    ///                 .filter(pred::Any(pred::Get()).or(pred::Put()))
    ///                 .filter(pred::Header("Content-Type", "text/plain"))
    ///                 .f(|r| HttpResponse::Ok())
    ///         })
    ///         .finish();
    /// }
    /// ```
    pub fn route(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap()
    }

    /// Register a new `GET` route.
    pub fn get(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Get())
    }

    /// Register a new `POST` route.
    pub fn post(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Post())
    }

    /// Register a new `PUT` route.
    pub fn put(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Put())
    }

    /// Register a new `DELETE` route.
    pub fn delete(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Delete())
    }

    /// Register a new `HEAD` route.
    pub fn head(&mut self) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Head())
    }

    /// Register a new route and add method check to route.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::*;
    /// fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    ///
    /// App::new().resource("/", |r| r.method(http::Method::GET).f(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().filter(pred::Get()).f(index));
    /// ```
    pub fn method(&mut self, method: Method) -> &mut Route<S> {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().filter(pred::Method(method))
    }

    /// Register a new route and add handler object.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::*;
    /// fn handler(req: HttpRequest) -> HttpResponse { unimplemented!() }
    ///
    /// App::new().resource("/", |r| r.h(handler));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn handler(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().h(handler));
    /// ```
    pub fn h<H: Handler<S>>(&mut self, handler: H) {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().h(handler)
    }

    /// Register a new route and add handler function.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::*;
    /// fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    ///
    /// App::new().resource("/", |r| r.f(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().f(index));
    /// ```
    pub fn f<F, R>(&mut self, handler: F)
    where
        F: Fn(HttpRequest<S>) -> R + 'static,
        R: Responder + 'static,
    {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().f(handler)
    }

    /// Register a new route and add handler.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// use actix_web::*;
    /// fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    ///
    /// App::new().resource("/", |r| r.with(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # use actix_web::*;
    /// # fn index(req: HttpRequest) -> HttpResponse { unimplemented!() }
    /// App::new().resource("/", |r| r.route().with(index));
    /// ```
    pub fn with<T, F, R>(&mut self, handler: F)
    where
        F: Fn(T) -> R + 'static,
        R: Responder + 'static,
        T: FromRequest<S> + 'static,
    {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().with(handler);
    }

    /// Register a new route and add async handler.
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # extern crate futures;
    /// use actix_web::*;
    /// use futures::future::Future;
    ///
    /// fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
    ///     unimplemented!()
    /// }
    ///
    /// App::new().resource("/", |r| r.with_async(index));
    /// ```
    ///
    /// This is shortcut for:
    ///
    /// ```rust
    /// # extern crate actix_web;
    /// # extern crate futures;
    /// # use actix_web::*;
    /// # use futures::future::Future;
    /// # fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
    /// #     unimplemented!()
    /// # }
    /// App::new().resource("/", |r| r.route().with_async(index));
    /// ```
    pub fn with_async<T, F, R, I, E>(&mut self, handler: F)
    where
        F: Fn(T) -> R + 'static,
        R: Future<Item = I, Error = E> + 'static,
        I: Responder + 'static,
        E: Into<Error> + 'static,
        T: FromRequest<S> + 'static,
    {
        self.routes.push(Route::default());
        self.routes.last_mut().unwrap().with_async(handler);
    }

    /// Register a resource middleware
    ///
    /// This is similar to `App's` middlewares, but
    /// middlewares get invoked on resource level.
    ///
    /// *Note* `Middleware::finish()` fires right after response get
    /// prepared. It does not wait until body get sent to peer.
    pub fn middleware<M: Middleware<S>>(&mut self, mw: M) {
        Rc::get_mut(&mut self.middlewares)
            .unwrap()
            .push(Box::new(mw));
    }

    pub(crate) fn handle(
        &mut self, mut req: HttpRequest<S>, default: Option<&mut ResourceHandler<S>>,
    ) -> AsyncResult<HttpResponse> {
        for route in &mut self.routes {
            if route.check(&mut req) {
                return if self.middlewares.is_empty() {
                    route.handle(req)
                } else {
                    route.compose(req, Rc::clone(&self.middlewares))
                };
            }
        }
        if let Some(resource) = default {
            resource.handle(req, None)
        } else {
            AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND))
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{Read, Write};

use battle::units::UnitType;
use resources::{FONT_HEIGHT, CHARACTER_GAP, ImageSource};
use utils::clamp;

use toml;
use toml::Value;

use std::collections::BTreeMap;
use std::collections::btree_map::Entry;

const FILENAME: &str = "settings.toml";
const MIN_MAP_SIZE: usize = 10;
const MAX_MAP_SIZE: usize = 60;
const DEFAULT_VOLUME: u8 = 100;
const DEFAULT_UI_SCALE: u8 = 2;
const MAX_UI_SCALE: u8 = 4;

type Table = BTreeMap<String, Value>;

// Extract the table out of a toml value
fn to_table(value: Value) -> Option<Table> {
    if let Value::Table(table) = value {
        Some(table)
    } else {
        None
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Settings {
    pub volume: u8,
    pub ui_scale: u8,
    pub window_width: u32,
    pub window_height: u32,
    pub fullscreen: bool,
    pub savegames: String
}

// The default settings
impl Default for Settings {
    fn default() -> Settings {
        Settings {
            volume: DEFAULT_VOLUME,
            ui_scale: DEFAULT_UI_SCALE,
            window_width: 960,
            window_height: 540,
            fullscreen: false,
            savegames: "savegames".into()
        }
    }
}

impl Settings {
    // Load the settings or use the defaults
    pub fn load() -> Settings {
        let mut buffer = String::new();
        let mut settings = Settings::default();

        // If the settings were able to be loaded and parsed into a toml table
        if let Some(loaded) = File::open(FILENAME).ok()
            .and_then(|mut file| file.read_to_string(&mut buffer).ok())
            .and_then(|_| buffer.parse::<Value>().ok())
            .and_then(to_table) {

            let mut settings_table = settings.to_table();

            // Change the default settings to the new keys
            for (key, value) in loaded {
                match settings_table.entry(key) {
                    Entry::Occupied(mut entry) => {
                        entry.insert(value);
                    },
                    Entry::Vacant(entry) => eprintln!("Warning: '{}' key '{}' does not exist.", FILENAME, entry.key())
                }
            }

            // Deserialize the settings again
            if let Ok(settings_struct) = Value::Table(settings_table).try_into() {
                settings = settings_struct;
            }
        } else {
            eprintln!("Warning: '{}' failed to load.", FILENAME);
        }

        settings.clamp();
        settings
    }

    // Save the settings
    pub fn save(&self) {
        if let Ok(mut file) = File::create(FILENAME) {
            let default = Settings::default().to_table();
            let mut settings = self.to_table();

            // Remove the settings that are the default
            for (key, value) in default {
                if settings[&key] == value {
                    settings.remove(&key);
                }
            }

            // Save the rest
            if let Ok(buffer) = toml::to_vec(&Value::from(settings)) {
                if file.write_all(&buffer).is_err() {
                    println!("Warnings: Failed to write to '{}'", FILENAME);
                }
            }
        } else {
            println!("Warning: Failed to open '{}'", FILENAME);
        }
    }

    pub fn ui_scale(&self) -> f32 {
        f32::from(self.ui_scale)
    }

    // Make sure the volume isn't too high
    pub fn clamp(&mut self) {
        self.volume = clamp(self.volume, 0, DEFAULT_VOLUME);
        self.ui_scale = clamp(self.ui_scale, 1, MAX_UI_SCALE);
    }

    // Get the height that a string would be rendered at
    pub fn font_height(&self) -> f32 {
        FONT_HEIGHT * self.ui_scale()
    }

    // Get the width that a string would be rendered at
    pub fn font_width(&self, string: &str) -> f32 {
        string.chars().fold(0.0, |total, character| total + (character.width() + CHARACTER_GAP) * self.ui_scale())
    }

    // Reset the settings
    pub fn reset(&mut self) {
        self.volume = DEFAULT_VOLUME;
        self.ui_scale = DEFAULT_UI_SCALE;
    }

    // Convert the settings into a B-Tree map of key-value pairs
    fn to_table(&self) -> Table {
        // This should never fail
        Value::try_from(&self).ok().and_then(to_table).unwrap()
    }
}

// A struct for holding the initialization settings for a skirmish
pub struct SkirmishSettings {
    pub cols: usize,
    pub rows: usize,
    pub player_units: usize,
    pub ai_units: usize,
    pub player_unit_type: UnitType,
    pub ai_unit_type: UnitType,
    pub light: f32
}

// The default skirmish settings
impl Default for SkirmishSettings {
    fn default() -> SkirmishSettings {
        SkirmishSettings {
            cols: 30,
            rows: 30,
            player_units: 6,
            ai_units: 4,
            player_unit_type: UnitType::Squaddie,
            ai_unit_type: UnitType::Machine,
            light: 1.0
        }
    }
}

impl SkirmishSettings {
    // Ensure that the settings are between their min and max values
    pub fn clamp(&mut self) {
        self.cols = clamp(self.cols, MIN_MAP_SIZE, MAX_MAP_SIZE);
        self.rows = clamp(self.rows, MIN_MAP_SIZE, MAX_MAP_SIZE);
        self.player_units = clamp(self.player_units, 1, self.cols);
        self.ai_units = clamp(self.ai_units, 1, self.cols);
        self.light = clamp(self.light, 0.0, 1.0);
    }

    // Switch the player unit type
    pub fn change_player_unit_type(&mut self) {
        self.player_unit_type = match self.player_unit_type {
            UnitType::Squaddie => UnitType::Machine,
            UnitType::Machine => UnitType::Squaddie
        }
    }

    // Switch the ai unit type
    pub fn change_ai_unit_type(&mut self) {
        self.ai_unit_type = match self.ai_unit_type {
            UnitType::Squaddie => UnitType::Machine,
            UnitType::Machine => UnitType::Squaddie
        }
    }
}

#[test]
fn load_save() {
    let mut settings = Settings::default();

    // Test clamping the settings

    settings.volume = 255;
    settings.ui_scale = 100;

    settings.clamp();

    assert_eq!(settings.volume, DEFAULT_VOLUME);
    assert_eq!(settings.ui_scale, MAX_UI_SCALE);

    settings.volume = 99;

    // Test saving and loading the settings

    settings.save();

    let settings_2 = Settings::load();

    assert_eq!(settings_2.volume, 99);

    settings.reset();
    settings.save();
}<commit_msg>Removed settings.toml warning if it doesn't exist<commit_after>use std::fs::File;
use std::io::{Read, Write};

use battle::units::UnitType;
use resources::{FONT_HEIGHT, CHARACTER_GAP, ImageSource};
use utils::clamp;

use toml;
use toml::Value;

use std::collections::BTreeMap;
use std::collections::btree_map::Entry;

const FILENAME: &str = "settings.toml";
const MIN_MAP_SIZE: usize = 10;
const MAX_MAP_SIZE: usize = 60;
const DEFAULT_VOLUME: u8 = 100;
const DEFAULT_UI_SCALE: u8 = 2;
const MAX_UI_SCALE: u8 = 4;

type Table = BTreeMap<String, Value>;

// Extract the table out of a toml value
fn to_table(value: Value) -> Option<Table> {
    if let Value::Table(table) = value {
        Some(table)
    } else {
        None
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Settings {
    pub volume: u8,
    pub ui_scale: u8,
    pub window_width: u32,
    pub window_height: u32,
    pub fullscreen: bool,
    pub savegames: String
}

// The default settings
impl Default for Settings {
    fn default() -> Settings {
        Settings {
            volume: DEFAULT_VOLUME,
            ui_scale: DEFAULT_UI_SCALE,
            window_width: 960,
            window_height: 540,
            fullscreen: false,
            savegames: "savegames".into()
        }
    }
}

impl Settings {
    // Load the settings or use the defaults
    pub fn load() -> Settings {
        let mut buffer = String::new();
        let mut settings = Settings::default();

        // If the settings were able to be loaded and parsed into a toml table
        if let Some(loaded) = File::open(FILENAME).ok()
            .and_then(|mut file| file.read_to_string(&mut buffer).ok())
            .and_then(|_| buffer.parse::<Value>().ok())
            .and_then(to_table) {

            let mut settings_table = settings.to_table();

            // Change the default settings to the new keys
            for (key, value) in loaded {
                match settings_table.entry(key) {
                    Entry::Occupied(mut entry) => {
                        entry.insert(value);
                    },
                    Entry::Vacant(entry) => eprintln!("Warning: '{}' key '{}' does not exist.", FILENAME, entry.key())
                }
            }

            // Deserialize the settings again
            if let Ok(settings_struct) = Value::Table(settings_table).try_into() {
                settings = settings_struct;
            }
        }

        settings.clamp();
        settings
    }

    // Save the settings
    pub fn save(&self) {
        if let Ok(mut file) = File::create(FILENAME) {
            let default = Settings::default().to_table();
            let mut settings = self.to_table();

            // Remove the settings that are the default
            for (key, value) in default {
                if settings[&key] == value {
                    settings.remove(&key);
                }
            }

            // Save the rest
            if let Ok(buffer) = toml::to_vec(&Value::from(settings)) {
                if file.write_all(&buffer).is_err() {
                    eprintln!("Warnings: Failed to write to '{}'", FILENAME);
                }
            }
        } else {
            eprintln!("Warning: Failed to open '{}'", FILENAME);
        }
    }

    pub fn ui_scale(&self) -> f32 {
        f32::from(self.ui_scale)
    }

    // Make sure the volume isn't too high
    pub fn clamp(&mut self) {
        self.volume = clamp(self.volume, 0, DEFAULT_VOLUME);
        self.ui_scale = clamp(self.ui_scale, 1, MAX_UI_SCALE);
    }

    // Get the height that a string would be rendered at
    pub fn font_height(&self) -> f32 {
        FONT_HEIGHT * self.ui_scale()
    }

    // Get the width that a string would be rendered at
    pub fn font_width(&self, string: &str) -> f32 {
        string.chars().fold(0.0, |total, character| total + (character.width() + CHARACTER_GAP) * self.ui_scale())
    }

    // Reset the settings
    pub fn reset(&mut self) {
        self.volume = DEFAULT_VOLUME;
        self.ui_scale = DEFAULT_UI_SCALE;
    }

    // Convert the settings into a B-Tree map of key-value pairs
    fn to_table(&self) -> Table {
        // This should never fail
        Value::try_from(&self).ok().and_then(to_table).unwrap()
    }
}

// A struct for holding the initialization settings for a skirmish
pub struct SkirmishSettings {
    pub cols: usize,
    pub rows: usize,
    pub player_units: usize,
    pub ai_units: usize,
    pub player_unit_type: UnitType,
    pub ai_unit_type: UnitType,
    pub light: f32
}

// The default skirmish settings
impl Default for SkirmishSettings {
    fn default() -> SkirmishSettings {
        SkirmishSettings {
            cols: 30,
            rows: 30,
            player_units: 6,
            ai_units: 4,
            player_unit_type: UnitType::Squaddie,
            ai_unit_type: UnitType::Machine,
            light: 1.0
        }
    }
}

impl SkirmishSettings {
    // Ensure that the settings are between their min and max values
    pub fn clamp(&mut self) {
        self.cols = clamp(self.cols, MIN_MAP_SIZE, MAX_MAP_SIZE);
        self.rows = clamp(self.rows, MIN_MAP_SIZE, MAX_MAP_SIZE);
        self.player_units = clamp(self.player_units, 1, self.cols);
        self.ai_units = clamp(self.ai_units, 1, self.cols);
        self.light = clamp(self.light, 0.0, 1.0);
    }

    // Switch the player unit type
    pub fn change_player_unit_type(&mut self) {
        self.player_unit_type = match self.player_unit_type {
            UnitType::Squaddie => UnitType::Machine,
            UnitType::Machine => UnitType::Squaddie
        }
    }

    // Switch the ai unit type
    pub fn change_ai_unit_type(&mut self) {
        self.ai_unit_type = match self.ai_unit_type {
            UnitType::Squaddie => UnitType::Machine,
            UnitType::Machine => UnitType::Squaddie
        }
    }
}

#[test]
fn load_save() {
    let mut settings = Settings::default();

    // Test clamping the settings

    settings.volume = 255;
    settings.ui_scale = 100;

    settings.clamp();

    assert_eq!(settings.volume, DEFAULT_VOLUME);
    assert_eq!(settings.ui_scale, MAX_UI_SCALE);

    settings.volume = 99;

    // Test saving and loading the settings

    settings.save();

    let settings_2 = Settings::load();

    assert_eq!(settings_2.volume, 99);

    settings.reset();
    settings.save();
}<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::fmt;
use std::hash::{self, Hash};
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ops;
use std::ptr;

#[cfg(not(feature = "std"))]
use alloc::alloc::{self, Layout};
#[cfg(feature = "std")]
use std::alloc::{self, Layout};

#[cfg(feature = "coerce")]
use std::marker::Unsize;
#[cfg(feature = "coerce")]
use std::ops::CoerceUnsized;

#[cfg(feature = "coerce")]
impl<T: ?Sized + Unsize<U>, U: ?Sized, Space> CoerceUnsized<SmallBox<U, Space>>
    for SmallBox<T, Space>
{}

/// Box value on stack or heap depending on its size
///
/// This macro is similar to `SmallBox::new`, which is used to create a new `Smallbox` instance,
/// but relaxing the constraint of `T: Sized`.
/// In order to do that, this macro will check the coersion rules between type `T` and the
/// expression type. This macro invokes a complier error for any invalid type coersion.
///
/// You can think that it has the signature of `smallbox!<U: Sized, T: ?Sized>(val: U) -> SmallBox<T, Space>`
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate smallbox;
///
/// # fn main() {
/// use smallbox::SmallBox;
/// use smallbox::space::*;
///
/// let small: SmallBox<[usize], S4> = smallbox!([0usize; 2]);
/// let large: SmallBox<[usize], S4> = smallbox!([1usize; 8]);
///
/// assert_eq!(small.len(), 2);
/// assert_eq!(large[7], 1);
///
/// assert!(large.is_heap() == true);
/// # }
/// ```
#[macro_export]
macro_rules! smallbox {
    ( $e: expr ) => {{
        let val = $e;
        let ptr = &val as *const _;
        #[allow(unsafe_code)]
        unsafe {
            $crate::SmallBox::new_unchecked(val, ptr)
        }
    }};
}

/// An optimized box that store value on stack or heap depending on its size
pub struct SmallBox<T: ?Sized, Space> {
    space: ManuallyDrop<Space>,
    ptr: *const T,
    _phantom: PhantomData<T>,
}

impl<T: ?Sized, Space> SmallBox<T, Space> {
    /// Box value on stack or heap depending on its size.
    ///
    /// # Example
    ///
    /// ```
    /// use smallbox::SmallBox;
    /// use smallbox::space::*;
    ///
    /// let small: SmallBox<_, S4> = SmallBox::new([0usize; 2]);
    /// let large: SmallBox<_, S4> = SmallBox::new([1usize; 8]);
    ///
    /// assert_eq!(small.len(), 2);
    /// assert_eq!(large[7], 1);
    ///
    /// assert!(large.is_heap() == true);
    /// ```
    pub fn new(val: T) -> SmallBox<T, Space>
    where
        T: Sized,
    {
        smallbox!(val)
    }

    #[doc(hidden)]
    pub unsafe fn new_unchecked<U>(val: U, ptr: *const T) -> SmallBox<T, Space>
    where
        U: Sized,
    {
        let result = Self::new_copy(&val, ptr);
        mem::forget(val);
        result
    }

    /// Change the capacity of `SmallBox`
    ///
    /// This method may move stack-allocated data to heap
    /// if the inline space is not sufficient. Once the data
    /// is stored on heap, it'll never be moved again.
    ///
    /// # Example
    ///
    /// ```
    /// use smallbox::SmallBox;
    /// use smallbox::space::{S2, S4};
    ///
    /// let s: SmallBox::<_, S4> = SmallBox::new([0usize; 4]);
    /// let m: SmallBox::<_, S2> = s.resize();
    /// ```
    pub fn resize<ToSpace>(self) -> SmallBox<T, ToSpace> {
        unsafe {
            let result = if self.is_heap() {
                // don't touch anything if the data is already on heap
                let mut space = ManuallyDrop::new(mem::uninitialized::<ToSpace>());
                SmallBox {
                    space,
                    ptr: self.ptr,
                    _phantom: PhantomData,
                }
            } else {
                let val: &T = &*self;
                SmallBox::<T, ToSpace>::new_copy(val, val as *const T)
            };

            mem::forget(self);

            result
        }
    }

    /// Returns true if the data is heap-allocated
    pub fn is_heap(&self) -> bool {
        !self.ptr.is_null()
    }

    unsafe fn new_copy<U>(val: &U, ptr: *const T) -> SmallBox<T, Space>
    where
        U: ?Sized,
    {
        let mut space = ManuallyDrop::new(mem::uninitialized::<Space>());

        let (ptr_addr, ptr_copy): (*const u8, *mut u8) = if mem::size_of_val::<U>(val)
            > mem::size_of::<Space>()
            || mem::align_of_val::<U>(val) > mem::align_of::<Space>()
        {
            // Heap
            let layout = Layout::for_value::<U>(val);
            let heap_ptr = alloc::alloc(layout);

            (heap_ptr, heap_ptr)
        } else {
            // Stack
            (ptr::null(), mem::transmute(&mut space))
        };

        let mut ptr = ptr;
        let ptr_ptr = &mut ptr as *mut _ as *mut usize;
        ptr_ptr.write(ptr_addr as usize);

        ptr::copy_nonoverlapping(
            val as *const _ as *const u8,
            ptr_copy,
            mem::size_of_val::<U>(val),
        );

        SmallBox {
            space,
            ptr,
            _phantom: PhantomData,
        }
    }

    unsafe fn as_ptr(&self) -> *const T {
        let mut ptr = self.ptr;

        if !self.is_heap() {
            let ptr_ptr = &mut ptr as *mut _ as *mut usize;
            ptr_ptr.write(mem::transmute(&self.space));
        }

        ptr
    }
}

impl<T: ?Sized, Space> ops::Deref for SmallBox<T, Space> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.as_ptr() }
    }
}

impl<T: ?Sized, Space> ops::DerefMut for SmallBox<T, Space> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *(self.as_ptr() as *const _ as *mut _) }
    }
}

impl<T: ?Sized, Space> ops::Drop for SmallBox<T, Space> {
    fn drop(&mut self) {
        unsafe {
            let layout = Layout::for_value::<T>(&*self);
            ptr::drop_in_place::<T>(&mut **self);
            if self.is_heap() {
                alloc::dealloc(self.ptr as *mut u8, layout);
            }
        }
    }
}

impl<T: Clone, Space> Clone for SmallBox<T, Space>
where
    T: Sized,
{
    fn clone(&self) -> Self {
        let val: &T = &*self;
        SmallBox::new(val.clone())
    }
}

impl<T: ?Sized + fmt::Display, Space> fmt::Display for SmallBox<T, Space> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl<T: ?Sized + fmt::Debug, Space> fmt::Debug for SmallBox<T, Space> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<T: ?Sized, Space> fmt::Pointer for SmallBox<T, Space> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Unique directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &**self;
        fmt::Pointer::fmt(&ptr, f)
    }
}

impl<T: ?Sized + PartialEq, Space> PartialEq for SmallBox<T, Space> {
    #[inline]
    fn eq(&self, other: &SmallBox<T, Space>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
    #[inline]
    fn ne(&self, other: &SmallBox<T, Space>) -> bool {
        PartialEq::ne(&**self, &**other)
    }
}

impl<T: ?Sized + PartialOrd, Space> PartialOrd for SmallBox<T, Space> {
    #[inline]
    fn partial_cmp(&self, other: &SmallBox<T, Space>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::lt(&**self, &**other)
    }
    #[inline]
    fn le(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::le(&**self, &**other)
    }
    #[inline]
    fn ge(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::ge(&**self, &**other)
    }
    #[inline]
    fn gt(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::gt(&**self, &**other)
    }
}

impl<T: ?Sized + Ord, Space> Ord for SmallBox<T, Space> {
    #[inline]
    fn cmp(&self, other: &SmallBox<T, Space>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

impl<T: ?Sized + Eq, Space> Eq for SmallBox<T, Space> {}

impl<T: ?Sized + Hash, Space> Hash for SmallBox<T, Space> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

unsafe impl<T: ?Sized + Send, Space> Send for SmallBox<T, Space> {}
unsafe impl<T: ?Sized + Sync, Space> Sync for SmallBox<T, Space> {}

#[cfg(test)]
mod tests {
    use super::SmallBox;
    use space::*;
    use std::any::Any;

    #[test]
    fn test_basic() {
        let stacked: SmallBox<usize, S1> = SmallBox::new(1234usize);
        assert!(*stacked == 1234);

        let heaped: SmallBox<(usize, usize), S1> = SmallBox::new((0, 1));
        assert!(*heaped == (0, 1));
    }

    #[test]
    fn test_new_unchecked() {
        let val = [0usize, 1];
        let ptr = &val as *const _;

        unsafe {
            let stacked: SmallBox<[usize], S2> = SmallBox::new_unchecked(val, ptr);
            assert!(*stacked == [0, 1]);
            assert!(!stacked.is_heap());
        }

        let val = [0usize, 1, 2];
        let ptr = &val as *const _;

        unsafe {
            let heaped: SmallBox<Any, S2> = SmallBox::new_unchecked(val, ptr);
            assert!(heaped.is_heap());

            if let Some(array) = heaped.downcast_ref::<[usize; 3]>() {
                assert_eq!(*array, [0, 1, 2]);
            } else {
                unreachable!();
            }
        }
    }

    #[test]
    #[deny(unsafe_code)]
    fn test_macro() {
        let stacked: SmallBox<Any, S1> = smallbox!(1234usize);
        if let Some(num) = stacked.downcast_ref::<usize>() {
            assert_eq!(*num, 1234);
        } else {
            unreachable!();
        }

        let heaped: SmallBox<Any, S1> = smallbox!([0usize, 1]);
        if let Some(array) = heaped.downcast_ref::<[usize; 2]>() {
            assert_eq!(*array, [0, 1]);
        } else {
            unreachable!();
        }

        let is_even: SmallBox<Fn(u8) -> bool, S1> = smallbox!(|num: u8| num % 2 == 0);
        assert!(!is_even(5));
        assert!(is_even(6));
    }

    #[test]
    #[cfg(feature = "coerce")]
    fn test_coerce() {
        let stacked: SmallBox<Any, S1> = SmallBox::new(1234usize);
        if let Some(num) = stacked.downcast_ref::<usize>() {
            assert_eq!(*num, 1234);
        } else {
            unreachable!();
        }

        let heaped: SmallBox<Any, S1> = SmallBox::new([0usize, 1]);
        if let Some(array) = heaped.downcast_ref::<[usize; 2]>() {
            assert_eq!(*array, [0, 1]);
        } else {
            unreachable!();
        }
    }

    #[test]
    fn test_drop() {
        use std::cell::Cell;

        #[derive(Debug, Clone)]
        struct Struct<'a>(&'a Cell<bool>);
        impl<'a> Drop for Struct<'a> {
            fn drop(&mut self) {
                self.0.set(true);
            }
        }

        let flag = Cell::new(false);
        let val: SmallBox<_, S2> = SmallBox::new(Struct(&flag));
        assert!(flag.get() == false);

        drop(val);
        assert!(flag.get() == true);
    }

    #[test]
    fn test_dont_drop_space() {
        struct NoDrop(S1);
        impl Drop for NoDrop {
            fn drop(&mut self) {
                unreachable!();
            }
        }

        drop(SmallBox::<_, NoDrop>::new([true]));
    }

    #[test]
    fn test_oversize() {
        let fit = SmallBox::<_, S1>::new([0usize; 1]);
        let oversize = SmallBox::<_, S1>::new([0usize; 2]);
        assert!(!fit.is_heap());
        assert!(oversize.is_heap());
    }

    #[test]
    fn test_resize() {
        let m = SmallBox::<_, S4>::new([0usize; 2]);
        let l = m.resize::<S8>();
        assert!(!l.is_heap());
        let m = l.resize::<S4>();
        assert!(!m.is_heap());
        let s = m.resize::<S2>();
        assert!(!s.is_heap());
        let xs = s.resize::<S1>();
        assert!(xs.is_heap());
        let m = xs.resize::<S4>();
        assert!(m.is_heap());
    }

    #[test]
    fn test_clone() {
        let stacked: SmallBox<[usize; 2], S2> = smallbox!([0usize, 1]);
        assert_eq!(stacked, stacked.clone())
    }

    #[test]
    fn test_zst() {
        let zst = SmallBox::<_, S1>::new([0usize; 0]);
        assert_eq!(*zst, [0usize; 0]);
    }
}
<commit_msg>fix test<commit_after>use std::cmp::Ordering;
use std::fmt;
use std::hash::{self, Hash};
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ops;
use std::ptr;

#[cfg(not(feature = "std"))]
use alloc::alloc::{self, Layout};
#[cfg(feature = "std")]
use std::alloc::{self, Layout};

#[cfg(feature = "coerce")]
use std::marker::Unsize;
#[cfg(feature = "coerce")]
use std::ops::CoerceUnsized;

#[cfg(feature = "coerce")]
impl<T: ?Sized + Unsize<U>, U: ?Sized, Space> CoerceUnsized<SmallBox<U, Space>>
    for SmallBox<T, Space>
{}

/// Box value on stack or heap depending on its size
///
/// This macro is similar to `SmallBox::new`, which is used to create a new `Smallbox` instance,
/// but relaxing the constraint of `T: Sized`.
/// In order to do that, this macro will check the coersion rules between type `T` and the
/// expression type. This macro invokes a complier error for any invalid type coersion.
///
/// You can think that it has the signature of `smallbox!<U: Sized, T: ?Sized>(val: U) -> SmallBox<T, Space>`
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate smallbox;
///
/// # fn main() {
/// use smallbox::SmallBox;
/// use smallbox::space::*;
///
/// let small: SmallBox<[usize], S4> = smallbox!([0usize; 2]);
/// let large: SmallBox<[usize], S4> = smallbox!([1usize; 8]);
///
/// assert_eq!(small.len(), 2);
/// assert_eq!(large[7], 1);
///
/// assert!(large.is_heap() == true);
/// # }
/// ```
#[macro_export]
macro_rules! smallbox {
    ( $e: expr ) => {{
        let val = $e;
        let ptr = &val as *const _;
        #[allow(unsafe_code)]
        unsafe {
            $crate::SmallBox::new_unchecked(val, ptr)
        }
    }};
}

/// An optimized box that store value on stack or heap depending on its size
pub struct SmallBox<T: ?Sized, Space> {
    space: ManuallyDrop<Space>,
    ptr: *const T,
    _phantom: PhantomData<T>,
}

impl<T: ?Sized, Space> SmallBox<T, Space> {
    /// Box value on stack or heap depending on its size.
    ///
    /// # Example
    ///
    /// ```
    /// use smallbox::SmallBox;
    /// use smallbox::space::*;
    ///
    /// let small: SmallBox<_, S4> = SmallBox::new([0usize; 2]);
    /// let large: SmallBox<_, S4> = SmallBox::new([1usize; 8]);
    ///
    /// assert_eq!(small.len(), 2);
    /// assert_eq!(large[7], 1);
    ///
    /// assert!(large.is_heap() == true);
    /// ```
    pub fn new(val: T) -> SmallBox<T, Space>
    where
        T: Sized,
    {
        smallbox!(val)
    }

    #[doc(hidden)]
    pub unsafe fn new_unchecked<U>(val: U, ptr: *const T) -> SmallBox<T, Space>
    where
        U: Sized,
    {
        let result = Self::new_copy(&val, ptr);
        mem::forget(val);
        result
    }

    /// Change the capacity of `SmallBox`
    ///
    /// This method may move stack-allocated data to heap
    /// if the inline space is not sufficient. Once the data
    /// is stored on heap, it'll never be moved again.
    ///
    /// # Example
    ///
    /// ```
    /// use smallbox::SmallBox;
    /// use smallbox::space::{S2, S4};
    ///
    /// let s: SmallBox::<_, S4> = SmallBox::new([0usize; 4]);
    /// let m: SmallBox::<_, S2> = s.resize();
    /// ```
    pub fn resize<ToSpace>(self) -> SmallBox<T, ToSpace> {
        unsafe {
            let result = if self.is_heap() {
                // don't touch anything if the data is already on heap
                let mut space = ManuallyDrop::new(mem::uninitialized::<ToSpace>());
                SmallBox {
                    space,
                    ptr: self.ptr,
                    _phantom: PhantomData,
                }
            } else {
                let val: &T = &*self;
                SmallBox::<T, ToSpace>::new_copy(val, val as *const T)
            };

            mem::forget(self);

            result
        }
    }

    /// Returns true if the data is heap-allocated
    pub fn is_heap(&self) -> bool {
        !self.ptr.is_null()
    }

    unsafe fn new_copy<U>(val: &U, ptr: *const T) -> SmallBox<T, Space>
    where
        U: ?Sized,
    {
        let mut space = ManuallyDrop::new(mem::uninitialized::<Space>());

        let (ptr_addr, ptr_copy): (*const u8, *mut u8) = if mem::size_of_val::<U>(val)
            > mem::size_of::<Space>()
            || mem::align_of_val::<U>(val) > mem::align_of::<Space>()
        {
            // Heap
            let layout = Layout::for_value::<U>(val);
            let heap_ptr = alloc::alloc(layout);

            (heap_ptr, heap_ptr)
        } else {
            // Stack
            (ptr::null(), mem::transmute(&mut space))
        };

        let mut ptr = ptr;
        let ptr_ptr = &mut ptr as *mut _ as *mut usize;
        ptr_ptr.write(ptr_addr as usize);

        ptr::copy_nonoverlapping(
            val as *const _ as *const u8,
            ptr_copy,
            mem::size_of_val::<U>(val),
        );

        SmallBox {
            space,
            ptr,
            _phantom: PhantomData,
        }
    }

    unsafe fn as_ptr(&self) -> *const T {
        let mut ptr = self.ptr;

        if !self.is_heap() {
            let ptr_ptr = &mut ptr as *mut _ as *mut usize;
            ptr_ptr.write(mem::transmute(&self.space));
        }

        ptr
    }
}

impl<T: ?Sized, Space> ops::Deref for SmallBox<T, Space> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.as_ptr() }
    }
}

impl<T: ?Sized, Space> ops::DerefMut for SmallBox<T, Space> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *(self.as_ptr() as *const _ as *mut _) }
    }
}

impl<T: ?Sized, Space> ops::Drop for SmallBox<T, Space> {
    fn drop(&mut self) {
        unsafe {
            let layout = Layout::for_value::<T>(&*self);
            ptr::drop_in_place::<T>(&mut **self);
            if self.is_heap() {
                alloc::dealloc(self.ptr as *mut u8, layout);
            }
        }
    }
}

impl<T: Clone, Space> Clone for SmallBox<T, Space>
where
    T: Sized,
{
    fn clone(&self) -> Self {
        let val: &T = &*self;
        SmallBox::new(val.clone())
    }
}

impl<T: ?Sized + fmt::Display, Space> fmt::Display for SmallBox<T, Space> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

impl<T: ?Sized + fmt::Debug, Space> fmt::Debug for SmallBox<T, Space> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

impl<T: ?Sized, Space> fmt::Pointer for SmallBox<T, Space> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's not possible to extract the inner Unique directly from the Box,
        // instead we cast it to a *const which aliases the Unique
        let ptr: *const T = &**self;
        fmt::Pointer::fmt(&ptr, f)
    }
}

impl<T: ?Sized + PartialEq, Space> PartialEq for SmallBox<T, Space> {
    #[inline]
    fn eq(&self, other: &SmallBox<T, Space>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
    #[inline]
    fn ne(&self, other: &SmallBox<T, Space>) -> bool {
        PartialEq::ne(&**self, &**other)
    }
}

impl<T: ?Sized + PartialOrd, Space> PartialOrd for SmallBox<T, Space> {
    #[inline]
    fn partial_cmp(&self, other: &SmallBox<T, Space>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::lt(&**self, &**other)
    }
    #[inline]
    fn le(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::le(&**self, &**other)
    }
    #[inline]
    fn ge(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::ge(&**self, &**other)
    }
    #[inline]
    fn gt(&self, other: &SmallBox<T, Space>) -> bool {
        PartialOrd::gt(&**self, &**other)
    }
}

impl<T: ?Sized + Ord, Space> Ord for SmallBox<T, Space> {
    #[inline]
    fn cmp(&self, other: &SmallBox<T, Space>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

impl<T: ?Sized + Eq, Space> Eq for SmallBox<T, Space> {}

impl<T: ?Sized + Hash, Space> Hash for SmallBox<T, Space> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

unsafe impl<T: ?Sized + Send, Space> Send for SmallBox<T, Space> {}
unsafe impl<T: ?Sized + Sync, Space> Sync for SmallBox<T, Space> {}

#[cfg(test)]
mod tests {
    use super::SmallBox;
    use space::*;
    use std::any::Any;

    #[test]
    fn test_basic() {
        let stacked: SmallBox<usize, S1> = SmallBox::new(1234usize);
        assert!(*stacked == 1234);

        let heaped: SmallBox<(usize, usize), S1> = SmallBox::new((0, 1));
        assert!(*heaped == (0, 1));
    }

    #[test]
    fn test_new_unchecked() {
        let val = [0usize, 1];
        let ptr = &val as *const _;

        unsafe {
            let stacked: SmallBox<[usize], S2> = SmallBox::new_unchecked(val, ptr);
            assert!(*stacked == [0, 1]);
            assert!(!stacked.is_heap());
        }

        let val = [0usize, 1, 2];
        let ptr = &val as *const _;

        unsafe {
            let heaped: SmallBox<Any, S2> = SmallBox::new_unchecked(val, ptr);
            assert!(heaped.is_heap());

            if let Some(array) = heaped.downcast_ref::<[usize; 3]>() {
                assert_eq!(*array, [0, 1, 2]);
            } else {
                unreachable!();
            }
        }
    }

    #[test]
    #[deny(unsafe_code)]
    fn test_macro() {
        let stacked: SmallBox<Any, S1> = smallbox!(1234usize);
        if let Some(num) = stacked.downcast_ref::<usize>() {
            assert_eq!(*num, 1234);
        } else {
            unreachable!();
        }

        let heaped: SmallBox<Any, S1> = smallbox!([0usize, 1]);
        if let Some(array) = heaped.downcast_ref::<[usize; 2]>() {
            assert_eq!(*array, [0, 1]);
        } else {
            unreachable!();
        }

        let is_even: SmallBox<Fn(u8) -> bool, S1> = smallbox!(|num: u8| num % 2 == 0);
        assert!(!is_even(5));
        assert!(is_even(6));
    }

    #[test]
    #[cfg(feature = "coerce")]
    fn test_coerce() {
        let stacked: SmallBox<Any, S1> = SmallBox::new(1234usize);
        if let Some(num) = stacked.downcast_ref::<usize>() {
            assert_eq!(*num, 1234);
        } else {
            unreachable!();
        }

        let heaped: SmallBox<Any, S1> = SmallBox::new([0usize, 1]);
        if let Some(array) = heaped.downcast_ref::<[usize; 2]>() {
            assert_eq!(*array, [0, 1]);
        } else {
            unreachable!();
        }
    }

    #[test]
    fn test_drop() {
        use std::cell::Cell;

        #[derive(Debug, Clone)]
        struct Struct<'a>(&'a Cell<bool>);
        impl<'a> Drop for Struct<'a> {
            fn drop(&mut self) {
                self.0.set(true);
            }
        }

        let flag = Cell::new(false);
        let val: SmallBox<_, S2> = SmallBox::new(Struct(&flag));
        assert!(flag.get() == false);

        drop(val);
        assert!(flag.get() == true);
    }

    #[test]
    fn test_dont_drop_space() {
        struct NoDrop(S1);
        impl Drop for NoDrop {
            fn drop(&mut self) {
                unreachable!();
            }
        }

        drop(SmallBox::<_, NoDrop>::new([true]));
    }

    #[test]
    fn test_oversize() {
        let fit = SmallBox::<_, S1>::new([0usize; 1]);
        let oversize = SmallBox::<_, S1>::new([0usize; 2]);
        assert!(!fit.is_heap());
        assert!(oversize.is_heap());
    }

    #[test]
    fn test_resize() {
        let m = SmallBox::<_, S4>::new([0usize; 2]);
        let l = m.resize::<S8>();
        assert!(!l.is_heap());
        let m = l.resize::<S4>();
        assert!(!m.is_heap());
        let s = m.resize::<S2>();
        assert!(!s.is_heap());
        let xs = s.resize::<S1>();
        assert!(xs.is_heap());
        let m = xs.resize::<S4>();
        assert!(m.is_heap());
    }

    #[test]
    fn test_clone() {
        let stacked: SmallBox<[usize; 2], S2> = smallbox!([0usize, 1]);
        assert_eq!(stacked, stacked.clone())
    }

    #[test]
    fn test_zst() {
        let zst: SmallBox<[usize], S1> = smallbox!([0usize; 0]);
        assert_eq!(*zst, [0usize; 0]);
    }
}
<|endoftext|>