<commit_before>use cairo::{self, ImageSurface};
use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::number_list::{NumberList, NumberListError, NumberListLength};
use crate::parsers;
use crate::property_bag::PropertyBag;
use crate::surface_utils::{
    iterators::Pixels, shared_surface::SharedImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Color matrix operation types.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum OperationType {
    Matrix,
    Saturate,
    HueRotate,
    LuminanceToAlpha,
}

/// The `feColorMatrix` filter primitive.
pub struct FeColorMatrix {
    base: PrimitiveWithInput,
    matrix: Matrix5<f64>,
}

impl Default for FeColorMatrix {
    /// Constructs a new `ColorMatrix` with empty properties.
    #[inline]
    fn default() -> FeColorMatrix {
        FeColorMatrix {
            base: PrimitiveWithInput::new::<Self>(),
            matrix: Matrix5::identity(),
        }
    }
}

impl NodeTrait for FeColorMatrix {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        // First, determine the operation type.
        let mut operation_type = OperationType::Matrix;
        for (attr, value) in pbag
            .iter()
            .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "type"))
        {
            operation_type = OperationType::parse(attr, value)?;
        }

        // Now read the matrix correspondingly.
        // LuminanceToAlpha doesn't accept any matrix.
        if operation_type == OperationType::LuminanceToAlpha {
            self.matrix = {
                #[cfg_attr(rustfmt, rustfmt_skip)]
                Matrix5::new(
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.2125, 0.7154, 0.0721, 0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 1.0,
                )
            };
        } else {
            for (attr, value) in pbag
                .iter()
                .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "values"))
            {
                let new_matrix = match operation_type {
                    OperationType::LuminanceToAlpha => unreachable!(),
                    OperationType::Matrix => {
                        let NumberList(v) =
                            NumberList::parse_str(value, NumberListLength::Exact(20))
                                .map_err(|err| {
                                    let err_str = match err {
                                        NumberListError::IncorrectNumberOfElements => {
                                            "incorrect number of elements: expected 20"
                                        }
                                        NumberListError::Parse(ref err) => &err,
                                    };

                                    ValueErrorKind::parse_error(err_str)
                                })
                                .attribute(attr)?;
                        let matrix = Matrix4x5::from_row_slice(&v);
                        let mut matrix = matrix.fixed_resize(0.0);
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                    OperationType::Saturate => {
                        let s = parsers::number(value).attribute(attr.clone())?;
                        if s < 0.0 || s > 1.0 {
                            return Err(ValueErrorKind::value_error("expected value from 0 to 1"))
                                .attribute(attr);
                        }

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        Matrix5::new(
                            0.213 + 0.787 * s, 0.715 - 0.715 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 + 0.285 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 - 0.715 * s, 0.072 + 0.928 * s, 0.0, 0.0,
                            0.0,               0.0,               0.0,               1.0, 0.0,
                            0.0,               0.0,               0.0,               0.0, 1.0,
                        )
                    }
                    OperationType::HueRotate => {
                        let degrees = parsers::number(value).attribute(attr.clone())?;
                        let (sin, cos) = degrees.to_radians().sin_cos();

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let a = Matrix3::new(
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let b = Matrix3::new(
                             0.787, -0.715, -0.072,
                            -0.213,  0.285, -0.072,
                            -0.213, -0.715,  0.928,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let c = Matrix3::new(
                            -0.213, -0.715,  0.928,
                             0.143,  0.140, -0.283,
                            -0.787,  0.715,  0.072,
                        );

                        let top_left = a + b * cos + c * sin;

                        let mut matrix = top_left.fixed_resize(0.0);
                        matrix[(3, 3)] = 1.0;
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                };

                self.matrix = new_matrix;
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeColorMatrix {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);

        let mut output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, pixel) in Pixels::new(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;

                let pixel_vec = if alpha == 0.0 {
                    Vector5::new(0.0, 0.0, 0.0, 0.0, 1.0)
                } else {
                    Vector5::new(
                        f64::from(pixel.r) / 255f64 / alpha,
                        f64::from(pixel.g) / 255f64 / alpha,
                        f64::from(pixel.b) / 255f64 / alpha,
                        alpha,
                        1.0,
                    )
                };
                let mut new_pixel_vec = Vector5::zeros();
                self.matrix.mul_to(&pixel_vec, &mut new_pixel_vec);

                let new_alpha = clamp(new_pixel_vec[3], 0.0, 1.0);

                let premultiply = |x: f64| ((clamp(x, 0.0, 1.0) * new_alpha * 255f64) + 0.5) as u8;

                let output_pixel = Pixel {
                    r: premultiply(new_pixel_vec[0]),
                    g: premultiply(new_pixel_vec[1]),
                    b: premultiply(new_pixel_vec[2]),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl OperationType {
    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
        match s {
            "matrix" => Ok(OperationType::Matrix),
            "saturate" => Ok(OperationType::Saturate),
            "hueRotate" => Ok(OperationType::HueRotate),
            "luminanceToAlpha" => Ok(OperationType::LuminanceToAlpha),
            _ => Err(ValueErrorKind::parse_error("invalid value")).attribute(attr),
        }
    }
}
<commit_msg>color_matrix.rs: impl Parse for OperationType instead of using a custom method<commit_after>use cairo::{self, ImageSurface};
use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::number_list::{NumberList, NumberListError, NumberListLength};
use crate::parsers::{self, Parse, ParseValue};
use crate::property_bag::PropertyBag;
use crate::surface_utils::{
    iterators::Pixels, shared_surface::SharedImageSurface, ImageSurfaceDataExt, Pixel,
};
use crate::util::clamp;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Color matrix operation types.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum OperationType {
    Matrix,
    Saturate,
    HueRotate,
    LuminanceToAlpha,
}

/// The `feColorMatrix` filter primitive.
pub struct FeColorMatrix {
    base: PrimitiveWithInput,
    matrix: Matrix5<f64>,
}

impl Default for FeColorMatrix {
    /// Constructs a new `ColorMatrix` with empty properties.
    #[inline]
    fn default() -> FeColorMatrix {
        FeColorMatrix {
            base: PrimitiveWithInput::new::<Self>(),
            matrix: Matrix5::identity(),
        }
    }
}

impl NodeTrait for FeColorMatrix {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        // First, determine the operation type.
        let mut operation_type = OperationType::Matrix;
        for (attr, value) in pbag
            .iter()
            .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "type"))
        {
            operation_type = attr.parse(value)?;
        }

        // Now read the matrix correspondingly.
        // LuminanceToAlpha doesn't accept any matrix.
        if operation_type == OperationType::LuminanceToAlpha {
            self.matrix = {
                #[cfg_attr(rustfmt, rustfmt_skip)]
                Matrix5::new(
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 0.0,
                    0.2125, 0.7154, 0.0721, 0.0, 0.0,
                    0.0,    0.0,    0.0,    0.0, 1.0,
                )
            };
        } else {
            for (attr, value) in pbag
                .iter()
                .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "values"))
            {
                let new_matrix = match operation_type {
                    OperationType::LuminanceToAlpha => unreachable!(),
                    OperationType::Matrix => {
                        let NumberList(v) =
                            NumberList::parse_str(value, NumberListLength::Exact(20))
                                .map_err(|err| {
                                    let err_str = match err {
                                        NumberListError::IncorrectNumberOfElements => {
                                            "incorrect number of elements: expected 20"
                                        }
                                        NumberListError::Parse(ref err) => &err,
                                    };

                                    ValueErrorKind::parse_error(err_str)
                                })
                                .attribute(attr)?;
                        let matrix = Matrix4x5::from_row_slice(&v);
                        let mut matrix = matrix.fixed_resize(0.0);
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                    OperationType::Saturate => {
                        let s = parsers::number(value).attribute(attr.clone())?;
                        if s < 0.0 || s > 1.0 {
                            return Err(ValueErrorKind::value_error("expected value from 0 to 1"))
                                .attribute(attr);
                        }

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        Matrix5::new(
                            0.213 + 0.787 * s, 0.715 - 0.715 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 + 0.285 * s, 0.072 - 0.072 * s, 0.0, 0.0,
                            0.213 - 0.213 * s, 0.715 - 0.715 * s, 0.072 + 0.928 * s, 0.0, 0.0,
                            0.0,               0.0,               0.0,               1.0, 0.0,
                            0.0,               0.0,               0.0,               0.0, 1.0,
                        )
                    }
                    OperationType::HueRotate => {
                        let degrees = parsers::number(value).attribute(attr.clone())?;
                        let (sin, cos) = degrees.to_radians().sin_cos();

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let a = Matrix3::new(
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                            0.213, 0.715, 0.072,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let b = Matrix3::new(
                             0.787, -0.715, -0.072,
                            -0.213,  0.285, -0.072,
                            -0.213, -0.715,  0.928,
                        );

                        #[cfg_attr(rustfmt, rustfmt_skip)]
                        let c = Matrix3::new(
                            -0.213, -0.715,  0.928,
                             0.143,  0.140, -0.283,
                            -0.787,  0.715,  0.072,
                        );

                        let top_left = a + b * cos + c * sin;

                        let mut matrix = top_left.fixed_resize(0.0);
                        matrix[(3, 3)] = 1.0;
                        matrix[(4, 4)] = 1.0;
                        matrix
                    }
                };

                self.matrix = new_matrix;
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeColorMatrix {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .into_irect(draw_ctx);

        let mut output_surface = ImageSurface::create(
            cairo::Format::ARgb32,
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
        )?;

        let output_stride = output_surface.get_stride() as usize;
        {
            let mut output_data = output_surface.get_data().unwrap();

            for (x, y, pixel) in Pixels::new(input.surface(), bounds) {
                let alpha = f64::from(pixel.a) / 255f64;

                let pixel_vec = if alpha == 0.0 {
                    Vector5::new(0.0, 0.0, 0.0, 0.0, 1.0)
                } else {
                    Vector5::new(
                        f64::from(pixel.r) / 255f64 / alpha,
                        f64::from(pixel.g) / 255f64 / alpha,
                        f64::from(pixel.b) / 255f64 / alpha,
                        alpha,
                        1.0,
                    )
                };
                let mut new_pixel_vec = Vector5::zeros();
                self.matrix.mul_to(&pixel_vec, &mut new_pixel_vec);

                let new_alpha = clamp(new_pixel_vec[3], 0.0, 1.0);

                let premultiply = |x: f64| ((clamp(x, 0.0, 1.0) * new_alpha * 255f64) + 0.5) as u8;

                let output_pixel = Pixel {
                    r: premultiply(new_pixel_vec[0]),
                    g: premultiply(new_pixel_vec[1]),
                    b: premultiply(new_pixel_vec[2]),
                    a: ((new_alpha * 255f64) + 0.5) as u8,
                };

                output_data.set_pixel(output_stride, output_pixel, x, y);
            }
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, input.surface().surface_type())?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl Parse for OperationType {
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind> {
        parse_identifiers!(
            parser,
            "matrix" => OperationType::Matrix,
            "saturate" => OperationType::Saturate,
            "hueRotate" => OperationType::HueRotate,
            "luminanceToAlpha" => OperationType::LuminanceToAlpha,
        ).map_err(|_: ParseError| ValueErrorKind::parse_error("parse error"))
    }
}
<|endoftext|>


<commit_before>use crate::schema::{evaluation_events, score_awards, badge_awards};
use crate::submission::{self, Submission, SubmissionStatus};
use diesel::prelude::*;
use diesel::sql_types::{Double, Text, Bool};
use juniper::FieldResult;
use std::error::Error;
use std::thread;
use turingarena::evaluation::mem::Evaluation;
use turingarena::evaluation::Event;
use turingarena::problem::driver::{ProblemDriver, ProblemPack};
use turingarena::award::{Score, AwardName};
use turingarena_task_maker::driver::IoiProblemDriver;

/// An evaluation event
#[derive(Queryable, Serialize, Deserialize, Clone, Debug)]
pub struct EvaluationEvent {
    /// id of the submission
    submission_id: String,

    /// serial number of the event
    serial: i32,

    /// value of the event, serialized
    event_json: String,
}

#[juniper::object]
impl EvaluationEvent {
    /// serial number of the event
    fn serial(&self) -> i32 {
        self.serial
    }

    /// value of this evaluation event
    fn event(&self) -> FieldResult<Event> {
        Ok(serde_json::from_str(&self.event_json)?)
    }

    /// events as JSON format
    /// This is currently provided only as a woraround the fact that
    /// events doesn't work, and should be removed in the future!
    fn event_json(&self) -> &String {
        &self.event_json
    }
}

#[derive(Insertable)]
#[table_name = "evaluation_events"]
struct EvaluationEventInput<'a> {
    submission_id: &'a str,
    serial: i32,
    event_json: String,
}

#[derive(Insertable)]
#[table_name = "score_awards"]
struct ScoreAwardInput<'a> {
    submission_id: &'a str,
    award_name: &'a str,
    score: f64,
}

#[derive(Insertable)]
#[table_name = "badge_awards"]
struct BadgeAwardInput<'a> {
    submission_id: &'a str,
    award_name: &'a str,
    badge: bool,
}

#[derive(Queryable)]
pub struct ScoreAward {
    /// Id of the submission
    #[allow(dead_code)]
    submission_id: String,

    /// Name of the award
    award_name: String,

    /// Score of the submission
    score: f64,
}

#[derive(Queryable)]
pub struct BadgeAward {
    /// Id of the submission
    #[allow(dead_code)]
    submission_id: String,

    /// Name of the award
    award_name: String,

    /// Score of the submission
    badge: bool,
}

#[juniper::object]
impl ScoreAward {
    /// The score
    fn score(&self) -> Score {
        Score(self.score)
    }

    /// Name of the award
    fn award_name(&self) -> AwardName {
        AwardName(self.award_name.clone())
    }
}

#[juniper::object]
impl BadgeAward {
    /// The badge
    fn badge(&self) -> bool {
        self.badge
    }

    /// Name of the award
    fn award_name(&self) -> AwardName {
        AwardName(self.award_name.clone())
    }
}

#[derive(QueryableByName)]
pub struct MaxScoreAward {
    #[sql_type = "Text"]
    award_name: String,

    #[sql_type = "Double"]
    score: f64,

    #[sql_type = "Text"]
    submission_id: String,
}

#[derive(QueryableByName)]
pub struct BestBadgeAward {
    #[sql_type = "Text"]
    award_name: String,

    #[sql_type = "Bool"]
    badge: bool,

    #[sql_type = "Text"]
    submission_id: String,
}

/// Maximum score award
#[juniper::object]
impl MaxScoreAward {
    /// Id of the most recent submission that made the max score
    fn submission_id(&self) -> &String {
        &self.submission_id
    }

    /// The score
    fn score(&self) -> Score {
        Score(self.score)
    }

    /// Name of the award
    fn award_name(&self) -> &String {
        &self.award_name
    }
}

/// Beste badge award
#[juniper::object]
impl BestBadgeAward {
    /// Id of the most recent submission that made the max score
    fn submission_id(&self) -> &String {
        &self.submission_id
    }

    /// The score
    fn badge(&self) -> bool {
        self.badge
    }

    /// Name of the award
    fn award_name(&self) -> &String {
        &self.award_name
    }
}

fn insert_event(
    conn: &SqliteConnection,
    serial: i32,
    submission_id: &str,
    event: &Event,
) -> Result<(), Box<dyn Error>> {
    if let Event::Score(score_event) = event {
        let score_award_input = ScoreAwardInput {
            award_name: &score_event.award_name.0,
            score: score_event.score.0,
            submission_id,
        };
        diesel::insert_into(score_awards::table)
            .values(&score_award_input)
            .execute(conn)?;
    }
    if let Event::Badge(badge_event) = event {
        let badge_award_input = BadgeAwardInput {
            award_name: &badge_event.award_name.0,
            badge: badge_event.badge,
            submission_id,
        };
        diesel::insert_into(badge_awards::table)
            .values(&badge_award_input)
            .execute(conn)?;
    }
    let event_input = EvaluationEventInput {
        serial,
        submission_id,
        event_json: serde_json::to_string(event)?,
    };
    diesel::insert_into(evaluation_events::table)
        .values(&event_input)
        .execute(conn)?;
    Ok(())
}

/// return a list of evaluation events for the specified evaluation
pub fn query_events(
    conn: &SqliteConnection,
    submission_id: &str,
) -> QueryResult<Vec<EvaluationEvent>> {
    evaluation_events::table
        .filter(evaluation_events::dsl::submission_id.eq(submission_id))
        .load(conn)
}

/// Get the best score award for (user, problem)
pub fn query_score_awards_of_user_and_problem(
    conn: &SqliteConnection,
    user_id: &str,
    problem_name: &str,
) -> QueryResult<Vec<MaxScoreAward>> {
    diesel::sql_query(
        "
        SELECT sc.award_id, MAX(sc.score) as score, (
            SELECT s.id
            FROM submissions s JOIN badge_awards sci ON s.id = sci.submission_id
            WHERE sci.score = score AND sci.award_id = sc.award_id
            ORDER BY s.created_at DESC
            LIMIT 1
        ) as submission_id
        FROM badge_awards sc JOIN submissions s ON sc.submission_id = s.id
        WHERE s.problem_name = ? AND s.user_id = ?
        GROUP BY sc.award_id
    ",
    )
        .bind::<Text, _>(problem_name)
        .bind::<Text, _>(user_id)
        .load::<MaxScoreAward>(conn)
}

/// Get the best award badge for (user, problem)
pub fn query_badge_awards_of_user_and_problem(
    conn: &SqliteConnection,
    user_id: &str,
    problem_name: &str,
) -> QueryResult<Vec<BestBadgeAward>> {
    diesel::sql_query(
        "
        SELECT sc.award_id, MAX(sc.badge) as badge, (
            SELECT s.id
            FROM submissions s JOIN badge_awards sci ON s.id = sci.submission_id
            WHERE sci.badge = badge AND sci.award_id = sc.award_id
            ORDER BY s.created_at DESC
            LIMIT 1
        ) as submission_id
        FROM badge_awards sc JOIN submissions s ON sc.submission_id = s.id
        WHERE s.problem_name = ? AND s.user_id = ?
        GROUP BY sc.award_id
    ",
    )
        .bind::<Text, _>(problem_name)
        .bind::<Text, _>(user_id)
        .load::<BestBadgeAward>(conn)
}

/// Get the score awards of (user, problem, submission)
pub fn query_score_awards(
    conn: &SqliteConnection,
    submission_id: &str,
) -> QueryResult<Vec<ScoreAward>> {
    score_awards::table
        .filter(score_awards::dsl::submission_id.eq(submission_id))
        .load(conn)
}

/// Get the badge awards of (user, problem, submission)
pub fn query_badge_awards(
    conn: &SqliteConnection,
    submission_id: &str,
) -> QueryResult<Vec<BadgeAward>> {
    badge_awards::table
        .filter(badge_awards::dsl::submission_id.eq(submission_id))
        .load(conn)
}

/// start the evaluation thread
pub fn evaluate(
    problem_pack: ProblemPack,
    submission: &Submission,
    db_connection: SqliteConnection,
) -> QueryResult<()> {
    let submission_id = submission.id.clone();
    let submission = submission.to_mem_submission(&db_connection)?;
    thread::spawn(move || {
        let Evaluation(receiver) = IoiProblemDriver::evaluate(problem_pack, submission);
        for (serial, event) in receiver.into_iter().enumerate() {
            insert_event(&db_connection, serial as i32, &submission_id, &event).unwrap();
        }
        submission::set_status(&db_connection, &submission_id, SubmissionStatus::Success).unwrap();
    });
    Ok(())
}
<commit_msg>contest: fix some errors in SQL queries<commit_after>use crate::schema::{evaluation_events, score_awards, badge_awards};
use crate::submission::{self, Submission, SubmissionStatus};
use diesel::prelude::*;
use diesel::sql_types::{Double, Text, Bool};
use juniper::FieldResult;
use std::error::Error;
use std::thread;
use turingarena::evaluation::mem::Evaluation;
use turingarena::evaluation::Event;
use turingarena::problem::driver::{ProblemDriver, ProblemPack};
use turingarena::award::{Score, AwardName};
use turingarena_task_maker::driver::IoiProblemDriver;

/// An evaluation event
#[derive(Queryable, Serialize, Deserialize, Clone, Debug)]
pub struct EvaluationEvent {
    /// id of the submission
    submission_id: String,

    /// serial number of the event
    serial: i32,

    /// value of the event, serialized
    event_json: String,
}

#[juniper::object]
impl EvaluationEvent {
    /// serial number of the event
    fn serial(&self) -> i32 {
        self.serial
    }

    /// value of this evaluation event
    fn event(&self) -> FieldResult<Event> {
        Ok(serde_json::from_str(&self.event_json)?)
    }

    /// events as JSON format
    /// This is currently provided only as a woraround the fact that
    /// events doesn't work, and should be removed in the future!
    fn event_json(&self) -> &String {
        &self.event_json
    }
}

#[derive(Insertable)]
#[table_name = "evaluation_events"]
struct EvaluationEventInput<'a> {
    submission_id: &'a str,
    serial: i32,
    event_json: String,
}

#[derive(Insertable)]
#[table_name = "score_awards"]
struct ScoreAwardInput<'a> {
    submission_id: &'a str,
    award_name: &'a str,
    score: f64,
}

#[derive(Insertable)]
#[table_name = "badge_awards"]
struct BadgeAwardInput<'a> {
    submission_id: &'a str,
    award_name: &'a str,
    badge: bool,
}

#[derive(Queryable)]
pub struct ScoreAward {
    /// Id of the submission
    #[allow(dead_code)]
    submission_id: String,

    /// Name of the award
    award_name: String,

    /// Score of the submission
    score: f64,
}

#[derive(Queryable)]
pub struct BadgeAward {
    /// Id of the submission
    #[allow(dead_code)]
    submission_id: String,

    /// Name of the award
    award_name: String,

    /// Score of the submission
    badge: bool,
}

#[juniper::object]
impl ScoreAward {
    /// The score
    fn score(&self) -> Score {
        Score(self.score)
    }

    /// Name of the award
    fn award_name(&self) -> AwardName {
        AwardName(self.award_name.clone())
    }
}

#[juniper::object]
impl BadgeAward {
    /// The badge
    fn badge(&self) -> bool {
        self.badge
    }

    /// Name of the award
    fn award_name(&self) -> AwardName {
        AwardName(self.award_name.clone())
    }
}

#[derive(QueryableByName)]
pub struct MaxScoreAward {
    #[sql_type = "Text"]
    award_name: String,

    #[sql_type = "Double"]
    score: f64,

    #[sql_type = "Text"]
    submission_id: String,
}

#[derive(QueryableByName)]
pub struct BestBadgeAward {
    #[sql_type = "Text"]
    award_name: String,

    #[sql_type = "Bool"]
    badge: bool,

    #[sql_type = "Text"]
    submission_id: String,
}

/// Maximum score award
#[juniper::object]
impl MaxScoreAward {
    /// Id of the most recent submission that made the max score
    fn submission_id(&self) -> &String {
        &self.submission_id
    }

    /// The score
    fn score(&self) -> Score {
        Score(self.score)
    }

    /// Name of the award
    fn award_name(&self) -> &String {
        &self.award_name
    }
}

/// Beste badge award
#[juniper::object]
impl BestBadgeAward {
    /// Id of the most recent submission that made the max score
    fn submission_id(&self) -> &String {
        &self.submission_id
    }

    /// The score
    fn badge(&self) -> bool {
        self.badge
    }

    /// Name of the award
    fn award_name(&self) -> &String {
        &self.award_name
    }
}

fn insert_event(
    conn: &SqliteConnection,
    serial: i32,
    submission_id: &str,
    event: &Event,
) -> Result<(), Box<dyn Error>> {
    if let Event::Score(score_event) = event {
        let score_award_input = ScoreAwardInput {
            award_name: &score_event.award_name.0,
            score: score_event.score.0,
            submission_id,
        };
        diesel::insert_into(score_awards::table)
            .values(&score_award_input)
            .execute(conn)?;
    }
    if let Event::Badge(badge_event) = event {
        let badge_award_input = BadgeAwardInput {
            award_name: &badge_event.award_name.0,
            badge: badge_event.badge,
            submission_id,
        };
        diesel::insert_into(badge_awards::table)
            .values(&badge_award_input)
            .execute(conn)?;
    }
    let event_input = EvaluationEventInput {
        serial,
        submission_id,
        event_json: serde_json::to_string(event)?,
    };
    diesel::insert_into(evaluation_events::table)
        .values(&event_input)
        .execute(conn)?;
    Ok(())
}

/// return a list of evaluation events for the specified evaluation
pub fn query_events(
    conn: &SqliteConnection,
    submission_id: &str,
) -> QueryResult<Vec<EvaluationEvent>> {
    evaluation_events::table
        .filter(evaluation_events::dsl::submission_id.eq(submission_id))
        .load(conn)
}

/// Get the best score award for (user, problem)
pub fn query_score_awards_of_user_and_problem(
    conn: &SqliteConnection,
    user_id: &str,
    problem_name: &str,
) -> QueryResult<Vec<MaxScoreAward>> {
    diesel::sql_query(
        "
        SELECT sc.award_name, MAX(sc.score) as score, (
            SELECT s.id
            FROM submissions s JOIN score_awards sci ON s.id = sci.submission_id
            WHERE sci.score = score AND sci.award_name = sc.award_name
            ORDER BY s.created_at DESC
            LIMIT 1
        ) as submission_id
        FROM score_awards sc JOIN submissions s ON sc.submission_id = s.id
        WHERE s.problem_name = ? AND s.user_id = ?
        GROUP BY sc.award_name
    ",
    )
        .bind::<Text, _>(problem_name)
        .bind::<Text, _>(user_id)
        .load::<MaxScoreAward>(conn)
}

/// Get the best award badge for (user, problem)
pub fn query_badge_awards_of_user_and_problem(
    conn: &SqliteConnection,
    user_id: &str,
    problem_name: &str,
) -> QueryResult<Vec<BestBadgeAward>> {
    diesel::sql_query(
        "
        SELECT sc.award_name, MAX(sc.badge) as badge, (
            SELECT s.id
            FROM submissions s JOIN badge_awards sci ON s.id = sci.submission_id
            WHERE sci.badge = badge AND sci.award_name = sc.award_name
            ORDER BY s.created_at DESC
            LIMIT 1
        ) as submission_id
        FROM badge_awards sc JOIN submissions s ON sc.submission_id = s.id
        WHERE s.problem_name = ? AND s.user_id = ?
        GROUP BY sc.award_name
    ",
    )
        .bind::<Text, _>(problem_name)
        .bind::<Text, _>(user_id)
        .load::<BestBadgeAward>(conn)
}

/// Get the score awards of (user, problem, submission)
pub fn query_score_awards(
    conn: &SqliteConnection,
    submission_id: &str,
) -> QueryResult<Vec<ScoreAward>> {
    score_awards::table
        .filter(score_awards::dsl::submission_id.eq(submission_id))
        .load(conn)
}

/// Get the badge awards of (user, problem, submission)
pub fn query_badge_awards(
    conn: &SqliteConnection,
    submission_id: &str,
) -> QueryResult<Vec<BadgeAward>> {
    badge_awards::table
        .filter(badge_awards::dsl::submission_id.eq(submission_id))
        .load(conn)
}

/// start the evaluation thread
pub fn evaluate(
    problem_pack: ProblemPack,
    submission: &Submission,
    db_connection: SqliteConnection,
) -> QueryResult<()> {
    let submission_id = submission.id.clone();
    let submission = submission.to_mem_submission(&db_connection)?;
    thread::spawn(move || {
        let Evaluation(receiver) = IoiProblemDriver::evaluate(problem_pack, submission);
        for (serial, event) in receiver.into_iter().enumerate() {
            insert_event(&db_connection, serial as i32, &submission_id, &event).unwrap();
        }
        submission::set_status(&db_connection, &submission_id, SubmissionStatus::Success).unwrap();
    });
    Ok(())
}
<|endoftext|>


<commit_before>use tokio_postgres::types::{ToSql, Type};
use tokio_postgres::{Error, Row};

use crate::{Client, Query, Statement};

pub struct Transaction<'a> {
    client: &'a mut Client,
    depth: u32,
    done: bool,
}

