<commit_before>//! Reject certain requests as instance load reaches capacity.
//!
//! The primary goal of this middleware is to avoid starving the download endpoint of resources.
//! When bots send many parallel requests that run slow database queries, download requests may
//! block and eventually timeout waiting for a database connection.
//!
//! Bots must continue to respect our crawler policy, but until we can manually block bad clients
//! we should avoid dropping download requests even if that means rejecting some legitimate
//! requests to other endpoints.

use std::env;
use std::sync::atomic::{AtomicUsize, Ordering};

use super::prelude::*;
use conduit::{RequestExt, StatusCode};

#[derive(Default)]
pub(super) struct BalanceCapacity {
    handler: Option<Box<dyn Handler>>,
    capacity: usize,
    in_flight_requests: AtomicUsize,
    report_only: bool,
    log_at_percentage: usize,
    throttle_at_percentage: usize,
    dl_only_at_percentage: usize,
}

impl BalanceCapacity {
    pub fn new(capacity: usize) -> Self {
        Self {
            handler: None,
            capacity,
            in_flight_requests: AtomicUsize::new(0),
            report_only: env::var("WEB_CAPACITY_REPORT_ONLY").ok().is_some(),
            log_at_percentage: read_env_percentage("WEB_CAPACITY_LOG_PCT", 50),
            throttle_at_percentage: read_env_percentage("WEB_CAPACITY_THROTTLE_PCT", 70),
            dl_only_at_percentage: read_env_percentage("WEB_CAPACITY_DL_ONLY_PCT", 80),
        }
    }

    /// Handle a request normally
    fn handle(&self, request: &mut dyn RequestExt) -> AfterResult {
        self.handler.as_ref().unwrap().call(request)
    }

    /// Handle a request when load exceeds a threshold
    ///
    /// In report-only mode, log metadata is added but the request is still served. Otherwise,
    /// the request is rejected with a service unavailable response.
    fn handle_high_load(&self, request: &mut dyn RequestExt, note: &str) -> AfterResult {
        if self.report_only {
            // In report-only mode we serve all requests but add log metadata
            super::log_request::add_custom_metadata(request, "would_reject", note);
            self.handle(request)
        } else {
            // Reject the request
            super::log_request::add_custom_metadata(request, "cause", note);
            let body = "Service temporarily unavailable";
            Response::builder()
                .status(StatusCode::SERVICE_UNAVAILABLE)
                .header(header::CONTENT_LENGTH, body.len())
                .body(Body::from_static(body.as_bytes()))
                .map_err(box_error)
        }
    }
}

impl AroundMiddleware for BalanceCapacity {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for BalanceCapacity {
    fn call(&self, request: &mut dyn RequestExt) -> AfterResult {
        // The _drop_on_exit ensures the counter is decremented for all exit paths (including panics)
        let (_drop_on_exit, count) = RequestCounter::add_one(&self.in_flight_requests);
        let load = 100 * count / self.capacity;

        // Begin logging request count so early stages of load increase can be located
        if load >= self.log_at_percentage {
            super::log_request::add_custom_metadata(request, "in_flight_requests", count);
        }

        // Download requests are always accepted
        if request.path().starts_with("/api/v1/crates/") && request.path().ends_with("/download") {
            return self.handle(request);
        }

        // Reject read-only requests as load nears capacity. Bots are likely to send only safe
        // requests and this helps prioritize requests that users may be reluctant to retry.
        if load >= self.throttle_at_percentage && request.method().is_safe() {
            return self.handle_high_load(request, "over capacity (throttle)");
        }

        // As load reaches capacity, all non-download requests are rejected
        if load >= self.dl_only_at_percentage {
            return self.handle_high_load(request, "over capacity (download only)");
        }

        self.handle(request)
    }
}

fn read_env_percentage(name: &str, default: usize) -> usize {
    if let Ok(value) = env::var(name) {
        value.parse().unwrap_or(default)
    } else {
        default
    }
}

// FIXME(JTG): I've copied the following from my `conduit-hyper` crate.  Once we transition from
// `civet`, we could pass the in_flight_request count from `condut-hyper` via a request extension.

/// A struct that stores a reference to an atomic counter so it can be decremented when dropped
struct RequestCounter<'a> {
    counter: &'a AtomicUsize,
}

impl<'a> RequestCounter<'a> {
    fn add_one(counter: &'a AtomicUsize) -> (Self, usize) {
        let previous = counter.fetch_add(1, Ordering::SeqCst);
        (Self { counter }, previous + 1)
    }
}

impl<'a> Drop for RequestCounter<'a> {
    fn drop(&mut self) {
        self.counter.fetch_sub(1, Ordering::SeqCst);
    }
}
<commit_msg>Do not count downloads as in-flight<commit_after>//! Reject certain requests as instance load reaches capacity.
//!
//! The primary goal of this middleware is to avoid starving the download endpoint of resources.
//! When bots send many parallel requests that run slow database queries, download requests may
//! block and eventually timeout waiting for a database connection.
//!
//! Bots must continue to respect our crawler policy, but until we can manually block bad clients
//! we should avoid dropping download requests even if that means rejecting some legitimate
//! requests to other endpoints.

use std::env;
use std::sync::atomic::{AtomicUsize, Ordering};

use super::prelude::*;
use conduit::{RequestExt, StatusCode};

#[derive(Default)]
pub(super) struct BalanceCapacity {
    handler: Option<Box<dyn Handler>>,
    capacity: usize,
    in_flight_non_dl_requests: AtomicUsize,
    report_only: bool,
    log_at_percentage: usize,
    throttle_at_percentage: usize,
    dl_only_at_percentage: usize,
}

impl BalanceCapacity {
    pub fn new(capacity: usize) -> Self {
        Self {
            handler: None,
            capacity,
            in_flight_non_dl_requests: AtomicUsize::new(0),
            report_only: env::var("WEB_CAPACITY_REPORT_ONLY").ok().is_some(),
            log_at_percentage: read_env_percentage("WEB_CAPACITY_LOG_PCT", 50),
            throttle_at_percentage: read_env_percentage("WEB_CAPACITY_THROTTLE_PCT", 70),
            dl_only_at_percentage: read_env_percentage("WEB_CAPACITY_DL_ONLY_PCT", 80),
        }
    }

    /// Handle a request normally
    fn handle(&self, request: &mut dyn RequestExt) -> AfterResult {
        self.handler.as_ref().unwrap().call(request)
    }

    /// Handle a request when load exceeds a threshold
    ///
    /// In report-only mode, log metadata is added but the request is still served. Otherwise,
    /// the request is rejected with a service unavailable response.
    fn handle_high_load(&self, request: &mut dyn RequestExt, note: &str) -> AfterResult {
        if self.report_only {
            // In report-only mode we serve all requests but add log metadata
            super::log_request::add_custom_metadata(request, "would_reject", note);
            self.handle(request)
        } else {
            // Reject the request
            super::log_request::add_custom_metadata(request, "cause", note);
            let body = "Service temporarily unavailable";
            Response::builder()
                .status(StatusCode::SERVICE_UNAVAILABLE)
                .header(header::CONTENT_LENGTH, body.len())
                .body(Body::from_static(body.as_bytes()))
                .map_err(box_error)
        }
    }
}

impl AroundMiddleware for BalanceCapacity {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for BalanceCapacity {
    fn call(&self, request: &mut dyn RequestExt) -> AfterResult {
        // Download requests are always accepted and do not affect the request count
        if request.path().starts_with("/api/v1/crates/") && request.path().ends_with("/download") {
            return self.handle(request);
        }

        // The _drop_on_exit ensures the counter is decremented for all exit paths (including panics)
        let (_drop_on_exit, count) = RequestCounter::add_one(&self.in_flight_non_dl_requests);
        let load = 100 * count / self.capacity;

        // Begin logging request count so early stages of load increase can be located
        if load >= self.log_at_percentage {
            super::log_request::add_custom_metadata(request, "in_flight_non_dl_requests", count);
        }

        // Reject read-only requests as load nears capacity. Bots are likely to send only safe
        // requests and this helps prioritize requests that users may be reluctant to retry.
        if load >= self.throttle_at_percentage && request.method().is_safe() {
            return self.handle_high_load(request, "over capacity (throttle)");
        }

        // As load reaches capacity, all non-download requests are rejected
        if load >= self.dl_only_at_percentage {
            return self.handle_high_load(request, "over capacity (download only)");
        }

        self.handle(request)
    }
}

fn read_env_percentage(name: &str, default: usize) -> usize {
    if let Ok(value) = env::var(name) {
        value.parse().unwrap_or(default)
    } else {
        default
    }
}

/// A struct that stores a reference to an atomic counter so it can be decremented when dropped
struct RequestCounter<'a> {
    counter: &'a AtomicUsize,
}

impl<'a> RequestCounter<'a> {
    fn add_one(counter: &'a AtomicUsize) -> (Self, usize) {
        let previous = counter.fetch_add(1, Ordering::SeqCst);
        (Self { counter }, previous + 1)
    }
}