impl<'a> Drop for Transaction<'a> {
    fn drop(&mut self) {
        if !self.done {
            let _ = self.rollback_inner();
        }
    }
}

impl<'a> Transaction<'a> {
    pub(crate) fn new(client: &'a mut Client) -> Transaction<'a> {
        Transaction {
            client,
            depth: 0,
            done: false,
        }
    }

    pub fn commit(mut self) -> Result<(), Error> {
        self.done = true;
        if self.depth == 0 {
            self.client.batch_execute("COMMIT")
        } else {
            self.client
                .batch_execute(&format!("RELEASE sp{}", self.depth))
        }
    }

    pub fn rollback(mut self) -> Result<(), Error> {
        self.done = true;
        self.rollback_inner()
    }

    fn rollback_inner(&mut self) -> Result<(), Error> {
        if self.depth == 0 {
            self.client.batch_execute("ROLLBACK")
        } else {
            self.client
                .batch_execute(&format!("ROLLBACK TO sp{}", self.depth))
        }
    }

    pub fn prepare(&mut self, query: &str) -> Result<Statement, Error> {
        self.client.prepare(query)
    }

    pub fn prepare_typed(&mut self, query: &str, types: &[Type]) -> Result<Statement, Error> {
        self.client.prepare_typed(query, types)
    }

    pub fn execute<T>(&mut self, query: &T, params: &[&dyn ToSql]) -> Result<u64, Error>
    where
        T: ?Sized + Query,
    {
        self.client.execute(query, params)
    }

    pub fn query<T>(&mut self, query: &T, params: &[&dyn ToSql]) -> Result<Vec<Row>, Error>
    where
        T: ?Sized + Query,
    {
        self.client.query(query, params)
    }

    pub fn batch_execute(&mut self, query: &str) -> Result<(), Error> {
        self.client.batch_execute(query)
    }

    pub fn transaction(&mut self) -> Result<Transaction<'_>, Error> {
        let depth = self.depth + 1;
        self.client
            .batch_execute(&format!("SAVEPOINT sp{}", depth))?;
        Ok(Transaction {
            client: self.client,
            depth,
            done: false,
        })
    }
}
<commit_msg>Sync transaction copy_in<commit_after>use std::io::Read;
use tokio_postgres::types::{ToSql, Type};
use tokio_postgres::{Error, Row};