impl<'a> Drop for RequestCounter<'a> {
    fn drop(&mut self) {
        self.counter.fetch_sub(1, Ordering::SeqCst);
    }
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::env::temp_dir;
use std::path::{Path, PathBuf};

use diesel::{Connection, RunQueryDsl, SqliteConnection};
use juniper::FieldResult;
use structopt::StructOpt;

use auth::JwtData;
use contest::UserToken;
use formats::ImportFileInput;
use problem::ProblemName;
use schema::blobs;
use user::UserId;
use user::UserInput;

use crate::api::contest::{Contest, ContestInput, ContestUpdateInput};
use crate::api::contest_evaluation::Evaluation;
use crate::api::contest_problem::{Problem, ProblemInput, ProblemInsertable, ProblemUpdateInput};
use crate::api::formats::Import;
use crate::api::user::{User, UserUpdateInput};

use super::*;
use crate::api::messages::{Message, MessageInput, MessageKind};

embed_migrations!();

pub struct MutationOk;

#[juniper::object]
impl MutationOk {
    fn ok() -> bool {
        true
    }
}

pub type RootNode<'a> = juniper::RootNode<'static, Query, Mutation>;

#[derive(StructOpt, Clone, Debug)]
pub struct ContestArgs {
    /// url of the database
    #[structopt(long, env = "DATABASE", default_value = "./database.sqlite3")]
    pub database_url: PathBuf,
}

#[derive(Debug, Clone)]
pub struct ApiConfig {
    /// Skip all authentication
    skip_auth: bool,

    /// Secret code to use for authenticating a JWT token.
    pub secret: Option<Vec<u8>>,

    /// Path of the database on the filesystem
    pub database_url: PathBuf,
}

pub struct ApiContext {
    pub config: ApiConfig,
    /// JWT data of the token submitted to the server (if any)
    pub jwt_data: Option<JwtData>,
    pub database: SqliteConnection,
    pub workspace_path: PathBuf,
}

impl juniper::Context for ApiContext {}

impl Default for ApiConfig {
    fn default() -> ApiConfig {
        ApiConfig {
            skip_auth: false,
            secret: None,
            database_url: PathBuf::default(),
        }
    }
}

impl ApiConfig {
    pub fn create_context(&self, jwt_data: Option<JwtData>) -> ApiContext {
        // FIXME: should not create directory here
        let workspace_path = temp_dir().join("turingarena");
        std::fs::create_dir_all(&workspace_path).expect("Unable to create workspace dir");

        ApiContext {
            config: self.clone(),
            database: self.connect_db(),
            jwt_data,
            workspace_path,
        }
    }

    fn connect_db(&self) -> SqliteConnection {
        let conn = SqliteConnection::establish(self.database_url.to_str().unwrap())
            .expect("Unable to establish connection");
        conn.execute("PRAGMA busy_timeout = 5000;")
            .expect("Unable to set `busy_timeout`");
        conn
    }

    pub fn with_args(self, args: ContestArgs) -> ApiConfig {
        self.with_database_url(args.database_url)
    }

    /// Set the database URL
    pub fn with_database_url(self, database_url: PathBuf) -> ApiConfig {
        ApiConfig {
            database_url,
            ..self
        }
    }

    /// Sets a secret
    pub fn with_secret(self, secret: Option<Vec<u8>>) -> ApiConfig {
        ApiConfig { secret, ..self }
    }

    /// Sets if to skip authentication
    pub fn with_skip_auth(self, skip_auth: bool) -> ApiConfig {
        ApiConfig { skip_auth, ..self }
    }
}

impl ApiContext {
    pub fn root_node(&self) -> RootNode {
        RootNode::new(Query, Mutation)
    }

    pub fn workspace_path(&self) -> &Path {
        &self.workspace_path
    }

    pub fn create_blob(&self, content: &[u8]) -> FieldResult<String> {
        use diesel::ExpressionMethods;
        let integrity = archive::compute_integrity(content);
        diesel::insert_into(blobs::table)
            .values((
                blobs::dsl::integrity.eq(&integrity),
                blobs::dsl::content.eq(content),
            ))
            .execute(&self.database)?;
        Ok(integrity)
    }

    pub fn unpack_archive(&self, integrity: &str, prefix: &str) -> FieldResult<PathBuf> {
        use diesel::QueryDsl;
        let workspace_path = &self.workspace_path().to_owned();

        archive::unpack_archive(workspace_path, prefix, integrity, || {
            Ok(blobs::table
                .find(integrity)
                .select(blobs::content)
                .first::<Vec<u8>>(&self.database)?)
        })
    }

    pub fn default_contest(&self) -> FieldResult<Contest> {
        Contest::current(&self)
    }

    /// Authorize admin operations
    #[must_use = "Error means forbidden"]
    pub fn authorize_admin(&self) -> juniper::FieldResult<()> {
        if self.config.skip_auth {
            return Ok(());
        }

        if let Some(data) = &self.jwt_data {
            if User::by_id(self, UserId(data.user.clone()))?.is_admin() {
                return Ok(());
            }
        }

        return Err(juniper::FieldError::from("Forbidden"));
    }

    /// Authenticate user
    #[must_use = "Error means forbidden"]
    pub fn authorize_user(&self, user_id: &Option<UserId>) -> juniper::FieldResult<()> {
        if self.config.skip_auth {
            return Ok(());
        }

        if let Some(id) = user_id {
            if self.config.secret != None {
                if let Some(data) = &self.jwt_data {
                    if data.user != id.0 {
                        return Err(juniper::FieldError::from("Forbidden for the given user id"));
                    }
                } else {
                    return Err(juniper::FieldError::from("Authentication required"));
                }
            }
        }
        Ok(())
    }
}

pub struct Query;

#[juniper_ext::graphql(Context = ApiContext)]
impl Query {
    pub fn contest(context: &ApiContext) -> FieldResult<Contest> {
        Contest::current(context)
    }

    pub fn user(context: &ApiContext, user_id: Option<UserId>) -> FieldResult<Option<User>> {
        Ok(if let Some(user_id) = user_id {
            Some(User::by_id(context, user_id.clone())?)
        } else {
            None
        })
    }

    /// Get the submission with the specified id
    pub fn submission(
        context: &ApiContext,
        submission_id: String,
    ) -> FieldResult<contest_submission::Submission> {
        let submission = contest_submission::Submission::by_id(context, &submission_id)?;
        context.authorize_user(&Some(submission.user_id()))?;
        Ok(submission)
    }

    /// Current time on the server as RFC3339 date
    pub fn server_time() -> String {
        chrono::Local::now().to_rfc3339()
    }
}

pub struct Mutation;

#[juniper_ext::graphql(Context = ApiContext)]
impl Mutation {
    /// Reset database
    fn init_db(context: &ApiContext) -> FieldResult<MutationOk> {
        context.authorize_admin()?;

        embedded_migrations::run_with_output(&context.database, &mut std::io::stdout())?;

        Contest::init(context)?;

        Ok(MutationOk)
    }

    /// Initializes a new contest
    fn init_contest(context: &ApiContext, contest: ContestInput) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Contest::insert(context, contest)?;
        Ok(MutationOk)
    }

    /// Authenticate a user, generating a JWT authentication token
    fn auth(context: &ApiContext, token: String) -> FieldResult<Option<UserToken>> {
        Ok(auth::auth(context, &token)?)
    }

    /// Current time on the server as RFC3339 date
    fn server_time() -> String {
        chrono::Local::now().to_rfc3339()
    }

    /// Add a user to the current contest
    pub fn update_contest(
        context: &ApiContext,
        input: ContestUpdateInput,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        context.default_contest()?.update(context, input)?;

        Ok(MutationOk)
    }

    /// Add a user to the current contest
    pub fn add_users(context: &ApiContext, inputs: Vec<UserInput>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        User::insert(context, inputs)?;
        Ok(MutationOk)
    }

    pub fn update_users(
        context: &ApiContext,
        inputs: Vec<UserUpdateInput>,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        User::update(context, inputs)?;
        Ok(MutationOk)
    }

    /// Delete a user from the current contest
    pub fn delete_users(context: &ApiContext, ids: Vec<String>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        User::delete(&context, ids)?;
        Ok(MutationOk)
    }

    /// Add problems to the current contest
    pub fn add_problems(
        context: &ApiContext,
        inputs: Vec<ProblemInput>,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Problem::insert(context, inputs);
        Ok(MutationOk)
    }

    /// Update problems in the current contest
    pub fn update_problems(
        context: &ApiContext,
        inputs: Vec<ProblemUpdateInput>,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Problem::update(&context, inputs)?;
        Ok(MutationOk)
    }

    /// Delete problems from the current contest
    pub fn delete_problems(context: &ApiContext, names: Vec<String>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Problem::delete(&context, names)?;
        Ok(MutationOk)
    }

        /// Import a file
        pub fn import(
            context: &ApiContext,
            inputs: Vec<ImportFileInput>,
            dry_run: Option<bool>,
        ) -> FieldResult<Import> {
            context.authorize_admin()?;
            let import = Import::load(inputs)?;
            if dry_run.is_some() && dry_run.unwrap() {
                // no-op
            } else {
                import.apply(&context)?;
            }
            Ok(import)
        }

    /// Submit a solution to the problem
    fn submit(
        context: &ApiContext,
        user_id: UserId,
        problem_name: ProblemName,
        files: Vec<contest_submission::FileInput>,
    ) -> FieldResult<contest_submission::Submission> {
        Ok(Problem::by_name(context, &problem_name.0)?
            .view(context, Some(user_id))?
            .tackling()
            .ok_or("Cannot submit now")?
            .submit(context, files)?)
    }

    fn evaluate(context: &ApiContext, submission_ids: Vec<String>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        for id in submission_ids {
            let submission = contest_submission::Submission::by_id(&context, &id)?;
            Evaluation::start_new(&submission, context)?;
        }
        Ok(MutationOk)
    }

    fn add_messages(context: &ApiContext, inputs: Vec<MessageInput>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Message::send(context, inputs)?;
        Ok(MutationOk)
    }

    fn send_message(
        context: &ApiContext,
        user_id: UserId,
        problem_name: Option<String>,
        text: String,
    ) -> FieldResult<MutationOk> {
        context.authorize_user(&Some(user_id.clone()))?;
        Message::send(
            context,
            vec![MessageInput {
                user_id: Some(user_id.0.clone()),
                kind: MessageKind::FromUser,
                problem_name,
                text,
            }],
        )?;
        Ok(MutationOk)
    }
}
<commit_msg>Format code<commit_after>use std::default::Default;
use std::env::temp_dir;
use std::path::{Path, PathBuf};