use crate::{Client, Query, Statement};

pub struct Transaction<'a> {
    client: &'a mut Client,
    depth: u32,
    done: bool,
}

impl<'a> Drop for Transaction<'a> {
    fn drop(&mut self) {
        if !self.done {
            let _ = self.rollback_inner();
        }
    }
}

impl<'a> Transaction<'a> {
    pub(crate) fn new(client: &'a mut Client) -> Transaction<'a> {
        Transaction {
            client,
            depth: 0,
            done: false,
        }
    }

    pub fn commit(mut self) -> Result<(), Error> {
        self.done = true;
        if self.depth == 0 {
            self.client.batch_execute("COMMIT")
        } else {
            self.client
                .batch_execute(&format!("RELEASE sp{}", self.depth))
        }
    }

    pub fn rollback(mut self) -> Result<(), Error> {
        self.done = true;
        self.rollback_inner()
    }

    fn rollback_inner(&mut self) -> Result<(), Error> {
        if self.depth == 0 {
            self.client.batch_execute("ROLLBACK")
        } else {
            self.client
                .batch_execute(&format!("ROLLBACK TO sp{}", self.depth))
        }
    }

    pub fn prepare(&mut self, query: &str) -> Result<Statement, Error> {
        self.client.prepare(query)
    }

    pub fn prepare_typed(&mut self, query: &str, types: &[Type]) -> Result<Statement, Error> {
        self.client.prepare_typed(query, types)
    }

    pub fn execute<T>(&mut self, query: &T, params: &[&dyn ToSql]) -> Result<u64, Error>
    where
        T: ?Sized + Query,
    {
        self.client.execute(query, params)
    }

    pub fn query<T>(&mut self, query: &T, params: &[&dyn ToSql]) -> Result<Vec<Row>, Error>
    where
        T: ?Sized + Query,
    {
        self.client.query(query, params)
    }

    pub fn copy_in<T, R>(
        &mut self,
        query: &T,
        params: &[&dyn ToSql],
        reader: R,
    ) -> Result<u64, Error>
    where
        T: ?Sized + Query,
        R: Read,
    {
        self.client.copy_in(query, params, reader)
    }

    pub fn batch_execute(&mut self, query: &str) -> Result<(), Error> {
        self.client.batch_execute(query)
    }

    pub fn transaction(&mut self) -> Result<Transaction<'_>, Error> {
        let depth = self.depth + 1;
        self.client
            .batch_execute(&format!("SAVEPOINT sp{}", depth))?;
        Ok(Transaction {
            client: self.client,
            depth,
            done: false,
        })
    }
}
<|endoftext|>


<commit_before>extern mod cairo;
extern mod core_graphics;
extern mod core_text;

use azure_hl::{BackendType, CairoBackend, CoreGraphicsAcceleratedBackend, CoreGraphicsBackend};
use azure_hl::{Direct2DBackend, NoBackend, RecordingBackend, SkiaBackend};
use bindgen::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};
use cairo::{cairo_font_face_t, cairo_matrix_t, cairo_scaled_font_t};
use cairo::bindgen::{cairo_font_face_destroy, cairo_font_options_create};
use cairo::bindgen::{cairo_font_options_destroy, cairo_matrix_init_identity, cairo_matrix_scale};
use cairo::bindgen::{cairo_scaled_font_create};
use cairo::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;
use core_graphics::font::CGFontRef;
use core_text::font::{CTFont, CTFontRef};

#[cfg(target_os="macos")]
type NativeFont = CTFont;

type SkTypeface = *c_void;

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,

    drop {
        AzReleaseScaledFont(self.azure_scaled_font);
    }
}

impl ScaledFont {
    static priv fn create_cairo_font(face: *cairo_font_face_t, size: AzFloat)
                                  -> *cairo_scaled_font_t {
        // FIXME: error handling

        let idmatrix: cairo_matrix_t = {
            xx: 0 as c_double,
            yx: 0 as c_double,
            xy: 0 as c_double,
            yy: 0 as c_double,
            x0: 0 as c_double,
            y0: 0 as c_double
        };
        cairo_matrix_init_identity(ptr::to_unsafe_ptr(&idmatrix));

        let fontmatrix = idmatrix;
        cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix), size as c_double, size as c_double);
        let options = cairo_font_options_create();
        let cfont = cairo_scaled_font_create(face,
                                             ptr::to_unsafe_ptr(&fontmatrix),
                                             ptr::to_unsafe_ptr(&idmatrix),
                                             options);
        cairo_font_options_destroy(options);

        return cfont;
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    static pub fn new(backend: BackendType, native_font: &const CTFont, size: AzFloat)
                   -> ScaledFont {
        let mut azure_native_font = {
            mType: 0,
            mFont: ptr::null()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;

                unsafe {
                    azure_native_font.mFont = cast::transmute(native_font.copy_to_CGFont());
                }
            }
            CairoBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_CAIRO_FONT_FACE;

                // TODO(Issue #184): may want to just reuse CGFont stored in servo's QuartzFontHandle.
                // This would require creating some trait like CGFontProvider with .get_CGFont().
                let cg_font = native_font.copy_to_CGFont();
                let face = cairo_quartz_font_face_create_for_cgfont(cg_font);
                if face == ptr::null() { fail; }

                let cairo_font = ScaledFont::create_cairo_font(face, size);
                cairo_font_face_destroy(face);

                unsafe {
                    azure_native_font.mFont = cast::transmute(cairo_font);
                }
            }
            NoBackend | Direct2DBackend | RecordingBackend => {
                fail ~"don't know how to make a scaled font for this backend";
            }
        }

        let azure_native_font_ptr = ptr::to_unsafe_ptr(&azure_native_font);
        let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
        ScaledFont { azure_scaled_font: move azure_scaled_font }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[link_args="-lskia"]
extern {
    #[cfg(target_os="macos")]
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *SkTypeface;
}

<commit_msg>Fix linux build breakage from misplaced CG/CT imports.<commit_after>extern mod cairo;

use azure_hl::{BackendType, CairoBackend, CoreGraphicsAcceleratedBackend, CoreGraphicsBackend};
use azure_hl::{Direct2DBackend, NoBackend, RecordingBackend, SkiaBackend};
use bindgen::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};
use cairo::{cairo_font_face_t, cairo_matrix_t, cairo_scaled_font_t};
use cairo::bindgen::{cairo_font_face_destroy, cairo_font_options_create};
use cairo::bindgen::{cairo_font_options_destroy, cairo_matrix_init_identity, cairo_matrix_scale};
use cairo::bindgen::{cairo_scaled_font_create};

#[cfg(target_os="macos")]
type NativeFont = CTFont;

type SkTypeface = *c_void;

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,

    drop {
        AzReleaseScaledFont(self.azure_scaled_font);
    }
}

impl ScaledFont {
    static priv fn create_cairo_font(face: *cairo_font_face_t, size: AzFloat)
                                  -> *cairo_scaled_font_t {
        // FIXME: error handling

        let idmatrix: cairo_matrix_t = {
            xx: 0 as c_double,
            yx: 0 as c_double,
            xy: 0 as c_double,
            yy: 0 as c_double,
            x0: 0 as c_double,
            y0: 0 as c_double
        };
        cairo_matrix_init_identity(ptr::to_unsafe_ptr(&idmatrix));

        let fontmatrix = idmatrix;
        cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix), size as c_double, size as c_double);
        let options = cairo_font_options_create();
        let cfont = cairo_scaled_font_create(face,
                                             ptr::to_unsafe_ptr(&fontmatrix),
                                             ptr::to_unsafe_ptr(&idmatrix),
                                             options);
        cairo_font_options_destroy(options);

        return cfont;
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    static pub fn new(backend: BackendType, native_font: &const CTFont, size: AzFloat)
                   -> ScaledFont {
        use core_graphics::font::CGFontRef;
        use core_text::font::{CTFont, CTFontRef};
        use cairo::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;

        let mut azure_native_font = {
            mType: 0,
            mFont: ptr::null()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;

                unsafe {
                    azure_native_font.mFont = cast::transmute(native_font.copy_to_CGFont());
                }
            }
            CairoBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_CAIRO_FONT_FACE;

                // TODO(Issue #184): may want to just reuse CGFont stored in servo's QuartzFontHandle.
                // This would require creating some trait like CGFontProvider with .get_CGFont().
                let cg_font = native_font.copy_to_CGFont();
                let face = cairo_quartz_font_face_create_for_cgfont(cg_font);
                if face == ptr::null() { fail; }

                let cairo_font = ScaledFont::create_cairo_font(face, size);
                cairo_font_face_destroy(face);

                unsafe {
                    azure_native_font.mFont = cast::transmute(cairo_font);
                }
            }
            NoBackend | Direct2DBackend | RecordingBackend => {
                fail ~"don't know how to make a scaled font for this backend";
            }
        }

        let azure_native_font_ptr = ptr::to_unsafe_ptr(&azure_native_font);
        let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
        ScaledFont { azure_scaled_font: move azure_scaled_font }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[link_args="-lskia"]
extern {
    #[cfg(target_os="macos")]
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *SkTypeface;
}

<|endoftext|>


<commit_before>//! The `join` macro.

/// Polls multiple futures simultaneously, returning a tuple
/// of all results once complete.
///
/// While `join!(a, b)` is similar to `(await!(a), await!(b))`,
/// `join!` polls both futures concurrently and therefore is more efficent.
///
/// This macro is only usable inside of async functions, closures, and blocks.
///
/// # Examples
///
/// ```
/// #![feature(pin, async_await, await_macro, futures_api)]
/// # futures::executor::block_on(async {
/// use futures::{join, future};
///
/// let a = future::ready(1);
/// let b = future::ready(2);
///
/// assert_eq!(join!(a, b), (1, 2));
/// # });
/// ```
#[macro_export]
macro_rules! join {
    ($($fut:ident),*) => { {
        $(
            let mut $fut = $crate::future::maybe_done($fut);
            $crate::pin_mut!($fut);
        )*
        loop {
            let mut all_done = true;
            $(
                if let $crate::core_reexport::task::Poll::Pending = $crate::poll!($fut.reborrow()) {
                    all_done = false;
                }
            )*
            if all_done {
                break;
            } else {
                $crate::pending!();
            }
        }

        ($(
            $fut.reborrow().take_output().unwrap(),
        )*)
    } }
}

/// Attempts to poll multiple futures simultaneously, returning a `Result`
/// of a tuple of all of the results once complete.
///
/// `try_join!` is similar to `join!`, but completes immediately if any of
/// the futures return an error.
///
/// This macro is only usable inside of async functions, closures, and blocks.
///
/// # Examples
///
/// ```
/// #![feature(pin, async_await, await_macro, futures_api)]
/// # futures::executor::block_on(async {
/// use futures::{try_join, future};
///
/// let a = future::ready(Ok::<i32, i32>(1));
/// let b = future::ready(Err::<u64, i32>(2));
///
/// assert_eq!(try_join!(a, b), Err(2));
///
/// let a = future::ready(Ok::<i32, i32>(1));
/// let b = future::ready(Ok::<u64, i32>(2));
///
/// assert_eq!(try_join!(a, b), Ok((1, 2)));
/// # });
/// ```
#[macro_export]
macro_rules! try_join {
    ($($fut:ident),*) => { {
        $(
            let mut $fut = $crate::future::maybe_done($fut);
            $crate::pin_mut!($fut);
        )*
        let res: $crate::core_reexport::result::Result<(), _> = loop {
            let mut all_done = true;
            $(
                if let $crate::core_reexport::task::Poll::Pending = $crate::poll!($fut.reborrow()) {
                    all_done = false;
                } else if $fut.reborrow().output_mut().unwrap().is_err() {
                    // `.err().unwrap()` rather than `.unwrap_err()` so that we don't introduce
                    // a `T: Debug` bound.
                    break $crate::core_reexport::result::Result::Err(
                        $fut.reborrow().take_output().unwrap().err().unwrap()
                    );
                }
            )*
            if all_done {
                break $crate::core_reexport::result::Result::Ok(());
            } else {
                $crate::pending!();
            }
        };

        res.map(|()| ($(
            // `.ok().unwrap()` rather than `.unwrap()` so that we don't introduce
            // an `E: Debug` bound.
            $fut.reborrow().take_output().unwrap().ok().unwrap(),
        )*))
    } }
}
<commit_msg>Cleanup join! by using Poll::is_pending<commit_after>//! The `join` macro.

/// Polls multiple futures simultaneously, returning a tuple
/// of all results once complete.
///
/// While `join!(a, b)` is similar to `(await!(a), await!(b))`,
/// `join!` polls both futures concurrently and therefore is more efficent.
///
/// This macro is only usable inside of async functions, closures, and blocks.
///
/// # Examples
///
/// ```
/// #![feature(pin, async_await, await_macro, futures_api)]
/// # futures::executor::block_on(async {
/// use futures::{join, future};
///
/// let a = future::ready(1);
/// let b = future::ready(2);
///
/// assert_eq!(join!(a, b), (1, 2));
/// # });
/// ```
#[macro_export]
macro_rules! join {
    ($($fut:ident),*) => { {
        $(
            let mut $fut = $crate::future::maybe_done($fut);
            $crate::pin_mut!($fut);
        )*
        loop {
            let mut all_done = true;
            $(
                if $crate::poll!($fut.reborrow()).is_pending() {
                    all_done = false;
                }
            )*
            if all_done {
                break;
            } else {
                $crate::pending!();
            }
        }

        ($(
            $fut.reborrow().take_output().unwrap(),
        )*)
    } }
}

/// Attempts to poll multiple futures simultaneously, returning a `Result`
/// of a tuple of all of the results once complete.
///
/// `try_join!` is similar to `join!`, but completes immediately if any of
/// the futures return an error.
///
/// This macro is only usable inside of async functions, closures, and blocks.
///
/// # Examples
///
/// ```
/// #![feature(pin, async_await, await_macro, futures_api)]
/// # futures::executor::block_on(async {
/// use futures::{try_join, future};
///
/// let a = future::ready(Ok::<i32, i32>(1));
/// let b = future::ready(Err::<u64, i32>(2));
///
/// assert_eq!(try_join!(a, b), Err(2));
///
/// let a = future::ready(Ok::<i32, i32>(1));
/// let b = future::ready(Ok::<u64, i32>(2));
///
/// assert_eq!(try_join!(a, b), Ok((1, 2)));
/// # });
/// ```
#[macro_export]
macro_rules! try_join {
    ($($fut:ident),*) => { {
        $(
            let mut $fut = $crate::future::maybe_done($fut);
            $crate::pin_mut!($fut);
        )*
        let res: $crate::core_reexport::result::Result<(), _> = loop {
            let mut all_done = true;
            $(
                if $crate::poll!($fut.reborrow()).is_pending() {
                    all_done = false;
                } else if $fut.reborrow().output_mut().unwrap().is_err() {
                    // `.err().unwrap()` rather than `.unwrap_err()` so that we don't introduce
                    // a `T: Debug` bound.
                    break $crate::core_reexport::result::Result::Err(
                        $fut.reborrow().take_output().unwrap().err().unwrap()
                    );
                }
            )*
            if all_done {
                break $crate::core_reexport::result::Result::Ok(());
            } else {
                $crate::pending!();
            }
        };

        res.map(|()| ($(
            // `.ok().unwrap()` rather than `.unwrap()` so that we don't introduce
            // an `E: Debug` bound.
            $fut.reborrow().take_output().unwrap().ok().unwrap(),
        )*))
    } }
}
<|endoftext|>