use diesel::{Connection, RunQueryDsl, SqliteConnection};
use juniper::FieldResult;
use structopt::StructOpt;

use auth::JwtData;
use contest::UserToken;
use formats::ImportFileInput;
use problem::ProblemName;
use schema::blobs;
use user::UserId;
use user::UserInput;

use crate::api::contest::{Contest, ContestInput, ContestUpdateInput};
use crate::api::contest_evaluation::Evaluation;
use crate::api::contest_problem::{Problem, ProblemInput, ProblemInsertable, ProblemUpdateInput};
use crate::api::formats::Import;
use crate::api::user::{User, UserUpdateInput};

use super::*;
use crate::api::messages::{Message, MessageInput, MessageKind};

embed_migrations!();

pub struct MutationOk;

#[juniper::object]
impl MutationOk {
    fn ok() -> bool {
        true
    }
}

pub type RootNode<'a> = juniper::RootNode<'static, Query, Mutation>;

#[derive(StructOpt, Clone, Debug)]
pub struct ContestArgs {
    /// url of the database
    #[structopt(long, env = "DATABASE", default_value = "./database.sqlite3")]
    pub database_url: PathBuf,
}

#[derive(Debug, Clone)]
pub struct ApiConfig {
    /// Skip all authentication
    skip_auth: bool,

    /// Secret code to use for authenticating a JWT token.
    pub secret: Option<Vec<u8>>,

    /// Path of the database on the filesystem
    pub database_url: PathBuf,
}

pub struct ApiContext {
    pub config: ApiConfig,
    /// JWT data of the token submitted to the server (if any)
    pub jwt_data: Option<JwtData>,
    pub database: SqliteConnection,
    pub workspace_path: PathBuf,
}

impl juniper::Context for ApiContext {}

impl Default for ApiConfig {
    fn default() -> ApiConfig {
        ApiConfig {
            skip_auth: false,
            secret: None,
            database_url: PathBuf::default(),
        }
    }
}

impl ApiConfig {
    pub fn create_context(&self, jwt_data: Option<JwtData>) -> ApiContext {
        // FIXME: should not create directory here
        let workspace_path = temp_dir().join("turingarena");
        std::fs::create_dir_all(&workspace_path).expect("Unable to create workspace dir");

        ApiContext {
            config: self.clone(),
            database: self.connect_db(),
            jwt_data,
            workspace_path,
        }
    }

    fn connect_db(&self) -> SqliteConnection {
        let conn = SqliteConnection::establish(self.database_url.to_str().unwrap())
            .expect("Unable to establish connection");
        conn.execute("PRAGMA busy_timeout = 5000;")
            .expect("Unable to set `busy_timeout`");
        conn
    }

    pub fn with_args(self, args: ContestArgs) -> ApiConfig {
        self.with_database_url(args.database_url)
    }

    /// Set the database URL
    pub fn with_database_url(self, database_url: PathBuf) -> ApiConfig {
        ApiConfig {
            database_url,
            ..self
        }
    }

    /// Sets a secret
    pub fn with_secret(self, secret: Option<Vec<u8>>) -> ApiConfig {
        ApiConfig { secret, ..self }
    }

    /// Sets if to skip authentication
    pub fn with_skip_auth(self, skip_auth: bool) -> ApiConfig {
        ApiConfig { skip_auth, ..self }
    }
}

impl ApiContext {
    pub fn root_node(&self) -> RootNode {
        RootNode::new(Query, Mutation)
    }

    pub fn workspace_path(&self) -> &Path {
        &self.workspace_path
    }

    pub fn create_blob(&self, content: &[u8]) -> FieldResult<String> {
        use diesel::ExpressionMethods;
        let integrity = archive::compute_integrity(content);
        diesel::insert_into(blobs::table)
            .values((
                blobs::dsl::integrity.eq(&integrity),
                blobs::dsl::content.eq(content),
            ))
            .execute(&self.database)?;
        Ok(integrity)
    }

    pub fn unpack_archive(&self, integrity: &str, prefix: &str) -> FieldResult<PathBuf> {
        use diesel::QueryDsl;
        let workspace_path = &self.workspace_path().to_owned();

        archive::unpack_archive(workspace_path, prefix, integrity, || {
            Ok(blobs::table
                .find(integrity)
                .select(blobs::content)
                .first::<Vec<u8>>(&self.database)?)
        })
    }

    pub fn default_contest(&self) -> FieldResult<Contest> {
        Contest::current(&self)
    }

    /// Authorize admin operations
    #[must_use = "Error means forbidden"]
    pub fn authorize_admin(&self) -> juniper::FieldResult<()> {
        if self.config.skip_auth {
            return Ok(());
        }

        if let Some(data) = &self.jwt_data {
            if User::by_id(self, UserId(data.user.clone()))?.is_admin() {
                return Ok(());
            }
        }

        return Err(juniper::FieldError::from("Forbidden"));
    }

    /// Authenticate user
    #[must_use = "Error means forbidden"]
    pub fn authorize_user(&self, user_id: &Option<UserId>) -> juniper::FieldResult<()> {
        if self.config.skip_auth {
            return Ok(());
        }

        if let Some(id) = user_id {
            if self.config.secret != None {
                if let Some(data) = &self.jwt_data {
                    if data.user != id.0 {
                        return Err(juniper::FieldError::from("Forbidden for the given user id"));
                    }
                } else {
                    return Err(juniper::FieldError::from("Authentication required"));
                }
            }
        }
        Ok(())
    }
}

pub struct Query;

#[juniper_ext::graphql(Context = ApiContext)]
impl Query {
    pub fn contest(context: &ApiContext) -> FieldResult<Contest> {
        Contest::current(context)
    }

    pub fn user(context: &ApiContext, user_id: Option<UserId>) -> FieldResult<Option<User>> {
        Ok(if let Some(user_id) = user_id {
            Some(User::by_id(context, user_id.clone())?)
        } else {
            None
        })
    }

    /// Get the submission with the specified id
    pub fn submission(
        context: &ApiContext,
        submission_id: String,
    ) -> FieldResult<contest_submission::Submission> {
        let submission = contest_submission::Submission::by_id(context, &submission_id)?;
        context.authorize_user(&Some(submission.user_id()))?;
        Ok(submission)
    }

    /// Current time on the server as RFC3339 date
    pub fn server_time() -> String {
        chrono::Local::now().to_rfc3339()
    }
}

pub struct Mutation;

#[juniper_ext::graphql(Context = ApiContext)]
impl Mutation {
    /// Reset database
    fn init_db(context: &ApiContext) -> FieldResult<MutationOk> {
        context.authorize_admin()?;

        embedded_migrations::run_with_output(&context.database, &mut std::io::stdout())?;

        Contest::init(context)?;

        Ok(MutationOk)
    }

    /// Initializes a new contest
    fn init_contest(context: &ApiContext, contest: ContestInput) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Contest::insert(context, contest)?;
        Ok(MutationOk)
    }

    /// Authenticate a user, generating a JWT authentication token
    fn auth(context: &ApiContext, token: String) -> FieldResult<Option<UserToken>> {
        Ok(auth::auth(context, &token)?)
    }

    /// Current time on the server as RFC3339 date
    fn server_time() -> String {
        chrono::Local::now().to_rfc3339()
    }

    /// Add a user to the current contest
    pub fn update_contest(
        context: &ApiContext,
        input: ContestUpdateInput,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        context.default_contest()?.update(context, input)?;

        Ok(MutationOk)
    }

    /// Add a user to the current contest
    pub fn add_users(context: &ApiContext, inputs: Vec<UserInput>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        User::insert(context, inputs)?;
        Ok(MutationOk)
    }

    pub fn update_users(
        context: &ApiContext,
        inputs: Vec<UserUpdateInput>,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        User::update(context, inputs)?;
        Ok(MutationOk)
    }

    /// Delete a user from the current contest
    pub fn delete_users(context: &ApiContext, ids: Vec<String>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        User::delete(&context, ids)?;
        Ok(MutationOk)
    }

    /// Add problems to the current contest
    pub fn add_problems(
        context: &ApiContext,
        inputs: Vec<ProblemInput>,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Problem::insert(context, inputs);
        Ok(MutationOk)
    }

    /// Update problems in the current contest
    pub fn update_problems(
        context: &ApiContext,
        inputs: Vec<ProblemUpdateInput>,
    ) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Problem::update(&context, inputs)?;
        Ok(MutationOk)
    }

    /// Delete problems from the current contest
    pub fn delete_problems(context: &ApiContext, names: Vec<String>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Problem::delete(&context, names)?;
        Ok(MutationOk)
    }

    /// Import a file
    pub fn import(
        context: &ApiContext,
        inputs: Vec<ImportFileInput>,
        dry_run: Option<bool>,
    ) -> FieldResult<Import> {
        context.authorize_admin()?;
        let import = Import::load(inputs)?;
        if dry_run.is_some() && dry_run.unwrap() {
            // no-op
        } else {
            import.apply(&context)?;
        }
        Ok(import)
    }

    /// Submit a solution to the problem
    fn submit(
        context: &ApiContext,
        user_id: UserId,
        problem_name: ProblemName,
        files: Vec<contest_submission::FileInput>,
    ) -> FieldResult<contest_submission::Submission> {
        Ok(Problem::by_name(context, &problem_name.0)?
            .view(context, Some(user_id))?
            .tackling()
            .ok_or("Cannot submit now")?
            .submit(context, files)?)
    }

    fn evaluate(context: &ApiContext, submission_ids: Vec<String>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        for id in submission_ids {
            let submission = contest_submission::Submission::by_id(&context, &id)?;
            Evaluation::start_new(&submission, context)?;
        }
        Ok(MutationOk)
    }

    fn add_messages(context: &ApiContext, inputs: Vec<MessageInput>) -> FieldResult<MutationOk> {
        context.authorize_admin()?;
        Message::send(context, inputs)?;
        Ok(MutationOk)
    }

    fn send_message(
        context: &ApiContext,
        user_id: UserId,
        problem_name: Option<String>,
        text: String,
    ) -> FieldResult<MutationOk> {
        context.authorize_user(&Some(user_id.clone()))?;
        Message::send(
            context,
            vec![MessageInput {
                user_id: Some(user_id.0.clone()),
                kind: MessageKind::FromUser,
                problem_name,
                text,
            }],
        )?;
        Ok(MutationOk)
    }
}
<|endoftext|>