<commit_before>#![no_main]
use libfuzzer_sys::fuzz_target;
use std::str;

extern crate nom;

use nom::{
  branch::alt,
  bytes::complete::tag,
  character::complete::char,
  character::complete::{digit1 as digit, space0 as space},
  combinator::{map_res, verify},
  multi::fold_many0,
  sequence::{delimited, pair},
  IResult,
};

use std::str::FromStr;
use std::cell::RefCell;

thread_local! {
    pub static LEVEL: RefCell<u32> = RefCell::new(0);
}

fn reset() {
    LEVEL.with(|l| {
        *l.borrow_mut() = 0;
    });
}

fn incr(i: &str) -> IResult<&str, ()> {
    LEVEL.with(|l| {
        *l.borrow_mut() += 1;

        // limit the number of recursions, the fuzzer keeps running into them
        if *l.borrow() >= 8192 {
            return Err(nom::Err::Failure(nom::error::Error::new(i, nom::error::ErrorKind::Count)));
        } else {
            Ok((i, ()))
        }
    })
}

fn decr() {
    LEVEL.with(|l| {
        *l.borrow_mut() -= 1;
    });
}

fn parens(i: &str) -> IResult<&str, i64> {
      delimited(space, delimited(tag("("), expr, tag(")")), space)(i)
}

fn factor(i: &str) -> IResult<&str, i64> {
  alt((
    map_res(delimited(space, digit, space), FromStr::from_str),
    parens,
  ))(i)
}

fn term(i: &str) -> IResult<&str, i64> {
  incr(i)?;
  let (i, init) = factor(i).map_err(|e| { decr(); e })?;

  let res = fold_many0(
    alt((
        pair(char('*'), factor),
        pair(char('/'), verify(factor, |i| *i != 0)),
    )),
    || init,
    |acc, (op, val): (char, i64)| {
      if op == '*' {
        acc.saturating_mul(val)
      } else {
        match acc.checked_div(val) {
            Some(v) => v,
            // we get a division with overflow because we can get acc = i64::MIN and val = -1
            // the division by zero is already checked earlier by verify
            None => i64::MAX,
        }
      }
    },
  )(i);

  decr();
  res
}

fn expr(i: &str) -> IResult<&str, i64> {
  incr(i)?;
  let (i, init) = term(i).map_err(|e| { decr(); e })?;

  let res = fold_many0(
    pair(alt((char('+'), char('-'))), term),
    || init,
    |acc, (op, val): (char, i64)| {
      if op == '+' {
        acc.saturating_add(val)
      } else {
        acc.saturating_sub(val)
      }
    },
  )(i);

  decr();
  res
}

fuzz_target!(|data: &[u8]| {
    reset();
    // fuzzed code goes here
    let temp = match str::from_utf8(data) {
        Ok(v) => {
            //println!("v: {}", v);
            factor(v)
        },
        Err(e) => factor("2"),
    };
});
<commit_msg>fix a stack overflow in the expression parser<commit_after>#![no_main]
use libfuzzer_sys::fuzz_target;
use std::str;

extern crate nom;

use nom::{
  branch::alt,
  bytes::complete::tag,
  character::complete::char,
  character::complete::{digit1 as digit, space0 as space},
  combinator::{map, map_res, verify},
  multi::fold_many0,
  sequence::{delimited, pair, terminated},
  IResult,
};

use std::str::FromStr;
use std::cell::RefCell;

thread_local! {
    pub static LEVEL: RefCell<u32> = RefCell::new(0);
}

fn reset() {
    LEVEL.with(|l| {
        *l.borrow_mut() = 0;
    });
}

fn incr(i: &str) -> IResult<&str, ()> {
    LEVEL.with(|l| {
        *l.borrow_mut() += 1;

        // limit the number of recursions, the fuzzer keeps running into them
        if *l.borrow() >= 8192 {
            return Err(nom::Err::Failure(nom::error::Error::new(i, nom::error::ErrorKind::Count)));
        } else {
            Ok((i, ()))
        }
    })
}

fn decr() {
    LEVEL.with(|l| {
        *l.borrow_mut() -= 1;
    });
}

fn parens(i: &str) -> IResult<&str, i64> {
      delimited(space, delimited(
              terminated(tag("("), incr),
              expr,
              map(tag(")"),  |_| decr())
      ), space)(i)
}

fn factor(i: &str) -> IResult<&str, i64> {
  alt((
    map_res(delimited(space, digit, space), FromStr::from_str),
    parens,
  ))(i)
}

fn term(i: &str) -> IResult<&str, i64> {
  incr(i)?;
  let (i, init) = factor(i).map_err(|e| { decr(); e })?;

  let res = fold_many0(
    alt((
        pair(char('*'), factor),
        pair(char('/'), verify(factor, |i| *i != 0)),
    )),
    || init,
    |acc, (op, val): (char, i64)| {
      if op == '*' {
        acc.saturating_mul(val)
      } else {
        match acc.checked_div(val) {
            Some(v) => v,
            // we get a division with overflow because we can get acc = i64::MIN and val = -1
            // the division by zero is already checked earlier by verify
            None => i64::MAX,
        }
      }
    },
  )(i);

  decr();
  res
}

fn expr(i: &str) -> IResult<&str, i64> {
  incr(i)?;
  let (i, init) = term(i).map_err(|e| { decr(); e })?;

  let res = fold_many0(
    pair(alt((char('+'), char('-'))), term),
    || init,
    |acc, (op, val): (char, i64)| {
      if op == '+' {
        acc.saturating_add(val)
      } else {
        acc.saturating_sub(val)
      }
    },
  )(i);

  decr();
  res
}

fuzz_target!(|data: &[u8]| {
    reset();
    // fuzzed code goes here
    let temp = match str::from_utf8(data) {
        Ok(v) => {
            //println!("v: {}", v);
            factor(v)
        },
        Err(e) => factor("2"),
    };
});
<|endoftext|>


<commit_before>use std::env;
use std::net::TcpStream;
use std::io::prelude::*;
use std::fs::File;

fn main() {
    println!("Hello, world!");
}
<commit_msg>add first line of connection test<commit_after>use std::env;
use std::net::TcpStream;
use std::io::prelude::*;
use std::fs::File;

fn main() {
    println!("Start Download Manager");

    //let tab: Vec<_> = env::args().collect();
    //assert_ne!(tab.len(), 1);
    let file = File::create("received_file");
    let mut stream = TcpStream::connect("127.0.0.1:8080").unwrap();
    let mut buf = vec![] ;
    let _ = stream.read_to_end(&mut buf).unwrap();
}
<|endoftext|>


<commit_before>use std::alloc::{alloc, dealloc, Layout};
use std::collections::HashMap;

#[derive(Debug)]
struct Node {
    key: i32,
    val: i32,
    prev: Option<*mut Node>,
    next: Option<*mut Node>,
}

#[derive(Debug)]
struct LRUCache {
    cap: i32,
    count: i32,
    hm: HashMap<i32, *mut Node>,
    entry: Option<*mut Node>,
    exit: Option<*mut Node>,
}

impl LRUCache {
    fn new(capacity: i32) -> Self {
        LRUCache {
            cap: capacity,
            count: 0,
            hm: HashMap::with_capacity(capacity as usize),
            entry: None,
            exit: None,
        }
    }
    fn get(&mut self, key: i32) -> i32 {
        unsafe {
            match self.hm.get(&key) {
                Some(vp) => {
                    let node = &mut **vp;
                    if let Some(prevp) = node.prev {
                        let prev = &mut *prevp;
                        match node.next {
                            Some(nextp) => {
                                let next = &mut *nextp;
                                prev.next = Some(nextp);
                                next.prev = Some(prevp);
                            }
                            None => {
                                prev.next = None;
                                self.exit = Some(prevp);
                            }
                        }
                        let entryp = self.entry.unwrap();
                        let entry = &mut *entryp;
                        node.next = Some(entryp);
                        node.prev = None;
                        entry.prev = Some(node);
                        self.entry = Some(*vp);
                    }
                    node.val
                }
                None => -1,
            }
        }
    }

    fn put(&mut self, key: i32, value: i32) {
        unsafe {
            match self.hm.get(&key) {
                Some(vp) => {
                    let node = &mut **vp;
                    if let Some(prevp) = node.prev {
                        let prev = &mut *prevp;
                        match node.next {
                            Some(nextp) => {
                                let next = &mut *nextp;
                                prev.next = Some(nextp);
                                next.prev = Some(prevp);
                            }
                            None => {
                                prev.next = None;
                                self.exit = Some(prevp);
                            }
                        }
                        let entryp = self.entry.unwrap();
                        let entry = &mut *entryp;
                        node.next = Some(entryp);
                        node.prev = None;
                        entry.prev = Some(node);
                        self.entry = Some(*vp);
                    }
                    node.val = value;
                }
                None => {
                    let nodep = alloc(Layout::new::<Node>()) as *mut Node;
                    let node = &mut *nodep;
                    node.key = key;
                    node.val = value;
                    if self.count > 0 {
                        let entryp = self.entry.unwrap();
                        let entry = &mut *entryp;
                        node.next = Some(entry);
                        entry.prev = Some(nodep);
                        self.entry = Some(nodep);
                    } else {
                        self.entry = Some(nodep);
                        self.exit = Some(nodep);
                    }
                    self.hm.insert(key, nodep);
                    self.count += 1;
                    self.clean()
                }
            }
        }
    }

    fn clean(&mut self) {
        unsafe {
            while self.count > self.cap {
                if let Some(exitp) = self.exit {
                    let exit_node = &mut *exitp;
                    if let Some(prevp) = exit_node.prev {
                        let mut prev = &mut *prevp;
                        prev.next = None;
                        self.exit = exit_node.prev;
                    } else {
                        self.exit = None;
                    }
                    self.hm.remove(&exit_node.key);
                    // dealloc(exitp as *mut u8, Layout::new::<Node>());
                }
                self.count -= 1;
            }
        }
    }

    fn display(&self) {
        unsafe {
            println!("Cache count/cap: {:?}/{:?}", self.count, self.cap);
            println!("Cache map:");
            for (k, v) in &self.hm {
                println!("- {:?} -> {:?}", k, (**v).val);
            }
            println!("Cache node:");
            println!("Entry -> {:?}", self.entry);
            println!("Exit -> {:?}", self.exit);
        }
    }
}

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

    #[test]
    fn it_works() {
        let mut cache = LRUCache::new(2);
        cache.put(1, 1);
        cache.put(2, 2);
        cache.display();
        assert_eq!(cache.get(1), 1); // 返回  1
        cache.put(3, 3); // 该操作会使得密钥 2 作废
        assert_eq!(cache.get(2), -1); // 返回 -1 (未找到)
        cache.put(4, 4); // 该操作会使得密钥 1 作废
        assert_eq!(cache.get(1), -1); // 返回 -1 (未找到)
        assert_eq!(cache.get(3), 3); // 返回  3
        assert_eq!(cache.get(4), 4); // 返回  4
    }

    #[test]
    fn it_works2() {
        let mut cache = LRUCache::new(2);
        cache.put(2, 1);
        cache.put(1, 1);
        cache.put(2, 3);
        cache.put(4, 1);
        cache.get(1);
        cache.get(2);
        cache.display();
    }

    #[test]
    fn it_works3() {
        // ["LRUCache","put","put","put","get","put","put","get","put","put","get","put","get","get","get","put","put","get","put","get"]
        // [[10],[7,28],[7,1],[8,15],[6],[10,27],[8,10],[8],[6,29],[1,9],[6],[10,7],[1],[2],[13],[8,30],[1,5],[1],[13,2],[12]]
        let mut cache = LRUCache::new(10);
        cache.put(7, 28);
        cache.put(7, 1);
        cache.put(8, 15);
        cache.get(6);
        cache.put(10, 27);
        cache.put(8, 10);
        cache.get(8);
    }

    fn leetcode_test(size: i32, cmds: Vec<&str>, args: Vec<Vec<i32>>) {
        let mut cache = LRUCache::new(size);
        for (cmd, arg) in cmds.iter().zip(args) {
            match cmd.as_ref() {
                "get" => {
                    let r = cache.get(arg[0]);
                    println!("Getting {:?} => {:?}", arg, r);
                }
                "put" => {
                    println!("Putting {:?}", arg);
                    cache.put(arg[0], arg[1]);
                }
                _ => unreachable!(),
            }
        }
    }

    #[test]
    fn leetcode_test1() {
        let cmds = vec![
            "put", "put", "put", "put", "put", "get", "put", "get", "get", "put", "get", "put",
            "put", "put", "get", "put", "get", "get", "get", "get", "put", "put", "get", "get",
            "get", "put", "put", "get", "put", "get", "put", "get", "get", "get", "put", "put",
            "put", "get", "put", "get", "get", "put", "put", "get", "put", "put", "put", "put",
            "get", "put", "put", "get", "put", "put", "get", "put", "put", "put", "put", "put",
            "get", "put", "put", "get", "put", "get", "get", "get", "put", "get", "get", "put",
            "put", "put", "put", "get", "put", "put", "put", "put", "get", "get", "get", "put",
            "put", "put", "get", "put", "put", "put", "get", "put", "put", "put", "get", "get",
            "get", "put", "put", "put", "put", "get", "put", "put", "put", "put", "put", "put",
            "put",
        ];
        let args = vec![
            vec![10, 13],
            vec![3, 17],
            vec![6, 11],
            vec![10, 5],
            vec![9, 10],
            vec![13],
            vec![2, 19],
            vec![2],
            vec![3],
            vec![5, 25],
            vec![8],
            vec![9, 22],
            vec![5, 5],
            vec![1, 30],
            vec![11],
            vec![9, 12],
            vec![7],
            vec![5],
            vec![8],
            vec![9],
            vec![4, 30],
            vec![9, 3],
            vec![9],
            vec![10],
            vec![10],
            vec![6, 14],
            vec![3, 1],
            vec![3],
            vec![10, 11],
            vec![8],
            vec![2, 14],
            vec![1],
            vec![5],
            vec![4],
            vec![11, 4],
            vec![12, 24],
            vec![5, 18],
            vec![13],
            vec![7, 23],
            vec![8],
            vec![12],
            vec![3, 27],
            vec![2, 12],
            vec![5],
            vec![2, 9],
            vec![13, 4],
            vec![8, 18],
            vec![1, 7],
            vec![6],
            vec![9, 29],
            vec![8, 21],
            vec![5],
            vec![6, 30],
            vec![1, 12],
            vec![10],
            vec![4, 15],
            vec![7, 22],
            vec![11, 26],
            vec![8, 17],
            vec![9, 29],
            vec![5],
            vec![3, 4],
            vec![11, 30],
            vec![12],
            vec![4, 29],
            vec![3],
            vec![9],
            vec![6],
            vec![3, 4],
            vec![1],
            vec![10],
            vec![3, 29],
            vec![10, 28],
            vec![1, 20],
            vec![11, 13],
            vec![3],
            vec![3, 12],
            vec![3, 8],
            vec![10, 9],
            vec![3, 26],
            vec![8],
            vec![7],
            vec![5],
            vec![13, 17],
            vec![2, 27],
            vec![11, 15],
            vec![12],
            vec![9, 19],
            vec![2, 15],
            vec![3, 16],
            vec![1],
            vec![12, 17],
            vec![9, 1],
            vec![6, 19],
            vec![4],
            vec![5],
            vec![5],
            vec![8, 1],
            vec![11, 7],
            vec![5, 2],
            vec![9, 28],
            vec![1],
            vec![2, 2],
            vec![7, 4],
            vec![4, 22],
            vec![7, 24],
            vec![9, 26],
            vec![13, 28],
            vec![11, 26],
        ];
        leetcode_test(10, cmds, args);
    }

    #[test]
    fn leetcode_test2() {
        let cmds = vec!["put", "put", "put", "put", "get", "get"];
        let args = vec![vec![2, 1], vec![1, 1], vec![2, 3], vec![4, 1], vec![1], vec![2]];
        leetcode_test(2, cmds, args);
    }
}
<commit_msg>LRU cache<commit_after>use std::alloc::{alloc_zeroed, dealloc, Layout};
use std::collections::HashMap;

#[derive(Debug)]
struct Node {
    key: i32,
    val: i32,
    prev: Option<*mut Node>,
    next: Option<*mut Node>,
}

#[derive(Debug)]
struct LRUCache {
    cap: i32,
    count: i32,
    hm: HashMap<i32, *mut Node>,
    entry: Option<*mut Node>,
    exit: Option<*mut Node>,
}

impl LRUCache {
    fn new(capacity: i32) -> Self {
        LRUCache {
            cap: capacity,
            count: 0,
            hm: HashMap::with_capacity(capacity as usize),
            entry: None,
            exit: None,
        }
    }
    fn get(&mut self, key: i32) -> i32 {
        unsafe {
            match self.hm.get(&key) {
                Some(vp) => {
                    let node = &mut **vp;
                    if let Some(prevp) = node.prev {
                        let prev = &mut *prevp;
                        match node.next {
                            Some(nextp) => {
                                let next = &mut *nextp;
                                prev.next = Some(nextp);
                                next.prev = Some(prevp);
                            }
                            None => {
                                prev.next = None;
                                self.exit = Some(prevp);
                            }
                        }
                        let entryp = self.entry.unwrap();
                        let entry = &mut *entryp;
                        node.next = Some(entryp);
                        node.prev = None;
                        entry.prev = Some(node);
                        self.entry = Some(*vp);
                    }
                    node.val
                }
                None => -1,
            }
        }
    }

    fn put(&mut self, key: i32, value: i32) {
        unsafe {
            match self.hm.get(&key) {
                Some(vp) => {
                    let node = &mut **vp;
                    if let Some(prevp) = node.prev {
                        let prev = &mut *prevp;
                        match node.next {
                            Some(nextp) => {
                                let next = &mut *nextp;
                                prev.next = Some(nextp);
                                next.prev = Some(prevp);
                            }
                            None => {
                                prev.next = None;
                                self.exit = Some(prevp);
                            }
                        }
                        let entryp = self.entry.unwrap();
                        let entry = &mut *entryp;
                        node.next = Some(entryp);
                        node.prev = None;
                        entry.prev = Some(node);
                        self.entry = Some(*vp);
                    }
                    node.val = value;
                }
                None => {
                    let nodep = alloc_zeroed(Layout::new::<Node>()) as *mut Node;
                    let node = &mut *nodep;
                    node.key = key;
                    node.val = value;
                    if self.count > 0 {
                        let entryp = self.entry.unwrap();
                        let entry = &mut *entryp;
                        node.next = Some(entry);
                        entry.prev = Some(nodep);
                        self.entry = Some(nodep);
                    } else {
                        self.entry = Some(nodep);
                        self.exit = Some(nodep);
                    }
                    self.hm.insert(key, nodep);
                    self.count += 1;
                    self.clean()
                }
            }
        }
    }

    fn clean(&mut self) {
        unsafe {
            while self.count > self.cap {
                if let Some(exitp) = self.exit {
                    let exit_node = &mut *exitp;
                    if let Some(prevp) = exit_node.prev {
                        let mut prev = &mut *prevp;
                        prev.next = None;
                        self.exit = exit_node.prev;
                    } else {
                        self.exit = None;
                    }
                    self.hm.remove(&exit_node.key);
                    dealloc(exitp as *mut u8, Layout::new::<Node>());
                }
                self.count -= 1;
            }
        }
    }