<commit_before>extern crate polydraw;

use polydraw::Application;
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::data::IntPoint;
use polydraw::draw::RGB;

fn letter_poly() -> Poly {
   let data = [vec![
      (409, 596),
      (529, 232),
      (566, 222),
      (603, 214),
      (640, 208),
      (658, 207),
      (675, 206),
      (710, 208),
      (743, 213),
      (775, 220),
      (806, 231),
      (835, 245),
      (862, 262),
      (887, 282),
      (910, 304),
      (931, 330),
      (950, 358),
      (966, 389),
      (980, 423),
      (991, 460),
      (999, 499),
      (1003, 541),
      (1005, 585),
      (1005, 791),
      (836, 791),
      (791, 792),
      (747, 794),
      (703, 797),
      (660, 801),
      (619, 807),
      (578, 813),
      (538, 821),
      (500, 830),
      (463, 840),
      (426, 852),
      (391, 864),
      (357, 877),
      (325, 892),
      (294, 907),
      (264, 923),
      (235, 941),
      (208, 959),
      (183, 978),
      (159, 999),
      (136, 1020),
      (115, 1042),
      (96, 1064),
      (78, 1088),
      (62, 1112),
      (48, 1138),
      (35, 1164),
      (25, 1190),
      (16, 1218),
      (9, 1246),
      (4, 1275),
      (1, 1305),
      (0, 1335),
      (1, 1361),
      (2, 1387),
      (5, 1412),
      (9, 1436),
      (15, 1459),
      (21, 1481),
      (28, 1502),
      (36, 1523),
      (45, 1543),
      (56, 1562),
      (67, 1580),
      (79, 1598),
      (92, 1614),
      (105, 1630),
      (120, 1645),
      (135, 1659),
      (151, 1673),
      (168, 1685),
      (185, 1697),
      (203, 1708),
      (222, 1717),
      (241, 1727),
      (261, 1735),
      (282, 1742),
      (303, 1749),
      (324, 1754),
      (346, 1759),
      (368, 1763),
      (391, 1766),
      (414, 1768),
      (461, 1770),
      (507, 1768),
      (551, 1764),
      (594, 1756),
      (637, 1746),
      (677, 1734),
      (717, 1720),
      (755, 1704),
      (792, 1686),
      (827, 1667),
      (860, 1648),
      (891, 1628),
      (920, 1607),
      (946, 1586),
      (971, 1566),
      (993, 1546),
      (1012, 1526),
      (1084, 1740),
      (1691, 1740),
      (1691, 1579),
      (1455, 1470),
      (1455, 540),
      (1454, 506),
      (1452, 473),
      (1448, 441),
      (1443, 410),
      (1437, 381),
      (1429, 352),
      (1420, 325),
      (1409, 299),
      (1397, 274),
      (1384, 250),
      (1370, 228),
      (1354, 206),
      (1337, 186),
      (1319, 166),
      (1300, 148),
      (1280, 131),
      (1258, 115),
      (1236, 100),
      (1212, 86),
      (1187, 73),
      (1162, 61),
      (1135, 50),
      (1107, 41),
      (1078, 32),
      (1049, 25),
      (1018, 18),
      (987, 12),
      (955, 8),
      (922, 4),
      (888, 2),
      (853, 0),
      (818, 0),
      (774, 1),
      (728, 3),
      (682, 7),
      (634, 12),
      (586, 18),
      (537, 25),
      (489, 34),
      (441, 43),
      (393, 53),
      (347, 64),
      (302, 76),
      (259, 89),
      (217, 101),
      (178, 115),
      (142, 129),
      (109, 142),
      (109, 596),
   ],
   vec![
      (1001, 1418),
      (952, 1435),
      (926, 1443),
      (899, 1450),
      (870, 1457),
      (840, 1462),
      (809, 1465),
      (776, 1466),
      (746, 1465),
      (716, 1463),
      (688, 1458),
      (660, 1452),
      (634, 1444),
      (610, 1434),
      (587, 1423),
      (566, 1409),
      (547, 1394),
      (530, 1377),
      (515, 1357),
      (503, 1337),
      (493, 1314),
      (486, 1289),
      (482, 1262),
      (480, 1234),
      (480, 1218),
      (482, 1202),
      (484, 1187),
      (487, 1173),
      (491, 1159),
      (496, 1146),
      (501, 1134),
      (507, 1122),
      (514, 1111),
      (522, 1101),
      (530, 1091),
      (540, 1082),
      (560, 1064),
      (583, 1050),
      (608, 1037),
      (635, 1026),
      (665, 1017),
      (697, 1010),
      (730, 1004),
      (765, 1000),
      (802, 998),
      (840, 998),
      (1005, 998),
   ]];

   let mut contours = Vec::new();

   for contour_data in &data[1..] {
      contours.push(
         points_from_coords(contour_data)
      );
   }

   let poly = Poly::new(
      contours, RGB::new(255, 255, 255),
   );

   poly
}

fn points_from_coords(coords: &[(i64, i64)]) -> Vec<IntPoint> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(IntPoint::new(x + 120, y + 120))
   }

   points
}

fn main() {
   let mut scene = Scene::new();

   scene.push(Box::new(letter_poly()));

   let mut renderer = DevelRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Letter")
      .size(1200, 800)
      .run();
}
<commit_msg>Fixing the letter example<commit_after>extern crate polydraw;

use polydraw::Application;
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::data::IntPoint;
use polydraw::draw::RGB;

fn letter_poly() -> Poly {
   let data = [vec![
      (409, 596),
      (529, 232),
      (566, 222),
      (603, 214),
      (640, 208),
      (658, 207),
      (675, 206),
      (710, 208),
      (743, 213),
      (775, 220),
      (806, 231),
      (835, 245),
      (862, 262),
      (887, 282),
      (910, 304),
      (931, 330),
      (950, 358),
      (966, 389),
      (980, 423),
      (991, 460),
      (999, 499),
      (1003, 541),
      (1005, 585),
      (1005, 791),
      (836, 791),
      (791, 792),
      (747, 794),
      (703, 797),
      (660, 801),
      (619, 807),
      (578, 813),
      (538, 821),
      (500, 830),
      (463, 840),
      (426, 852),
      (391, 864),
      (357, 877),
      (325, 892),
      (294, 907),
      (264, 923),
      (235, 941),
      (208, 959),
      (183, 978),
      (159, 999),
      (136, 1020),
      (115, 1042),
      (96, 1064),
      (78, 1088),
      (62, 1112),
      (48, 1138),
      (35, 1164),
      (25, 1190),
      (16, 1218),
      (9, 1246),
      (4, 1275),
      (1, 1305),
      (0, 1335),
      (1, 1361),
      (2, 1387),
      (5, 1412),
      (9, 1436),
      (15, 1459),
      (21, 1481),
      (28, 1502),
      (36, 1523),
      (45, 1543),
      (56, 1562),
      (67, 1580),
      (79, 1598),
      (92, 1614),
      (105, 1630),
      (120, 1645),
      (135, 1659),
      (151, 1673),
      (168, 1685),
      (185, 1697),
      (203, 1708),
      (222, 1717),
      (241, 1727),
      (261, 1735),
      (282, 1742),
      (303, 1749),
      (324, 1754),
      (346, 1759),
      (368, 1763),
      (391, 1766),
      (414, 1768),
      (461, 1770),
      (507, 1768),
      (551, 1764),
      (594, 1756),
      (637, 1746),
      (677, 1734),
      (717, 1720),
      (755, 1704),
      (792, 1686),
      (827, 1667),
      (860, 1648),
      (891, 1628),
      (920, 1607),
      (946, 1586),
      (971, 1566),
      (993, 1546),
      (1012, 1526),
      (1084, 1740),
      (1691, 1740),
      (1691, 1579),
      (1455, 1470),
      (1455, 540),
      (1454, 506),
      (1452, 473),
      (1448, 441),
      (1443, 410),
      (1437, 381),
      (1429, 352),
      (1420, 325),
      (1409, 299),
      (1397, 274),
      (1384, 250),
      (1370, 228),
      (1354, 206),
      (1337, 186),
      (1319, 166),
      (1300, 148),
      (1280, 131),
      (1258, 115),
      (1236, 100),
      (1212, 86),
      (1187, 73),
      (1162, 61),
      (1135, 50),
      (1107, 41),
      (1078, 32),
      (1049, 25),
      (1018, 18),
      (987, 12),
      (955, 8),
      (922, 4),
      (888, 2),
      (853, 0),
      (818, 0),
      (774, 1),
      (728, 3),
      (682, 7),
      (634, 12),
      (586, 18),
      (537, 25),
      (489, 34),
      (441, 43),
      (393, 53),
      (347, 64),
      (302, 76),
      (259, 89),
      (217, 101),
      (178, 115),
      (142, 129),
      (109, 142),
      (109, 596),
   ],
   vec![
      (1001, 1418),
      (952, 1435),
      (926, 1443),
      (899, 1450),
      (870, 1457),
      (840, 1462),
      (809, 1465),
      (776, 1466),
      (746, 1465),
      (716, 1463),
      (688, 1458),
      (660, 1452),
      (634, 1444),
      (610, 1434),
      (587, 1423),
      (566, 1409),
      (547, 1394),
      (530, 1377),
      (515, 1357),
      (503, 1337),
      (493, 1314),
      (486, 1289),
      (482, 1262),
      (480, 1234),
      (480, 1218),
      (482, 1202),
      (484, 1187),
      (487, 1173),
      (491, 1159),
      (496, 1146),
      (501, 1134),
      (507, 1122),
      (514, 1111),
      (522, 1101),
      (530, 1091),
      (540, 1082),
      (560, 1064),
      (583, 1050),
      (608, 1037),
      (635, 1026),
      (665, 1017),
      (697, 1010),
      (730, 1004),
      (765, 1000),
      (802, 998),
      (840, 998),
      (1005, 998),
   ]];

   let mut contours = Vec::new();

   for contour_data in data.iter() {
      contours.push(
         points_from_coords(contour_data)
      );
   }

   let poly = Poly::new(
      contours, RGB::new(255, 255, 255),
   );

   poly
}