    fn display(&self) {
        unsafe {
            println!("Cache count/cap: {:?}/{:?}", self.count, self.cap);
            println!("Cache map:");
            for (k, v) in &self.hm {
                println!("- {:?} -> {:?}", k, (**v).val);
            }
            println!("Cache node:");
            println!("Entry -> {:?}", self.entry);
            println!("Exit -> {:?}", self.exit);
        }
    }
}

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

    #[test]
    fn it_works() {
        let mut cache = LRUCache::new(2);
        cache.put(1, 1);
        cache.put(2, 2);
        cache.display();
        assert_eq!(cache.get(1), 1); // 返回  1
        cache.put(3, 3); // 该操作会使得密钥 2 作废
        assert_eq!(cache.get(2), -1); // 返回 -1 (未找到)
        cache.put(4, 4); // 该操作会使得密钥 1 作废
        assert_eq!(cache.get(1), -1); // 返回 -1 (未找到)
        assert_eq!(cache.get(3), 3); // 返回  3
        assert_eq!(cache.get(4), 4); // 返回  4
    }

    #[test]
    fn it_works2() {
        let mut cache = LRUCache::new(2);
        cache.put(2, 1);
        cache.put(1, 1);
        cache.put(2, 3);
        cache.put(4, 1);
        cache.get(1);
        cache.get(2);
        cache.display();
    }

    #[test]
    fn it_works3() {
        // ["LRUCache","put","put","put","get","put","put","get","put","put","get","put","get","get","get","put","put","get","put","get"]
        // [[10],[7,28],[7,1],[8,15],[6],[10,27],[8,10],[8],[6,29],[1,9],[6],[10,7],[1],[2],[13],[8,30],[1,5],[1],[13,2],[12]]
        let mut cache = LRUCache::new(10);
        cache.put(7, 28);
        cache.put(7, 1);
        cache.put(8, 15);
        cache.get(6);
        cache.put(10, 27);
        cache.put(8, 10);
        cache.get(8);
    }

    fn leetcode_test(size: i32, cmds: Vec<&str>, args: Vec<Vec<i32>>) {
        let mut cache = LRUCache::new(size);
        for (cmd, arg) in cmds.iter().zip(args) {
            match cmd.as_ref() {
                "get" => {
                    let r = cache.get(arg[0]);
                    println!("Getting {:?} => {:?}", arg, r);
                }
                "put" => {
                    println!("Putting {:?}", arg);
                    cache.put(arg[0], arg[1]);
                }
                _ => unreachable!(),
            }
        }
    }

    #[test]
    fn leetcode_test1() {
        let cmds = vec![
            "put", "put", "put", "put", "put", "get", "put", "get", "get", "put", "get", "put",
            "put", "put", "get", "put", "get", "get", "get", "get", "put", "put", "get", "get",
            "get", "put", "put", "get", "put", "get", "put", "get", "get", "get", "put", "put",
            "put", "get", "put", "get", "get", "put", "put", "get", "put", "put", "put", "put",
            "get", "put", "put", "get", "put", "put", "get", "put", "put", "put", "put", "put",
            "get", "put", "put", "get", "put", "get", "get", "get", "put", "get", "get", "put",
            "put", "put", "put", "get", "put", "put", "put", "put", "get", "get", "get", "put",
            "put", "put", "get", "put", "put", "put", "get", "put", "put", "put", "get", "get",
            "get", "put", "put", "put", "put", "get", "put", "put", "put", "put", "put", "put",
            "put",
        ];
        let args = vec![
            vec![10, 13],
            vec![3, 17],
            vec![6, 11],
            vec![10, 5],
            vec![9, 10],
            vec![13],
            vec![2, 19],
            vec![2],
            vec![3],
            vec![5, 25],
            vec![8],
            vec![9, 22],
            vec![5, 5],
            vec![1, 30],
            vec![11],
            vec![9, 12],
            vec![7],
            vec![5],
            vec![8],
            vec![9],
            vec![4, 30],
            vec![9, 3],
            vec![9],
            vec![10],
            vec![10],
            vec![6, 14],
            vec![3, 1],
            vec![3],
            vec![10, 11],
            vec![8],
            vec![2, 14],
            vec![1],
            vec![5],
            vec![4],
            vec![11, 4],
            vec![12, 24],
            vec![5, 18],
            vec![13],
            vec![7, 23],
            vec![8],
            vec![12],
            vec![3, 27],
            vec![2, 12],
            vec![5],
            vec![2, 9],
            vec![13, 4],
            vec![8, 18],
            vec![1, 7],
            vec![6],
            vec![9, 29],
            vec![8, 21],
            vec![5],
            vec![6, 30],
            vec![1, 12],
            vec![10],
            vec![4, 15],
            vec![7, 22],
            vec![11, 26],
            vec![8, 17],
            vec![9, 29],
            vec![5],
            vec![3, 4],
            vec![11, 30],
            vec![12],
            vec![4, 29],
            vec![3],
            vec![9],
            vec![6],
            vec![3, 4],
            vec![1],
            vec![10],
            vec![3, 29],
            vec![10, 28],
            vec![1, 20],
            vec![11, 13],
            vec![3],
            vec![3, 12],
            vec![3, 8],
            vec![10, 9],
            vec![3, 26],
            vec![8],
            vec![7],
            vec![5],
            vec![13, 17],
            vec![2, 27],
            vec![11, 15],
            vec![12],
            vec![9, 19],
            vec![2, 15],
            vec![3, 16],
            vec![1],
            vec![12, 17],
            vec![9, 1],
            vec![6, 19],
            vec![4],
            vec![5],
            vec![5],
            vec![8, 1],
            vec![11, 7],
            vec![5, 2],
            vec![9, 28],
            vec![1],
            vec![2, 2],
            vec![7, 4],
            vec![4, 22],
            vec![7, 24],
            vec![9, 26],
            vec![13, 28],
            vec![11, 26],
        ];
        leetcode_test(10, cmds, args);
    }

    #[test]
    fn leetcode_test2() {
        let cmds = vec!["put", "put", "put", "put", "get", "get"];
        let args = vec![vec![2, 1], vec![1, 1], vec![2, 3], vec![4, 1], vec![1], vec![2]];
        leetcode_test(2, cmds, args);
    }
}
<|endoftext|>


<commit_before>use cf = core_foundation;
use cf::array::CFArrayRef;
use cf::base::{
    AbstractCFType,
    AbstractCFTypeRef,
    CFAllocatorRef,
    CFIndex,
    CFRange,
    CFRelease,
    CFTypeRef,
    CFTypeID,
    kCFAllocatorDefault,
};
use cf::dictionary::CFDictionaryRef;
use cf::number::CFNumberRef;
use cf::set::CFSetRef;
use cf::string::CFStringRef;

use cg = core_graphics;
use cg::base::CGFloat;

use libc::c_void;

/*
* CTFontTraits.h
*/
// actually, these are extern enums
pub type CTFontFormat = u32;
pub const kCTFontFormatUnrecognized: CTFontFormat = 0;
pub const kCTFontFormatOpenTypePostScript: CTFontFormat = 1;
pub const kCTFontFormatOpenTypeTrueType: CTFontFormat = 2;
pub const kCTFontFormatTrueType: CTFontFormat = 3;
pub const kCTFontFormatPostScript: CTFontFormat = 4;
pub const kCTFontFormatBitmap: CTFontFormat = 5;

pub const kCTFontClassMaskShift: u32 = 28;

pub type CTFontSymbolicTraits = u32;
pub const kCTFontItalicTrait: CTFontSymbolicTraits = (1 << 0);
pub const kCTFontBoldTrait: CTFontSymbolicTraits = (1 << 1);
pub const kCTFontExpandedTrait: CTFontSymbolicTraits = (1 << 5);
pub const kCTFontCondensedTrait: CTFontSymbolicTraits = (1 << 6);
pub const kCTFontMonoSpaceTrait: CTFontSymbolicTraits = (1 << 10);
pub const kCTFontVerticalTrait: CTFontSymbolicTraits = (1 << 11);
pub const kCTFontUIOptimizedTrait: CTFontSymbolicTraits = (1 << 12);
pub const kCTFontClassMaskTrait: CTFontSymbolicTraits = (15 << kCTFontClassMaskShift);

pub type CTFontStylisticClass = u32;
pub const kCTFontUnknownClass: CTFontStylisticClass = (0 << kCTFontClassMaskShift);
pub const kCTFontOldStyleSerifsClass: CTFontStylisticClass = (1 << kCTFontClassMaskShift);
pub const kCTFontTransitionalSerifsClass: CTFontStylisticClass = (2 << kCTFontClassMaskShift);
pub const kCTFontModernSerifsClass: CTFontStylisticClass = (3 << kCTFontClassMaskShift);
pub const kCTFontClarendonSerifsClass: CTFontStylisticClass = (4 << kCTFontClassMaskShift);
pub const kCTFontSlabSerifsClass: CTFontStylisticClass = (5 << kCTFontClassMaskShift);
pub const kCTFontFreeformSerifsClass: CTFontStylisticClass = (7 << kCTFontClassMaskShift);
pub const kCTFontSansSerifClass: CTFontStylisticClass = (8 << kCTFontClassMaskShift);
pub const kCTFontOrnamentalsClass: CTFontStylisticClass = (9 << kCTFontClassMaskShift);
pub const kCTFontScriptsClass: CTFontStylisticClass = (10 << kCTFontClassMaskShift);
pub const kCTFontSymbolicClass: CTFontStylisticClass = (12 << kCTFontClassMaskShift);

/*
* CTFontDescriptor.h
*/
pub type CTFontOrientation = u32;
pub const kCTFontDefaultOrientation: CTFontOrientation = 0;
pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
pub const kCTFontVerticalOrientation: CTFontOrientation = 2;

pub type CTFontPriority = u32;
pub const kCTFontPrioritySystem: CTFontPriority = 10000;
pub const kCTFontPriorityNetwork: CTFontPriority = 20000;
pub const kCTFontPriorityComputer: CTFontPriority = 30000;
pub const kCTFontPriorityUser: CTFontPriority = 40000;
pub const kCTFontPriorityDynamic: CTFontPriority = 50000;
pub const kCTFontPriorityProcess: CTFontPriority = 60000;

struct __CTFontDescriptor { private: () }
pub type CTFontDescriptorRef = *__CTFontDescriptor;

impl CTFontDescriptorRef : AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef }
}

struct CTFontDescriptor {
    obj: CTFontDescriptorRef,

    drop {
        unsafe {
            CFRelease(cast::transmute(self.obj))
        }
    }
}

pub impl CTFontDescriptor : AbstractCFType<CTFontDescriptorRef> {
    pure fn get_ref() -> CTFontDescriptorRef { self.obj }

    static fn wrap(obj: CTFontDescriptorRef) -> CTFontDescriptor {
        CTFontDescriptor { obj: obj }
    }

    static fn unwrap(wrapper: CTFontDescriptor) -> CTFontDescriptorRef {
        wrapper.obj
    }
}