fn points_from_coords(coords: &[(i64, i64)]) -> Vec<IntPoint> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(IntPoint::new(x + 120, y + 120))
   }

   points
}

fn main() {
   let mut scene = Scene::new();

   scene.push(Box::new(letter_poly()));

   let mut renderer = DevelRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Letter")
      .size(1200, 800)
      .run();
}
<|endoftext|>


<commit_before>extern crate libc;
use libc::{c_char, c_int, uint8_t, uint16_t, uint32_t, c_void, timeval, c_uint, ssize_t, fd_set};

pub const FALSE: c_int = 0;
pub const TRUE: c_int = 1;
pub const OFF: c_int = 0;
pub const ON: c_int = 1;

macro_rules! modbus_enum {
    (pub enum $name:ident { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        #[cfg(target_env = "msvc")]
        pub type $name = i32;
        #[allow(non_camel_case_types)]
        #[cfg(not(target_env = "msvc"))]
        pub type $name = u32;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (pub enum $name:ident: $t:ty { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        pub type $name = $t;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $val;
        modbus_enum!(gen, $name, $val+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident = $e:expr, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $e;
        modbus_enum!(gen, $name, $e+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, ) => {}
}
modbus_enum! {
    pub enum  modbus_backend_type_t {
        _MODBUS_BACKEND_TYPE_RTU=0,
        _MODBUS_BACKEND_TYPE_TCP,
    }
}

modbus_enum! {
    pub enum modbus_error_recovery_mode {
        MODBUS_ERROR_RECOVERY_NONE          = 0,
        MODBUS_ERROR_RECOVERY_LINK          = (1<<1),
        MODBUS_ERROR_RECOVERY_PROTOCOL      = (1<<2),
    }
}

modbus_enum! {
    pub enum msg_type_t {
        MSG_INDICATION,
        MSG_CONFIRMATION,
    }
}

#[repr(C)]
#[allow(non_camel_case_types)]
pub struct modbus_backend_t {
    backend_type: c_uint,
    header_length: c_uint,
    checksum_length: c_uint,
    max_adu_length: c_uint,
    set_slave: extern fn(ctx: *mut modbus_t, slave: c_int) -> c_int,
    build_request_basis: extern fn(ctx: *mut modbus_t, function: c_int, addr: c_int,
                                nb: c_int, req: *mut uint8_t) -> c_int,
    build_response_basis: extern fn(sft: *mut sft_t, rsp: *mut uint8_t) -> c_int,
    prepare_response_tid: extern fn(req: *const uint8_t, req_length: *mut c_int) -> c_int,
    send_msg_pre: extern fn(req: *mut uint8_t, req_length: c_int) -> c_int,
    send: extern fn(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int) -> ssize_t,
    receive: extern fn(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int,
    recv: extern fn(ctx: *mut modbus_t, rsp: *mut uint8_t, rsp_length: c_int) -> ssize_t,
    check_integrity: extern fn(ctx: *mut modbus_t, msg: *mut uint8_t,
                            msg_length: *const c_int) -> c_int,
    pre_check_confirmation: extern fn(ctx: *mut modbus_t, req: *const uint8_t,
                                   rsp: *const uint8_t, rsp_length: c_int) -> c_int,
    connect: extern fn(ctx: *mut modbus_t) -> c_int,
    close: extern fn(ctx: *mut modbus_t),
    flush: extern fn(ctx: *mut modbus_t) -> c_int,
    select: extern fn(ctx: *mut modbus_t, rset: *mut fd_set, tv: *mut timeval, msg_length: c_int) -> c_int,
    free: extern fn(ctx: *mut modbus_t),
}

#[repr(C)]
pub struct sft_t {
    slave: c_int,
    function: c_int,
    t_id: c_int,
}

#[repr(C)]
pub struct _modbus {
    /* Slave address */
    slave: c_int,
    /* Socket or file descriptor */
    s: c_int,
    debug: c_int,
    error_recovery: c_int,
    response_timeout: timeval,
    byte_timeout: timeval,
    backend: *const modbus_backend_t,
    backend_data: *mut c_void,
}

#[allow(non_camel_case_types)]
pub type modbus_t = _modbus;

#[repr(C)]
pub struct modbus_mapping_t {
    nb_bits: c_int,
    start_bits: c_int,
    nb_input_bits: c_int,
    start_input_bits: c_int,
    nb_input_registers: c_int,
    start_input_registers: c_int,
    nb_registers: c_int,
    start_registers: c_int,
    tab_bits: *mut uint8_t,
    tab_input_bits: *mut uint8_t,
    tab_input_registers: *mut uint16_t,
    tab_registers: *mut uint16_t,
}

// modbus-rtu.h
pub const MODBUS_RTU_MAX_ADU_LENGTH: c_int = 256;

pub const MODBUS_RTU_RS232: c_int = 0;
pub const MODBUS_RTU_RS485: c_int = 1;

pub const MODBUS_RTU_RTS_NONE: c_int = 0;
pub const MODBUS_RTU_RTS_UP: c_int   = 1;
pub const MODBUS_RTU_RTS_DOWN: c_int = 2;

#[link(name = "modbus")]
extern {
    pub fn modbus_set_slave(ctx: *mut modbus_t, slave: c_int) -> c_int;
    pub fn modbus_set_error_recovery(ctx: *mut modbus_t, error_recovery: modbus_error_recovery_mode) -> c_int;

    pub fn modbus_set_socket(ctx: *mut modbus_t, socket: c_int) -> c_int;
    pub fn modbus_get_socket(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_get_response_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_response_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_byte_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_byte_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_header_length(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_connect(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_close(ctx: *mut modbus_t);

    pub fn modbus_free(ctx: *mut modbus_t);

    pub fn modbus_flush(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_set_debug(ctx: *mut modbus_t, flag: c_int) -> c_int;

    pub fn modbus_strerror(errnum: c_int) -> *const c_char;

    pub fn modbus_read_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_input_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_read_input_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_write_bit(ctx: *mut modbus_t, coil_addr: c_int, status: c_int) -> c_int;
    pub fn modbus_write_register(ctx: *mut modbus_t, reg_addr: c_int, value: c_int) -> c_int;
    pub fn modbus_write_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint8_t) -> c_int;
    pub fn modbus_write_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint16_t) -> c_int;
    pub fn modbus_mask_write_register(ctx: *mut modbus_t, addr: c_int, and_mask: uint16_t, or_mask: uint16_t) -> c_int;
    pub fn modbus_write_and_read_registers(ctx: *mut modbus_t, write_addr: c_int, write_nb: c_int,
                                                   src: *const uint16_t, read_addr: c_int, read_nb: c_int,
                                                   dest: *mut uint16_t) -> c_int;
    pub fn modbus_report_slave_id(ctx: *mut modbus_t, max_dest: c_int, dest: *mut uint8_t) -> c_int;

    pub fn modbus_mapping_new_start_address(
        start_bits: c_uint, nb_bits: c_uint,
        start_input_bits: c_uint, nb_input_bits: c_uint,
        start_registers: c_uint, nb_registers: c_uint,
        start_input_registers: c_uint, nb_input_registers: c_uint) -> *mut modbus_mapping_t;

    pub fn modbus_mapping_new(nb_bits: c_int, nb_input_bits: c_int, nb_registers: c_int, nb_input_registers: c_int)  -> *mut modbus_mapping_t;
    pub fn modbus_mapping_free(mb_mapping: *mut modbus_mapping_t);

    pub fn modbus_send_raw_request(ctx: *mut modbus_t, raw_req: *mut uint8_t, raw_req_length: c_int) -> c_int;

    pub fn modbus_receive(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int;

    pub fn modbus_receive_confirmation(ctx: *mut modbus_t, rsp: *mut uint8_t) -> c_int;

    pub fn modbus_reply(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int, mb_mapping: *mut modbus_mapping_t) -> c_int;
    pub fn modbus_reply_exception(ctx: *mut modbus_t, req: *const uint8_t, exception_code: c_uint) -> c_int;

    pub fn modbus_new_rtu(device: *const c_char, baud: c_int, parity: c_char, data_bit: c_int, stop_bit: c_int) -> *mut modbus_t;

    // modbus-rtu.h
    pub fn modbus_rtu_set_serial_mode(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_serial_mode(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_rts(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_rts(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_custom_rts(ctx: *mut modbus_t, set_rts: extern fn(ctx: *mut modbus_t, on: c_int)) -> c_int;

    pub fn modbus_rtu_set_rts_delay(ctx: *mut modbus_t, us: c_int) -> c_int;
    pub fn modbus_rtu_get_rts_delay(ctx: *mut modbus_t) -> c_int;

}

fn main() {
    let device: *const c_char = std::ffi::CString::new(std::env::args().nth(1).unwrap()).unwrap().as_ptr();
    let slave_id: i32 = std::env::args().nth(2).unwrap().parse().unwrap();

    unsafe {
        let mut tab_reg = vec![0u16; 32];

        let ctx = modbus_new_rtu(device, 9600, 'N' as i8, 8, 1);
        modbus_set_slave(ctx, slave_id);
        modbus_set_debug(ctx, TRUE);

        modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
        if  modbus_connect(ctx) == -1 {
            modbus_free(ctx);
            panic!("Connection failed!");
        }
        // https://doc.rust-lang.org/std/primitive.pointer.html
        let rc = modbus_read_registers(ctx, 0, 19, tab_reg.as_mut_ptr());
        if rc == -1 {
            println!("Registers could not be read");
        }

        for i in 0..rc {
            println!("register[{}]=[{}] (0x{})", i, &tab_reg[i as usize], &tab_reg[i as usize]);
        }

    }
}
<commit_msg>Fix var type<commit_after>extern crate libc;
use libc::{c_char, c_int, uint8_t, uint16_t, uint32_t, c_void, timeval, c_uint, ssize_t, fd_set};

pub const FALSE: c_int = 0;
pub const TRUE: c_int = 1;
pub const OFF: c_int = 0;
pub const ON: c_int = 1;

macro_rules! modbus_enum {
    (pub enum $name:ident { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        #[cfg(target_env = "msvc")]
        pub type $name = i32;
        #[allow(non_camel_case_types)]
        #[cfg(not(target_env = "msvc"))]
        pub type $name = u32;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (pub enum $name:ident: $t:ty { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        pub type $name = $t;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $val;
        modbus_enum!(gen, $name, $val+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident = $e:expr, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $e;
        modbus_enum!(gen, $name, $e+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, ) => {}
}
modbus_enum! {
    pub enum  modbus_backend_type_t {
        _MODBUS_BACKEND_TYPE_RTU=0,
        _MODBUS_BACKEND_TYPE_TCP,
    }
}

modbus_enum! {
    pub enum modbus_error_recovery_mode {
        MODBUS_ERROR_RECOVERY_NONE          = 0,
        MODBUS_ERROR_RECOVERY_LINK          = (1<<1),
        MODBUS_ERROR_RECOVERY_PROTOCOL      = (1<<2),
    }
}

modbus_enum! {
    pub enum msg_type_t {
        MSG_INDICATION,
        MSG_CONFIRMATION,
    }
}

#[repr(C)]
#[allow(non_camel_case_types)]
pub struct modbus_backend_t {
    backend_type: c_uint,
    header_length: c_uint,
    checksum_length: c_uint,
    max_adu_length: c_uint,
    set_slave: extern fn(ctx: *mut modbus_t, slave: c_int) -> c_int,
    build_request_basis: extern fn(ctx: *mut modbus_t, function: c_int, addr: c_int,
                                nb: c_int, req: *mut uint8_t) -> c_int,
    build_response_basis: extern fn(sft: *mut sft_t, rsp: *mut uint8_t) -> c_int,
    prepare_response_tid: extern fn(req: *const uint8_t, req_length: *mut c_int) -> c_int,
    send_msg_pre: extern fn(req: *mut uint8_t, req_length: c_int) -> c_int,
    send: extern fn(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int) -> ssize_t,
    receive: extern fn(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int,
    recv: extern fn(ctx: *mut modbus_t, rsp: *mut uint8_t, rsp_length: c_int) -> ssize_t,
    check_integrity: extern fn(ctx: *mut modbus_t, msg: *mut uint8_t,
                            msg_length: *const c_int) -> c_int,
    pre_check_confirmation: extern fn(ctx: *mut modbus_t, req: *const uint8_t,
                                   rsp: *const uint8_t, rsp_length: c_int) -> c_int,
    connect: extern fn(ctx: *mut modbus_t) -> c_int,
    close: extern fn(ctx: *mut modbus_t),
    flush: extern fn(ctx: *mut modbus_t) -> c_int,
    select: extern fn(ctx: *mut modbus_t, rset: *mut fd_set, tv: *mut timeval, msg_length: c_int) -> c_int,
    free: extern fn(ctx: *mut modbus_t),
}

#[repr(C)]
pub struct sft_t {
    slave: c_int,
    function: c_int,
    t_id: c_int,
}

#[repr(C)]
pub struct _modbus {
    /* Slave address */
    slave: c_int,
    /* Socket or file descriptor */
    s: c_int,
    debug: c_int,
    error_recovery: c_int,
    response_timeout: timeval,
    byte_timeout: timeval,
    backend: *const modbus_backend_t,
    backend_data: *mut c_void,
}

#[allow(non_camel_case_types)]
pub type modbus_t = _modbus;

#[repr(C)]
pub struct modbus_mapping_t {
    nb_bits: c_int,
    start_bits: c_int,
    nb_input_bits: c_int,
    start_input_bits: c_int,
    nb_input_registers: c_int,
    start_input_registers: c_int,
    nb_registers: c_int,
    start_registers: c_int,
    tab_bits: *mut uint8_t,
    tab_input_bits: *mut uint8_t,
    tab_input_registers: *mut uint16_t,
    tab_registers: *mut uint16_t,
}

// modbus-rtu.h
pub const MODBUS_RTU_MAX_ADU_LENGTH: c_int = 256;

pub const MODBUS_RTU_RS232: c_int = 0;
pub const MODBUS_RTU_RS485: c_int = 1;

pub const MODBUS_RTU_RTS_NONE: c_int = 0;
pub const MODBUS_RTU_RTS_UP: c_int   = 1;
pub const MODBUS_RTU_RTS_DOWN: c_int = 2;

#[link(name = "modbus")]
extern {
    pub fn modbus_set_slave(ctx: *mut modbus_t, slave: c_int) -> c_int;
    pub fn modbus_set_error_recovery(ctx: *mut modbus_t, error_recovery: modbus_error_recovery_mode) -> c_int;

    pub fn modbus_set_socket(ctx: *mut modbus_t, socket: c_int) -> c_int;
    pub fn modbus_get_socket(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_get_response_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_response_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_byte_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_byte_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_header_length(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_connect(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_close(ctx: *mut modbus_t);

    pub fn modbus_free(ctx: *mut modbus_t);

    pub fn modbus_flush(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_set_debug(ctx: *mut modbus_t, flag: c_int) -> c_int;

    pub fn modbus_strerror(errnum: c_int) -> *const c_char;

    pub fn modbus_read_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_input_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_read_input_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_write_bit(ctx: *mut modbus_t, coil_addr: c_int, status: c_int) -> c_int;
    pub fn modbus_write_register(ctx: *mut modbus_t, reg_addr: c_int, value: c_int) -> c_int;
    pub fn modbus_write_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint8_t) -> c_int;
    pub fn modbus_write_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint16_t) -> c_int;
    pub fn modbus_mask_write_register(ctx: *mut modbus_t, addr: c_int, and_mask: uint16_t, or_mask: uint16_t) -> c_int;
    pub fn modbus_write_and_read_registers(ctx: *mut modbus_t, write_addr: c_int, write_nb: c_int,
                                                   src: *const uint16_t, read_addr: c_int, read_nb: c_int,
                                                   dest: *mut uint16_t) -> c_int;
    pub fn modbus_report_slave_id(ctx: *mut modbus_t, max_dest: c_int, dest: *mut uint8_t) -> c_int;

    pub fn modbus_mapping_new_start_address(
        start_bits: c_uint, nb_bits: c_uint,
        start_input_bits: c_uint, nb_input_bits: c_uint,
        start_registers: c_uint, nb_registers: c_uint,
        start_input_registers: c_uint, nb_input_registers: c_uint) -> *mut modbus_mapping_t;

    pub fn modbus_mapping_new(nb_bits: c_int, nb_input_bits: c_int, nb_registers: c_int, nb_input_registers: c_int)  -> *mut modbus_mapping_t;
    pub fn modbus_mapping_free(mb_mapping: *mut modbus_mapping_t);

    pub fn modbus_send_raw_request(ctx: *mut modbus_t, raw_req: *mut uint8_t, raw_req_length: c_int) -> c_int;

    pub fn modbus_receive(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int;

    pub fn modbus_receive_confirmation(ctx: *mut modbus_t, rsp: *mut uint8_t) -> c_int;

    pub fn modbus_reply(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int, mb_mapping: *mut modbus_mapping_t) -> c_int;
    pub fn modbus_reply_exception(ctx: *mut modbus_t, req: *const uint8_t, exception_code: c_uint) -> c_int;

    pub fn modbus_new_rtu(device: *const c_char, baud: c_int, parity: c_char, data_bit: c_int, stop_bit: c_int) -> *mut modbus_t;

    // modbus-rtu.h
    pub fn modbus_rtu_set_serial_mode(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_serial_mode(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_rts(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_rts(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_custom_rts(ctx: *mut modbus_t, set_rts: extern fn(ctx: *mut modbus_t, on: c_int)) -> c_int;

    pub fn modbus_rtu_set_rts_delay(ctx: *mut modbus_t, us: c_int) -> c_int;
    pub fn modbus_rtu_get_rts_delay(ctx: *mut modbus_t) -> c_int;

}

fn main() {
    let device: *const c_char = std::ffi::CString::new(std::env::args().nth(1).unwrap()).unwrap().as_ptr();
    let slave_id: i32 = std::env::args().nth(2).unwrap().parse().unwrap();

    unsafe {
        let mut tab_reg = vec![0u16; 32];

        let ctx = modbus_new_rtu(device, 9600, 'N' as c_char, 8, 1);
        modbus_set_slave(ctx, slave_id);
        modbus_set_debug(ctx, TRUE);

        modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
        if  modbus_connect(ctx) == -1 {
            modbus_free(ctx);
            panic!("Connection failed!");
        }
        // https://doc.rust-lang.org/std/primitive.pointer.html
        let rc = modbus_read_registers(ctx, 0, 19, tab_reg.as_mut_ptr());
        if rc == -1 {
            println!("Registers could not be read");
        }

        for i in 0..rc {
            println!("register[{}]=[{}] (0x{})", i, &tab_reg[i as usize], &tab_reg[i as usize]);
        }

    }
}
<|endoftext|>


<commit_before>extern crate native;
extern crate glfw;
extern crate nalgebra;
extern crate kiss3d;

use nalgebra::na::Vec3;
use kiss3d::window::Window;
use kiss3d::light;
use kiss3d::camera::FirstPersonStereo;
use kiss3d::post_processing::OculusStereo;

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let mut window = Window::new_with_size("Kiss3d: stereo", 1280, 800);

    let mut c = window.add_cube(1.0, 1.0, 1.0);

    let eye        = Vec3::new(0.0f32, 0.0, 10.0);
    let at         = Vec3::new(0.0f32, 0.0, 0.0);
    let mut camera = FirstPersonStereo::new(eye, at, 0.3f32);

    // Position the window correctly. -6/-26 takes care of icewm default
    // window decoration. Should probably just disable decorations (since
    // the top title is obscured anyway).
    window.glfw_window().set_pos(-6, -26);
    c.set_color(1.0, 0.0, 0.0);

    window.set_light(light::StickToCamera);

    let mut oculus_stereo = OculusStereo::new();

    while window.render_with_camera_and_effect(&mut camera, &mut oculus_stereo) {
        for mut event in window.events().iter() {
            match event.value {
                glfw::KeyEvent(glfw::Key1, _, glfw::Release, _) => {
                    let ipd = camera.ipd();
                    camera.set_ipd(ipd + 0.1f32);
                },
                glfw::KeyEvent(glfw::Key2, _, glfw::Release, _) => {
                    let ipd = camera.ipd();
                    camera.set_ipd(ipd - 0.1f32);
                },
                _ => { }
            }
        }
    }
}
<commit_msg>Remove an unused `mut`.<commit_after>extern crate native;
extern crate glfw;
extern crate nalgebra;
extern crate kiss3d;

use nalgebra::na::Vec3;
use kiss3d::window::Window;
use kiss3d::light;
use kiss3d::camera::FirstPersonStereo;
use kiss3d::post_processing::OculusStereo;

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let mut window = Window::new_with_size("Kiss3d: stereo", 1280, 800);

    let mut c = window.add_cube(1.0, 1.0, 1.0);

    let eye        = Vec3::new(0.0f32, 0.0, 10.0);
    let at         = Vec3::new(0.0f32, 0.0, 0.0);
    let mut camera = FirstPersonStereo::new(eye, at, 0.3f32);

    // Position the window correctly. -6/-26 takes care of icewm default
    // window decoration. Should probably just disable decorations (since
    // the top title is obscured anyway).
    window.glfw_window().set_pos(-6, -26);
    c.set_color(1.0, 0.0, 0.0);

    window.set_light(light::StickToCamera);

    let mut oculus_stereo = OculusStereo::new();

    while window.render_with_camera_and_effect(&mut camera, &mut oculus_stereo) {
        for event in window.events().iter() {
            match event.value {
                glfw::KeyEvent(glfw::Key1, _, glfw::Release, _) => {
                    let ipd = camera.ipd();
                    camera.set_ipd(ipd + 0.1f32);
                },
                glfw::KeyEvent(glfw::Key2, _, glfw::Release, _) => {
                    let ipd = camera.ipd();
                    camera.set_ipd(ipd - 0.1f32);
                },
                _ => { }
            }
        }
    }
}
<|endoftext|>


<commit_before>// test1.rs
// This is a test for the following sections:
// - Variables
// - Functions

// Mary is buying apples. One apple usually costs 2 dollars, but if you buy
// more than 40 at once, each apple only costs 1! Write a function that calculates
// the price of an order of apples given the order amount. No hints this time!

// Put your function here!
// fn ..... {

// Don't modify this function!
#[test]
fn verify_test() {
    let price1 = calculate_price(55);
    let price2 = calculate_price(40);

    assert_eq!(55, price1);
    assert_eq!(80, price2);
}
<commit_msg>chore: Clarify comment in exercises/test1.rs<commit_after>// test1.rs
// This is a test for the following sections:
// - Variables
// - Functions

// Mary is buying apples. One apple usually costs 2 dollars, but if you buy
// 40 or more at once, each apple only costs 1! Write a function that calculates
// the price of an order of apples given the order amount. No hints this time!

// Put your function here!
// fn ..... {

// Don't modify this function!
#[test]
fn verify_test() {
    let price1 = calculate_price(55);
    let price2 = calculate_price(40);

    assert_eq!(55, price1);
    assert_eq!(80, price2);
}
<|endoftext|>


<commit_before>pub type c_char = u8;
pub type wchar_t = u32;

pub const O_DIRECT: ::c_int = 0x10000;
pub const O_DIRECTORY: ::c_int = 0x4000;
pub const O_NOFOLLOW: ::c_int = 0x8000;
pub const O_LARGEFILE: ::c_int = 0o400000;
<commit_msg>Auto merge of #713 - marmistrz:fix-gettid, r=alexcrichton<commit_after>pub type c_char = u8;
pub type wchar_t = u32;

pub const O_DIRECT: ::c_int = 0x10000;
pub const O_DIRECTORY: ::c_int = 0x4000;
pub const O_NOFOLLOW: ::c_int = 0x8000;
pub const O_LARGEFILE: ::c_int = 0o400000;

pub const SYS_gettid: ::c_long = 224;
<|endoftext|>


<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a [`Waker`], which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `.await` the value.
///
/// [`Waker`]: crate::task::Waker
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
#[lang = "future_trait"]
#[rustc_on_unimplemented(label = "`{Self}` is not a future", message = "`{Self}` is not a future")]
pub trait Future {
    /// The type of value produced on completion.
    #[stable(feature = "futures_api", since = "1.36.0")]
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// [`Waker::wake`] is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Pending`]: Poll::Pending
    /// [`Poll::Ready(val)`]: Poll::Ready
    /// [`Waker`]: crate::task::Waker
    /// [`Waker::wake`]: crate::task::Waker::wake
    #[lang = "poll"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl
 Future for Pin

where
    P: Unpin + ops::DerefMut<Target: Future>,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<commit_msg>Remove unnecessary intra-doc link<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a [`Waker`], which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `.await` the value.
///
/// [`Waker`]: crate::task::Waker
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
#[lang = "future_trait"]
#[rustc_on_unimplemented(label = "`{Self}` is not a future", message = "`{Self}` is not a future")]
pub trait Future {
    /// The type of value produced on completion.
    #[stable(feature = "futures_api", since = "1.36.0")]
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// [`Waker::wake`] is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Ready(val)`]: Poll::Ready
    /// [`Waker`]: crate::task::Waker
    /// [`Waker::wake`]: crate::task::Waker::wake
    #[lang = "poll"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl
 Future for Pin

where
    P: Unpin + ops::DerefMut<Target: Future>,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<|endoftext|>


<commit_before>fn encode_decode(plain: &str) -> String {
    atbash(plain).collect()
}

fn transcode_char(c: char) -> char {
    // Ignore digits and spaces otherwise shift the character
    // the required number of spaces
    if c.is_ascii_digit() || c.is_ascii_whitespace() {
        c
    } else {
        (b'z' + b'a' - c as u8) as char
    }
}

/// Filter out non-ascii characters and transcode the text
/// character by character
fn atbash<'a>(s: &'a str) -> impl Iterator<Item = char> + 'a {
    s.chars().filter_map(|c| {
        Some(c)
            .filter(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace())
            .map(|c| transcode_char(c.to_ascii_lowercase()))
    })
}

fn main() {
    let plaintext = "The quick brown fox jumps over the lazy dog.";
    let ciphertext = "gsv jfrxp yildm ulc qfnkh levi gsv ozab wlt";

    // It can encode plaintext
    assert_eq!(
        encode_decode(plaintext),
        "gsv jfrxp yildm ulc qfnkh levi gsv ozab wlt"
    );

    // It can decode ciphertext
    assert_eq!(
        encode_decode(ciphertext),
        "the quick brown fox jumps over the lazy dog"
    );
}
<commit_msg>Fixed function parameter name<commit_after>fn encode_decode(text: &str) -> String {
    atbash(text).collect()
}

fn transcode_char(c: char) -> char {
    // Ignore digits and spaces otherwise shift the character
    // the required number of spaces
    if c.is_ascii_digit() || c.is_ascii_whitespace() {
        c
    } else {
        (b'z' + b'a' - c as u8) as char
    }
}

/// Filter out non-ascii characters and transcode the text
/// character by character
fn atbash<'a>(s: &'a str) -> impl Iterator<Item = char> + 'a {
    s.chars().filter_map(|c| {
        Some(c)
            .filter(|c| c.is_ascii_alphanumeric() || c.is_ascii_whitespace())
            .map(|c| transcode_char(c.to_ascii_lowercase()))
    })
}

fn main() {
    let plaintext = "The quick brown fox jumps over the lazy dog.";
    let ciphertext = "gsv jfrxp yildm ulc qfnkh levi gsv ozab wlt";

    // It can encode plaintext
    assert_eq!(
        encode_decode(plaintext),
        "gsv jfrxp yildm ulc qfnkh levi gsv ozab wlt"
    );

    // It can decode ciphertext
    assert_eq!(
        encode_decode(ciphertext),
        "the quick brown fox jumps over the lazy dog"
    );
}
<|endoftext|>


<commit_before>use num_complex::Complex;
use std::marker::PhantomData;

/// Holds information about how to partition the access to a slice to get aligned
/// reads/writes to the largest portion of the slice.
pub struct SimdPartition<T> {
    /// Left part of the slice which must not be accessed with SIMD operations
    pub left: usize,
    /// Right  part of the slice which must not be accessed with SIMD operations
    right: usize,
    len: usize,
    data_type: PhantomData<T>,
}

/// Iterator around the left and right side of a vector.
pub struct EdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    left: *mut T,
    right: *mut T,
    end: *mut T,
    _marker: PhantomData<&'a mut T>,
}

impl<'a, T> EdgeIteratorMut<'a, T> {
    pub fn new(slice: &mut [T], left: usize, right: usize) -> impl Iterator<Item = &mut T> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            EdgeIteratorMut {
                pos: start,
                left: start.offset(left - 1),
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for EdgeIteratorMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                self.pos = self.pos.offset(1);
                Some(value)
            }
        }
    }
}

/// Iterator with index around the left and right side of a vector.
pub struct IndexedEdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    idx: isize,
    left: *mut T,
    right_idx: isize,
    right: *mut T,
    end: *mut T,
    _marker: PhantomData<&'a mut T>,
}

impl<'a, T> IndexedEdgeIteratorMut<'a, T> {
    pub fn new(
        slice: &mut [T],
        left: usize,
        right: usize,
    ) -> impl Iterator<Item = (isize, &mut T)> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            IndexedEdgeIteratorMut {
                pos: start,
                idx: 0,
                left: start.offset(left - 1),
                right_idx: len - right,
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for IndexedEdgeIteratorMut<'a, T> {
    type Item = (isize, &'a mut T);

    fn next(&mut self) -> Option<(isize, &'a mut T)> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
                self.idx = self.right_idx;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                let idx = self.idx;
                self.pos = self.pos.offset(1);
                self.idx += 1;
                Some((idx, value))
            }
        }
    }
}

/// Creates an iterator for the first `left` and last `right` elements in a slice
fn create_edge_iter_mut<T>(
    slice: &mut [T],
    right: usize,
    left: usize,
    len: usize,
) -> impl Iterator<Item = &mut T> {
    let (left_values, right_values) = slice.split_at_mut(left);
    let right = right - left;
    let right_len = len - left;

    left_values
        .iter_mut()
        .chain(right_values[right..right_len].iter_mut())
}

impl<T> SimdPartition<T> {
    pub fn new_all_scalar(len: usize) -> Self {
        Self {
            left: len,
            right: 0,
            len,
            data_type: PhantomData,
        }
    }

    pub fn new_simd(left: usize, right: usize, len: usize) -> Self {
        Self {
            left,
            right,
            len,
            data_type: PhantomData,
        }
    }

    /// Iterator over the left and right side of the slice.
    pub fn edge_iter<'a>(&self, slice: &'a [T]) -> impl Iterator<Item = &'a T> {
        slice[0..self.left]
            .iter()
            .chain(slice[self.len - self.right..self.len].iter())
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter<'a>(&self, slice: &'a [Complex<T>]) -> impl Iterator<Item = &'a Complex<T>> {
        slice[0..self.left / 2]
            .iter()
            .chain(slice[self.len / 2 - self.right / 2..self.len / 2].iter())
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn edge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len], self.left, self.right)
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter_mut<'a>(
        &self,
        slice: &'a mut [Complex<T>],
    ) -> impl Iterator<Item = &'a mut Complex<T>> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn redge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Gets the center of a slice.
    pub fn center<'a>(&self, slice: &'a [T]) -> &'a [T] {
        if self.left == self.len {
            &[]
        } else {
            &slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice.
    pub fn center_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice, expects the real part of complex data.
    pub fn rcenter_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left / 2..self.len / 2 - self.right / 2]
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{EdgeIteratorMut, IndexedEdgeIteratorMut};

    #[test]
    fn edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for n in EdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n;
        }

        let expected = vec![-1, -2, 3, 4, 5, 6, -7, -8, -9];
        assert_eq!(&data, &expected);
    }

    #[test]
    fn indexed_edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for (idx, n) in IndexedEdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n - 10 * (idx + 1);
        }

        let expected = vec![-11, -22, 3, 4, 5, 6, -77, -88, -99];
        assert_eq!(&data, &expected);
    }
}
<commit_msg>Removed unused function<commit_after>use num_complex::Complex;
use std::marker::PhantomData;

/// Holds information about how to partition the access to a slice to get aligned
/// reads/writes to the largest portion of the slice.
pub struct SimdPartition<T> {
    /// Left part of the slice which must not be accessed with SIMD operations
    pub left: usize,
    /// Right  part of the slice which must not be accessed with SIMD operations
    right: usize,
    len: usize,
    data_type: PhantomData<T>,
}

/// Iterator around the left and right side of a vector.
pub struct EdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    left: *mut T,
    right: *mut T,
    end: *mut T,
    _marker: PhantomData<&'a mut T>,
}

impl<'a, T> EdgeIteratorMut<'a, T> {
    pub fn new(slice: &mut [T], left: usize, right: usize) -> impl Iterator<Item = &mut T> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            EdgeIteratorMut {
                pos: start,
                left: start.offset(left - 1),
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for EdgeIteratorMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                self.pos = self.pos.offset(1);
                Some(value)
            }
        }
    }
}

/// Iterator with index around the left and right side of a vector.
pub struct IndexedEdgeIteratorMut<'a, T: 'a> {
    pos: *mut T,
    idx: isize,
    left: *mut T,
    right_idx: isize,
    right: *mut T,
    end: *mut T,
    _marker: PhantomData<&'a mut T>,
}

impl<'a, T> IndexedEdgeIteratorMut<'a, T> {
    pub fn new(
        slice: &mut [T],
        left: usize,
        right: usize,
    ) -> impl Iterator<Item = (isize, &mut T)> {
        let start = slice.as_mut_ptr();
        let len = slice.len() as isize;
        let left = left as isize;
        let right = right as isize;
        unsafe {
            IndexedEdgeIteratorMut {
                pos: start,
                idx: 0,
                left: start.offset(left - 1),
                right_idx: len - right,
                right: start.offset(len - right),
                end: start.offset(len - 1),
                _marker: PhantomData,
            }
        }
    }
}

impl<'a, T> Iterator for IndexedEdgeIteratorMut<'a, T> {
    type Item = (isize, &'a mut T);

    fn next(&mut self) -> Option<(isize, &'a mut T)> {
        unsafe {
            // Jump from end of left to right.
            if self.pos > self.left && self.pos < self.right {
                self.pos = self.right;
                self.idx = self.right_idx;
            }

            if self.pos > self.end {
                return None;
            } else {
                let value = &mut *self.pos;
                let idx = self.idx;
                self.pos = self.pos.offset(1);
                self.idx += 1;
                Some((idx, value))
            }
        }
    }
}

impl<T> SimdPartition<T> {
    pub fn new_all_scalar(len: usize) -> Self {
        Self {
            left: len,
            right: 0,
            len,
            data_type: PhantomData,
        }
    }

    pub fn new_simd(left: usize, right: usize, len: usize) -> Self {
        Self {
            left,
            right,
            len,
            data_type: PhantomData,
        }
    }

    /// Iterator over the left and right side of the slice.
    pub fn edge_iter<'a>(&self, slice: &'a [T]) -> impl Iterator<Item = &'a T> {
        slice[0..self.left]
            .iter()
            .chain(slice[self.len - self.right..self.len].iter())
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter<'a>(&self, slice: &'a [Complex<T>]) -> impl Iterator<Item = &'a Complex<T>> {
        slice[0..self.left / 2]
            .iter()
            .chain(slice[self.len / 2 - self.right / 2..self.len / 2].iter())
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn edge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len], self.left, self.right)
    }

    /// Iterator over the left and right side of the slice. Expects complex data.
    pub fn cedge_iter_mut<'a>(
        &self,
        slice: &'a mut [Complex<T>],
    ) -> impl Iterator<Item = &'a mut Complex<T>> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Iterator over the left and right side of the slice. Expects the real part of complex data.
    pub fn redge_iter_mut<'a>(&self, slice: &'a mut [T]) -> impl Iterator<Item = &'a mut T> {
        EdgeIteratorMut::new(&mut slice[0..self.len / 2], self.left / 2, self.right / 2)
    }

    /// Gets the center of a slice.
    pub fn center<'a>(&self, slice: &'a [T]) -> &'a [T] {
        if self.left == self.len {
            &[]
        } else {
            &slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice.
    pub fn center_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left..self.len - self.right]
        }
    }

    // Gets the center of a slice, expects the real part of complex data.
    pub fn rcenter_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
        if self.left == self.len {
            &mut []
        } else {
            &mut slice[self.left / 2..self.len / 2 - self.right / 2]
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{EdgeIteratorMut, IndexedEdgeIteratorMut};

    #[test]
    fn edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for n in EdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n;
        }

        let expected = vec![-1, -2, 3, 4, 5, 6, -7, -8, -9];
        assert_eq!(&data, &expected);
    }

    #[test]
    fn indexed_edge_iter_test() {
        let mut data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        for (idx, n) in IndexedEdgeIteratorMut::new(&mut data, 2, 3) {
            *n = -*n - 10 * (idx + 1);
        }

        let expected = vec![-11, -22, 3, 4, 5, 6, -77, -88, -99];
        assert_eq!(&data, &expected);
    }
}
<|endoftext|>