extern {
    /*
     * CTFontTraits.h
     */

    // font trait constants
    const kCTFontSymbolicTrait: CFStringRef;
    const kCTFontWeightTrait: CFStringRef;
    const kCTFontWidthTrait: CFStringRef;
    const kCTFontSlantTrait: CFStringRef;

    /*
     * CTFontDescriptor.h
     */

    // font attribute constants
    const kCTFontURLAttribute: CFStringRef;
    const kCTFontNameAttribute: CFStringRef;
    const kCTFontDisplayNameAttribute: CFStringRef;
    const kCTFontFamilyNameAttribute: CFStringRef;
    const kCTFontStyleNameAttribute: CFStringRef;
    const kCTFontTraitsAttribute: CFStringRef;
    const kCTFontVariationAttribute: CFStringRef;
    const kCTFontSizeAttribute: CFStringRef;
    const kCTFontMatrixAttribute: CFStringRef;
    const kCTFontCascadeListAttribute: CFStringRef;
    const kCTFontCharacterSetAttribute: CFStringRef;
    const kCTFontLanguagesAttribute: CFStringRef;
    const kCTFontBaselineAdjustAttribute: CFStringRef;
    const kCTFontMacintoshEncodingsAttribute: CFStringRef;
    const kCTFontFeaturesAttribute: CFStringRef;
    const kCTFontFeatureSettingsAttribute: CFStringRef;
    const kCTFontFixedAdvanceAttribute: CFStringRef;
    const kCTFontOrientationAttribute: CFStringRef;
    const kCTFontFormatAttribute: CFStringRef;
    const kCTFontRegistrationScopeAttribute: CFStringRef;
    const kCTFontPriorityAttribute: CFStringRef;
    const kCTFontEnabledAttribute: CFStringRef;

    fn CTFontDescriptorCopyAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef) -> CFTypeRef;
    fn CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef;
    fn CTFontDescriptorCopyLocalizedAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef, language: *CFStringRef) -> CFTypeRef;
    fn CTFontDescriptorCreateCopyWithAttributes(original: CTFontDescriptorRef, attributes: CFDictionaryRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateCopyWithFeature(original: CTFontDescriptorRef, featureTypeIdentifier: CFNumberRef, featureSelectorIdentifier: CFNumberRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateCopyWithVariation(original: CTFontDescriptorRef, variationIdentifier: CFNumberRef, variationValue: CGFloat) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateMatchingFontDescriptor(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateMatchingFontDescriptors(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateWithNameAndSize(name: CFStringRef, size: CGFloat) -> CTFontDescriptorRef;
    fn CTFontDescriptorGetTypeID() -> CFTypeID;
}<commit_msg>Implement CTFontDescriptor::family_name().<commit_after>use cf = core_foundation;
use cf::array::CFArrayRef;
use cf::base::{
    AbstractCFType,
    AbstractCFTypeRef,
    CFAllocatorRef,
    CFIndex,
    CFGetTypeID,
    CFRange,
    CFRelease,
    CFTypeRef,
    CFTypeID,
    kCFAllocatorDefault,
};
use cf::dictionary::CFDictionaryRef;
use cf::number::CFNumberRef;
use cf::set::CFSetRef;
use cf::string::{
    CFString,
    CFStringRef,
    CFStringGetTypeID,
};

use cg = core_graphics;
use cg::base::CGFloat;

use libc::c_void;

/*
* CTFontTraits.h
*/
// actually, these are extern enums
pub type CTFontFormat = u32;
pub const kCTFontFormatUnrecognized: CTFontFormat = 0;
pub const kCTFontFormatOpenTypePostScript: CTFontFormat = 1;
pub const kCTFontFormatOpenTypeTrueType: CTFontFormat = 2;
pub const kCTFontFormatTrueType: CTFontFormat = 3;
pub const kCTFontFormatPostScript: CTFontFormat = 4;
pub const kCTFontFormatBitmap: CTFontFormat = 5;

pub const kCTFontClassMaskShift: u32 = 28;

pub type CTFontSymbolicTraits = u32;
pub const kCTFontItalicTrait: CTFontSymbolicTraits = (1 << 0);
pub const kCTFontBoldTrait: CTFontSymbolicTraits = (1 << 1);
pub const kCTFontExpandedTrait: CTFontSymbolicTraits = (1 << 5);
pub const kCTFontCondensedTrait: CTFontSymbolicTraits = (1 << 6);
pub const kCTFontMonoSpaceTrait: CTFontSymbolicTraits = (1 << 10);
pub const kCTFontVerticalTrait: CTFontSymbolicTraits = (1 << 11);
pub const kCTFontUIOptimizedTrait: CTFontSymbolicTraits = (1 << 12);
pub const kCTFontClassMaskTrait: CTFontSymbolicTraits = (15 << kCTFontClassMaskShift);

pub type CTFontStylisticClass = u32;
pub const kCTFontUnknownClass: CTFontStylisticClass = (0 << kCTFontClassMaskShift);
pub const kCTFontOldStyleSerifsClass: CTFontStylisticClass = (1 << kCTFontClassMaskShift);
pub const kCTFontTransitionalSerifsClass: CTFontStylisticClass = (2 << kCTFontClassMaskShift);
pub const kCTFontModernSerifsClass: CTFontStylisticClass = (3 << kCTFontClassMaskShift);
pub const kCTFontClarendonSerifsClass: CTFontStylisticClass = (4 << kCTFontClassMaskShift);
pub const kCTFontSlabSerifsClass: CTFontStylisticClass = (5 << kCTFontClassMaskShift);
pub const kCTFontFreeformSerifsClass: CTFontStylisticClass = (7 << kCTFontClassMaskShift);
pub const kCTFontSansSerifClass: CTFontStylisticClass = (8 << kCTFontClassMaskShift);
pub const kCTFontOrnamentalsClass: CTFontStylisticClass = (9 << kCTFontClassMaskShift);
pub const kCTFontScriptsClass: CTFontStylisticClass = (10 << kCTFontClassMaskShift);
pub const kCTFontSymbolicClass: CTFontStylisticClass = (12 << kCTFontClassMaskShift);

/*
* CTFontDescriptor.h
*/
pub type CTFontOrientation = u32;
pub const kCTFontDefaultOrientation: CTFontOrientation = 0;
pub const kCTFontHorizontalOrientation: CTFontOrientation = 1;
pub const kCTFontVerticalOrientation: CTFontOrientation = 2;

pub type CTFontPriority = u32;
pub const kCTFontPrioritySystem: CTFontPriority = 10000;
pub const kCTFontPriorityNetwork: CTFontPriority = 20000;
pub const kCTFontPriorityComputer: CTFontPriority = 30000;
pub const kCTFontPriorityUser: CTFontPriority = 40000;
pub const kCTFontPriorityDynamic: CTFontPriority = 50000;
pub const kCTFontPriorityProcess: CTFontPriority = 60000;

struct __CTFontDescriptor { private: () }
pub type CTFontDescriptorRef = *__CTFontDescriptor;

impl CTFontDescriptorRef : AbstractCFTypeRef {
    pure fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef }
}

struct CTFontDescriptor {
    obj: CTFontDescriptorRef,

    drop {
        unsafe {
            CFRelease(cast::transmute(self.obj))
        }
    }
}

pub impl CTFontDescriptor : AbstractCFType<CTFontDescriptorRef> {
    pure fn get_ref() -> CTFontDescriptorRef { self.obj }

    static fn wrap(obj: CTFontDescriptorRef) -> CTFontDescriptor {
        CTFontDescriptor { obj: obj }
    }

    static fn unwrap(wrapper: CTFontDescriptor) -> CTFontDescriptorRef {
        wrapper.obj
    }
}

pub impl CTFontDescriptor {
    fn family_name() -> ~str {
        let value = CTFontDescriptorCopyAttribute(self.obj, kCTFontDisplayNameAttribute);
        // family name should never be null.
        assert value.is_not_null();
        assert CFGetTypeID(value) == CFStringGetTypeID();

        let name : CFString = cf::base::wrap(value as CFStringRef);
        return name.to_str();
    }
}

extern {
    /*
     * CTFontTraits.h
     */

    // font trait constants
    const kCTFontSymbolicTrait: CFStringRef;
    const kCTFontWeightTrait: CFStringRef;
    const kCTFontWidthTrait: CFStringRef;
    const kCTFontSlantTrait: CFStringRef;

    /*
     * CTFontDescriptor.h
     */

    // font attribute constants
    const kCTFontURLAttribute: CFStringRef;
    const kCTFontNameAttribute: CFStringRef;
    const kCTFontDisplayNameAttribute: CFStringRef;
    const kCTFontFamilyNameAttribute: CFStringRef;
    const kCTFontStyleNameAttribute: CFStringRef;
    const kCTFontTraitsAttribute: CFStringRef;
    const kCTFontVariationAttribute: CFStringRef;
    const kCTFontSizeAttribute: CFStringRef;
    const kCTFontMatrixAttribute: CFStringRef;
    const kCTFontCascadeListAttribute: CFStringRef;
    const kCTFontCharacterSetAttribute: CFStringRef;
    const kCTFontLanguagesAttribute: CFStringRef;
    const kCTFontBaselineAdjustAttribute: CFStringRef;
    const kCTFontMacintoshEncodingsAttribute: CFStringRef;
    const kCTFontFeaturesAttribute: CFStringRef;
    const kCTFontFeatureSettingsAttribute: CFStringRef;
    const kCTFontFixedAdvanceAttribute: CFStringRef;
    const kCTFontOrientationAttribute: CFStringRef;
    const kCTFontFormatAttribute: CFStringRef;
    const kCTFontRegistrationScopeAttribute: CFStringRef;
    const kCTFontPriorityAttribute: CFStringRef;
    const kCTFontEnabledAttribute: CFStringRef;

    fn CTFontDescriptorCopyAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef) -> CFTypeRef;
    fn CTFontDescriptorCopyAttributes(descriptor: CTFontDescriptorRef) -> CFDictionaryRef;
    fn CTFontDescriptorCopyLocalizedAttribute(descriptor: CTFontDescriptorRef, attribute: CFStringRef, language: *CFStringRef) -> CFTypeRef;
    fn CTFontDescriptorCreateCopyWithAttributes(original: CTFontDescriptorRef, attributes: CFDictionaryRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateCopyWithFeature(original: CTFontDescriptorRef, featureTypeIdentifier: CFNumberRef, featureSelectorIdentifier: CFNumberRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateCopyWithVariation(original: CTFontDescriptorRef, variationIdentifier: CFNumberRef, variationValue: CGFloat) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateMatchingFontDescriptor(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateMatchingFontDescriptors(descriptor: CTFontDescriptorRef, mandatoryAttributes: CFSetRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateWithAttributes(attributes: CFDictionaryRef) -> CTFontDescriptorRef;
    fn CTFontDescriptorCreateWithNameAndSize(name: CFStringRef, size: CGFloat) -> CTFontDescriptorRef;
    fn CTFontDescriptorGetTypeID() -> CFTypeID;
}<|endoftext|>


<commit_before>extern crate queen_attack;

use queen_attack::*;

#[test]
fn chess_position_on_the_board_is_ok() {
    assert!(ChessPosition::new(2, 4).is_ok());
}

#[test]
#[ignore]
fn chess_position_off_the_board_is_err() {
    assert!(ChessPosition::new(-1, 2).is_err());
    assert!(ChessPosition::new(8, 2).is_err());
    assert!(ChessPosition::new(5, -1).is_err());
    assert!(ChessPosition::new(5, 8).is_err());
}

#[test]
#[ignore]
fn queen_is_created_with_a_ok_position() {
    Queen::new(ChessPosition::new(2, 4).unwrap());
}

#[test]
#[ignore]
#[should_panic(expected = "Invalid Position")]
fn queen_panics_with_err_position() {
    Queen::new(ChessPosition::new(-1, 4).unwrap());
}

#[test]
#[ignore]
fn queens_that_can_not_attack() {
    let white_queen = Queen::new(ChessPosition::new(2, 4).unwrap());
    let black_queen = Queen::new(ChessPosition::new(6, 6).unwrap());
    assert!(!white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_rank_can_attack() {
    let white_queen = Queen::new(ChessPosition::new(2, 4).unwrap());
    let black_queen = Queen::new(ChessPosition::new(2, 6).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_file_can_attack() {
    let white_queen = Queen::new(ChessPosition::new(4, 5).unwrap());
    let black_queen = Queen::new(ChessPosition::new(3, 5).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_one() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_two() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(3, 1).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_three() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(1, 1).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_four() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(5, 5).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}
<commit_msg>queen attack: Remove unnecessary test<commit_after>extern crate queen_attack;

use queen_attack::*;

#[test]
fn chess_position_on_the_board_is_ok() {
    assert!(ChessPosition::new(2, 4).is_ok());
}

#[test]
#[ignore]
fn chess_position_off_the_board_is_err() {
    assert!(ChessPosition::new(-1, 2).is_err());
    assert!(ChessPosition::new(8, 2).is_err());
    assert!(ChessPosition::new(5, -1).is_err());
    assert!(ChessPosition::new(5, 8).is_err());
}

#[test]
#[ignore]
fn queen_is_created_with_a_ok_position() {
    Queen::new(ChessPosition::new(2, 4).unwrap());
}

#[test]
#[ignore]
fn queens_that_can_not_attack() {
    let white_queen = Queen::new(ChessPosition::new(2, 4).unwrap());
    let black_queen = Queen::new(ChessPosition::new(6, 6).unwrap());
    assert!(!white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_rank_can_attack() {
    let white_queen = Queen::new(ChessPosition::new(2, 4).unwrap());
    let black_queen = Queen::new(ChessPosition::new(2, 6).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_file_can_attack() {
    let white_queen = Queen::new(ChessPosition::new(4, 5).unwrap());
    let black_queen = Queen::new(ChessPosition::new(3, 5).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_one() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_two() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(3, 1).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_three() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(1, 1).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}

#[test]
#[ignore]
fn queens_on_the_same_diagonal_can_attack_four() {
    let white_queen = Queen::new(ChessPosition::new(2, 2).unwrap());
    let black_queen = Queen::new(ChessPosition::new(5, 5).unwrap());
    assert!(white_queen.can_attack(&black_queen));
}
<|endoftext|>