<commit_before>mod error;

use std::convert::{TryFrom, TryInto};

use fleetspeak::Packet;
use log::error;

use crate::action;
pub use self::error::{Error, ParseError};

pub type Result<T> = std::result::Result<T, Error>;

pub fn execute<S, R, H>(session: &mut S, handler: H, payload: Payload) -> Result<()>
where
    S: Session,
    R: action::Request,
    H: FnOnce(&mut S, R) -> Result<()>,
{
    handler(session, payload.parse()?)
}

pub fn handle<M>(message: M)
where
    M: TryInto<Demand, Error=ParseError>,
{
    let demand = match message.try_into() {
        Ok(demand) => demand,
        Err(error) => {
            error!("failed to parse the message: {}", error);
            return;
        }
    };

    let mut session = Action::new(demand.header.clone());
    let result = action::dispatch(&demand.action, &mut session, demand.payload);

    let status = Status {
        header: demand.header,
        result: result,
    };

    let message = match status.try_into() {
        Ok(message) => message,
        Err(error) => {
            // If we cannot encode the final status message, there is nothing
            // we can do to notify the server, as status is responsible for
            // reporting errors. We can only log the error and carry on.
            error!("failed to encode status message: {}", error);
            return;
        }
    };

    send(message);
}

pub trait Session {
    fn send<R: action::Response>(&mut self, response: R) -> Result<()>;
}

pub struct Action {
    header: Header,
    next_response_id: u64,
}

impl Action {

    pub fn new(header: Header) -> Action {
        Action {
            header: header,
            next_response_id: 0,
        }
    }
}

impl Session for Action {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: self.header.session_id.clone(),
            request_id: Some(self.header.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }.send()?;

        self.next_response_id += 1;

        Ok(())
    }
}

pub struct Sink {
    id: &'static str,
}

impl Session for Sink {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }.send()
    }
}

pub fn startup() -> Sink {
    Sink { id: "/flows/F:Startup" }
}

pub struct Demand {
    pub action: String,
    pub header: Header,
    pub payload: Payload,
}

impl TryFrom<rrg_proto::GrrMessage> for Demand {

    type Error = ParseError;

    fn try_from(message: rrg_proto::GrrMessage)
    -> std::result::Result<Demand, ParseError>
    {
        use ParseError::*;

        let header = Header {
            session_id: message.session_id.ok_or(MissingField("session id"))?,
            request_id: message.request_id.ok_or(MissingField("request id"))?,
        };

        Ok(Demand {
            action: message.name.ok_or(MissingField("action name"))?,
            header: header,
            payload: Payload(message.args),
        })
    }
}

#[derive(Clone, Debug)]
pub struct Header {
    pub session_id: String,
    pub request_id: u64,
}

#[derive(Debug)]
pub struct Payload(Option<Vec<u8>>);

impl Payload {

    pub fn parse<R>(&self) -> std::result::Result<R, ParseError>
    where
        R: action::Request,
    {
        let proto = match self {
            Payload(Some(bytes)) => prost::Message::decode(&bytes[..])?,
            Payload(None) => Default::default(),
        };

        Ok(R::from_proto(proto))
    }
}

// TODO: This type should not be exposed.
pub struct Request<R: action::Request> {
    pub name: String,
    pub session_id: String,
    pub request_id: u64,
    pub data: R,
}

impl<R: action::Request> TryFrom<rrg_proto::GrrMessage> for Request<R> {

    type Error = ParseError;

    fn try_from(message: rrg_proto::GrrMessage)
    -> std::result::Result<Request<R>, ParseError>
    {
        use ParseError::*;

        let name = message.name.ok_or(MissingField("action name"))?;
        let session_id = message.session_id.ok_or(MissingField("session id"))?;
        let request_id = message.request_id.ok_or(MissingField("request id"))?;

        let proto = match message.args {
            Some(bytes) => prost::Message::decode(&bytes[..])?,
            None => Default::default(),
        };

        Ok(Request {
            name: name,
            session_id: session_id,
            request_id: request_id,
            data: R::from_proto(proto),
        })
    }
}

struct Response<R: action::Response> {
    session_id: String,
    request_id: Option<u64>,
    response_id: Option<u64>,
    data: R,
}

impl<R: action::Response> Response<R> {

    fn send(self) -> Result<()> {
        let message = self.try_into()?;
        send(message);

        Ok(())
    }
}

impl<R: action::Response> TryInto<rrg_proto::GrrMessage> for Response<R> {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError>
    {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        })
    }
}

struct Status {
    header: Header,
    result: Result<()>,
}

impl TryInto<rrg_proto::GrrMessage> for Status {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError> {
        let status = match self.result {
            Ok(()) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::Ok.into()),
                ..Default::default()
            },
            Err(error) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::GenericError.into()),
                error_message: Some(error.to_string()),
                ..Default::default()
            },
        };

        let mut data = Vec::new();
        prost::Message::encode(&status, &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.header.session_id),
            response_id: Some(self.header.request_id),
            r#type: Some(rrg_proto::grr_message::Type::Status.into()),
            args_rdf_name: Some(String::from("GrrStatus")),
            args: Some(data),
            ..Default::default()
        })
    }
}

fn send(message: rrg_proto::GrrMessage) {
        let packet = Packet {
            service: String::from("GRR"),
            kind: Some(String::from("GrrMessage")),
            data: message,
        };

        if let Err(error) = fleetspeak::send(packet) {
            // If we failed to deliver the message through Fleetspeak, it means
            // that our communication is broken (e.g. the pipe was closed) and
            // the agent should be killed.
            panic!("message delivery failure: {}", error)
        };
}
<commit_msg>Remove a no longer used request type.<commit_after>mod error;

use std::convert::{TryFrom, TryInto};

use fleetspeak::Packet;
use log::error;

use crate::action;
pub use self::error::{Error, ParseError};

pub type Result<T> = std::result::Result<T, Error>;

pub fn execute<S, R, H>(session: &mut S, handler: H, payload: Payload) -> Result<()>
where
    S: Session,
    R: action::Request,
    H: FnOnce(&mut S, R) -> Result<()>,
{
    handler(session, payload.parse()?)
}

pub fn handle<M>(message: M)
where
    M: TryInto<Demand, Error=ParseError>,
{
    let demand = match message.try_into() {
        Ok(demand) => demand,
        Err(error) => {
            error!("failed to parse the message: {}", error);
            return;
        }
    };

    let mut session = Action::new(demand.header.clone());
    let result = action::dispatch(&demand.action, &mut session, demand.payload);

    let status = Status {
        header: demand.header,
        result: result,
    };

    let message = match status.try_into() {
        Ok(message) => message,
        Err(error) => {
            // If we cannot encode the final status message, there is nothing
            // we can do to notify the server, as status is responsible for
            // reporting errors. We can only log the error and carry on.
            error!("failed to encode status message: {}", error);
            return;
        }
    };

    send(message);
}

pub trait Session {
    fn send<R: action::Response>(&mut self, response: R) -> Result<()>;
}

pub struct Action {
    header: Header,
    next_response_id: u64,
}

impl Action {

    pub fn new(header: Header) -> Action {
        Action {
            header: header,
            next_response_id: 0,
        }
    }
}

impl Session for Action {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: self.header.session_id.clone(),
            request_id: Some(self.header.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }.send()?;

        self.next_response_id += 1;

        Ok(())
    }
}

pub struct Sink {
    id: &'static str,
}

impl Session for Sink {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }.send()
    }
}

pub fn startup() -> Sink {
    Sink { id: "/flows/F:Startup" }
}

pub struct Demand {
    pub action: String,
    pub header: Header,
    pub payload: Payload,
}

impl TryFrom<rrg_proto::GrrMessage> for Demand {

    type Error = ParseError;

    fn try_from(message: rrg_proto::GrrMessage)
    -> std::result::Result<Demand, ParseError>
    {
        use ParseError::*;

        let header = Header {
            session_id: message.session_id.ok_or(MissingField("session id"))?,
            request_id: message.request_id.ok_or(MissingField("request id"))?,
        };

        Ok(Demand {
            action: message.name.ok_or(MissingField("action name"))?,
            header: header,
            payload: Payload(message.args),
        })
    }
}

#[derive(Clone, Debug)]
pub struct Header {
    pub session_id: String,
    pub request_id: u64,
}

#[derive(Debug)]
pub struct Payload(Option<Vec<u8>>);

impl Payload {

    pub fn parse<R>(&self) -> std::result::Result<R, ParseError>
    where
        R: action::Request,
    {
        let proto = match self {
            Payload(Some(bytes)) => prost::Message::decode(&bytes[..])?,
            Payload(None) => Default::default(),
        };

        Ok(R::from_proto(proto))
    }
}

struct Response<R: action::Response> {
    session_id: String,
    request_id: Option<u64>,
    response_id: Option<u64>,
    data: R,
}

impl<R: action::Response> Response<R> {

    fn send(self) -> Result<()> {
        let message = self.try_into()?;
        send(message);

        Ok(())
    }
}

impl<R: action::Response> TryInto<rrg_proto::GrrMessage> for Response<R> {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError>
    {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        })
    }
}

struct Status {
    header: Header,
    result: Result<()>,
}

impl TryInto<rrg_proto::GrrMessage> for Status {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError> {
        let status = match self.result {
            Ok(()) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::Ok.into()),
                ..Default::default()
            },
            Err(error) => rrg_proto::GrrStatus {
                status: Some(rrg_proto::grr_status::ReturnedStatus::GenericError.into()),
                error_message: Some(error.to_string()),
                ..Default::default()
            },
        };

        let mut data = Vec::new();
        prost::Message::encode(&status, &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.header.session_id),
            response_id: Some(self.header.request_id),
            r#type: Some(rrg_proto::grr_message::Type::Status.into()),
            args_rdf_name: Some(String::from("GrrStatus")),
            args: Some(data),
            ..Default::default()
        })
    }
}

fn send(message: rrg_proto::GrrMessage) {
        let packet = Packet {
            service: String::from("GRR"),
            kind: Some(String::from("GrrMessage")),
            data: message,
        };

        if let Err(error) = fleetspeak::send(packet) {
            // If we failed to deliver the message through Fleetspeak, it means
            // that our communication is broken (e.g. the pipe was closed) and
            // the agent should be killed.
            panic!("message delivery failure: {}", error)
        };
}
<|endoftext|>


<commit_before>// Built-in Lints
#![deny(warnings, missing_debug_implementations, missing_copy_implementations)]
// Clippy lints
#![allow(
    clippy::option_map_unwrap_or_else,
    clippy::option_map_unwrap_or,
    clippy::match_same_arms,
    clippy::type_complexity
)]
#![warn(
    clippy::option_unwrap_used,
    clippy::result_unwrap_used,
    clippy::print_stdout,
    clippy::wrong_pub_self_convention,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding
)]
#![cfg_attr(test, allow(clippy::option_unwrap_used, clippy::result_unwrap_used))]
//! Provides functions for maintaining database schema.
//!
//! A database migration always provides procedures to update the schema, as well as to revert
//! itself. Diesel's migrations are versioned, and run in order. Diesel also takes care of tracking
//! which migrations have already been run automatically. Your migrations don't need to be
//! idempotent, as Diesel will ensure no migration is run twice unless it has been reverted.
//!
//! Migrations should be placed in a `/migrations` directory at the root of your project (the same
//! directory as `Cargo.toml`). When any of these functions are run, Diesel will search for the
//! migrations directory in the current directory and its parents, stopping when it finds the
//! directory containing `Cargo.toml`.
//!
//! Individual migrations should be a folder containing exactly two files, `up.sql` and `down.sql`.
//! `up.sql` will be used to run the migration, while `down.sql` will be used for reverting it. The
//! folder itself should have the structure `{version}_{migration_name}`. It is recommended that
//! you use the timestamp of creation for the version.
//!
//! Migrations can either be run with the CLI or embedded into the compiled application
//! and executed with code, for example right after establishing a database connection.
//! For more information, consult the [`embed_migrations!`](../macro.embed_migrations.html) macro.
//!
//! ## Example
//!
//! ```text
//! # Directory Structure
//! - 20151219180527_create_users
//!     - up.sql
//!     - down.sql
//! - 20160107082941_create_posts
//!     - up.sql
//!     - down.sql
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/up.sql
//! CREATE TABLE users (
//!   id SERIAL PRIMARY KEY,
//!   name VARCHAR NOT NULL,
//!   hair_color VARCHAR
//! );
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/down.sql
//! DROP TABLE users;
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/up.sql
//! CREATE TABLE posts (
//!   id SERIAL PRIMARY KEY,
//!   user_id INTEGER NOT NULL,
//!   title VARCHAR NOT NULL,
//!   body TEXT
//! );
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/down.sql
//! DROP TABLE posts;
//! ```
#[macro_use]
extern crate diesel;

#[cfg(feature = "barrel")]
extern crate barrel;

#[doc(hidden)]
pub mod connection;
pub mod migration;
#[doc(hidden)]
pub mod schema;

#[doc(inline)]
pub use self::connection::MigrationConnection;
#[doc(inline)]
pub use self::migration::*;
pub use diesel::migration::*;

use std::fs::DirEntry;
use std::io::{stdout, Write};

use self::schema::__diesel_schema_migrations::dsl::*;
use diesel::expression_methods::*;
use diesel::{Connection, QueryDsl, QueryResult, RunQueryDsl};

use std::env;
use std::path::{Path, PathBuf};

pub static TIMESTAMP_FORMAT: &str = "%Y-%m-%d-%H%M%S";

/// Runs all migrations that have not yet been run. This function will print all progress to
/// stdout. This function will return an `Err` if some error occurs reading the migrations, or if
/// any migration fails to run. Each migration is run in its own transaction, so some migrations
/// may be committed, even if a later migration fails to run.
///
/// It should be noted that this runs all migrations that have not already been run, regardless of
/// whether or not their version is later than the latest run migration. This is generally not a
/// problem, and eases the more common case of two developers generating independent migrations on
/// a branch. Whoever created the second one will eventually need to run the first when both
/// branches are merged.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn run_pending_migrations<Conn>(conn: &Conn) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations_dir = find_migrations_directory()?;
    run_pending_migrations_in_directory(conn, &migrations_dir, &mut stdout())
}

#[doc(hidden)]
pub fn run_pending_migrations_in_directory<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let all_migrations = migrations_in_directory(migrations_dir)?;
    run_migrations(conn, all_migrations, output)
}

/// Compares migrations found in `migrations_dir` to those that have been applied.
/// Returns a list of pathbufs and whether they have been applied.
pub fn mark_migrations_in_directory<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
) -> Result<Vec<(Box<dyn Migration>, bool)>, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations = migrations_in_directory(migrations_dir)?;
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;
    let migrations = migrations
        .into_iter()
        .map(|m| {
            let applied = already_run.contains(&m.version().to_string());
            (m, applied)
        })
        .collect();
    Ok(migrations)
}

// Returns true if there are outstanding migrations in the migrations directory, otherwise
// returns false. Returns an `Err` if there are problems with migration setup.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn any_pending_migrations<Conn>(conn: &Conn) -> Result<bool, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations_dir = find_migrations_directory()?;
    any_pending_migrations_in_directory(conn, &migrations_dir)
}

pub fn any_pending_migrations_in_directory<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
) -> Result<bool, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let all_migrations = migrations_in_directory(&migrations_dir)?;
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;

    let pending = all_migrations
        .into_iter()
        .any(|m| !already_run.contains(&m.version().to_string()));

    Ok(pending)
}

/// Reverts the last migration that was run. Returns the version that was reverted. Returns an
/// `Err` if no migrations have ever been run.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn revert_latest_migration<Conn>(conn: &Conn) -> Result<String, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations_dir = find_migrations_directory()?;
    revert_latest_migration_in_directory(conn, &migrations_dir)
}

pub fn revert_latest_migration_in_directory<Conn>(
    conn: &Conn,
    path: &Path,
) -> Result<String, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    setup_database(conn)?;
    let latest_migration_version = conn
        .latest_run_migration_version()?
        .ok_or_else(|| RunMigrationsError::MigrationError(MigrationError::NoMigrationRun))?;
    revert_migration_with_version(conn, path, &latest_migration_version, &mut stdout())
        .map(|_| latest_migration_version)
}

#[doc(hidden)]
pub fn revert_migration_with_version<Conn: Connection>(
    conn: &Conn,
    migrations_dir: &Path,
    ver: &str,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError> {
    migration_with_version(migrations_dir, ver)
        .map_err(Into::into)
        .and_then(|m| revert_migration(conn, &m, output))
}

#[doc(hidden)]
pub fn run_migration_with_version<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
    ver: &str,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    migration_with_version(migrations_dir, ver)
        .map_err(Into::into)
        .and_then(|m| run_migration(conn, &*m, output))
}

fn migration_with_version(
    migrations_dir: &Path,
    ver: &str,
) -> Result<Box<dyn Migration>, MigrationError> {
    let all_migrations = migrations_in_directory(migrations_dir)?;
    let migration = all_migrations.into_iter().find(|m| m.version() == ver);
    match migration {
        Some(m) => Ok(m),
        None => Err(MigrationError::UnknownMigrationVersion(ver.into())),
    }
}

#[doc(hidden)]
pub fn setup_database<Conn: MigrationConnection>(conn: &Conn) -> QueryResult<usize> {
    conn.setup()
}

#[doc(hidden)]
pub fn migration_paths_in_directory(path: &Path) -> Result<Vec<DirEntry>, MigrationError> {
    path.read_dir()?
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if entry.file_name().to_string_lossy().starts_with('.') {
                None
            } else {
                Some(Ok(entry))
            }
        })
        .collect()
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<dyn Migration>>, MigrationError> {
    migration_paths_in_directory(path)?
        .iter()
        .map(|e| migration_from(e.path()))
        .collect()
}

/// Run all pending migrations in the given list. Apps should likely be calling
/// `run_pending_migrations` or `run_pending_migrations_in_directory` instead.
pub fn run_migrations<Conn, List>(
    conn: &Conn,
    migrations: List,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
    List: IntoIterator,
    List::Item: Migration,
{
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;
    let mut pending_migrations: Vec<_> = migrations
        .into_iter()
        .filter(|m| !already_run.contains(&m.version().to_string()))
        .collect();

    pending_migrations.sort_by(|a, b| a.version().cmp(b.version()));
    for migration in pending_migrations {
        run_migration(conn, &migration, output)?;
    }
    Ok(())
}

fn run_migration<Conn>(
    conn: &Conn,
    migration: &dyn Migration,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    conn.transaction(|| {
        if migration.version() != "00000000000000" {
            writeln!(output, "Running migration {}", name(&migration))?;
        }
        if let Err(e) = migration.run(conn) {
            writeln!(
                output,
                "Executing migration script {}",
                file_name(&migration, "up.sql")
            )?;
            return Err(e);
        }
        conn.insert_new_migration(migration.version())?;
        Ok(())
    })
}

fn revert_migration<Conn: Connection>(
    conn: &Conn,
    migration: &dyn Migration,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError> {
    conn.transaction(|| {
        writeln!(output, "Rolling back migration {}", name(&migration))?;
        if let Err(e) = migration.revert(conn) {
            writeln!(
                output,
                "Executing migration script {}",
                file_name(&migration, "down.sql")
            )?;
            return Err(e);
        }
        let target = __diesel_schema_migrations.filter(version.eq(migration.version()));
        ::diesel::delete(target).execute(conn)?;
        Ok(())
    })
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents of the
/// current directory, until it reaches the root directory.  Returns
/// `MigrationError::MigrationDirectoryNotFound` if no directory is found.
pub fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&env::current_dir()?)
}

/// Searches for the migrations directory relative to the given path. See
/// `find_migrations_directory` for more details.
pub fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else {
        path.parent()
            .map(|p| search_for_migrations_directory(p))
            .unwrap_or_else(|| Err(MigrationError::MigrationDirectoryNotFound(path.into())))
            .map_err(|_| MigrationError::MigrationDirectoryNotFound(path.into()))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempfile;

    use super::*;

    use self::tempfile::Builder;
    use std::fs;

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = Builder::new().prefix("diesel").tempdir().unwrap();

        assert_eq!(
            Err(MigrationError::MigrationDirectoryNotFound(dir.path().into())),
            search_for_migrations_directory(dir.path())
        );
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = Builder::new().prefix("diesel").tempdir().unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");

        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(
            Ok(migrations_path),
            search_for_migrations_directory(&temp_path)
        );
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = Builder::new().prefix("diesel").tempdir().unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(
            Ok(migrations_path),
            search_for_migrations_directory(&child_path)
        );
    }
}
<commit_msg>Rustfmt<commit_after>// Built-in Lints
#![deny(warnings, missing_debug_implementations, missing_copy_implementations)]
// Clippy lints
#![allow(
    clippy::option_map_unwrap_or_else,
    clippy::option_map_unwrap_or,
    clippy::match_same_arms,
    clippy::type_complexity
)]
#![warn(
    clippy::option_unwrap_used,
    clippy::result_unwrap_used,
    clippy::print_stdout,
    clippy::wrong_pub_self_convention,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding
)]
#![cfg_attr(test, allow(clippy::option_unwrap_used, clippy::result_unwrap_used))]
//! Provides functions for maintaining database schema.
//!
//! A database migration always provides procedures to update the schema, as well as to revert
//! itself. Diesel's migrations are versioned, and run in order. Diesel also takes care of tracking
//! which migrations have already been run automatically. Your migrations don't need to be
//! idempotent, as Diesel will ensure no migration is run twice unless it has been reverted.
//!
//! Migrations should be placed in a `/migrations` directory at the root of your project (the same
//! directory as `Cargo.toml`). When any of these functions are run, Diesel will search for the
//! migrations directory in the current directory and its parents, stopping when it finds the
//! directory containing `Cargo.toml`.
//!
//! Individual migrations should be a folder containing exactly two files, `up.sql` and `down.sql`.
//! `up.sql` will be used to run the migration, while `down.sql` will be used for reverting it. The
//! folder itself should have the structure `{version}_{migration_name}`. It is recommended that
//! you use the timestamp of creation for the version.
//!
//! Migrations can either be run with the CLI or embedded into the compiled application
//! and executed with code, for example right after establishing a database connection.
//! For more information, consult the [`embed_migrations!`](../macro.embed_migrations.html) macro.
//!
//! ## Example
//!
//! ```text
//! # Directory Structure
//! - 20151219180527_create_users
//!     - up.sql
//!     - down.sql
//! - 20160107082941_create_posts
//!     - up.sql
//!     - down.sql
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/up.sql
//! CREATE TABLE users (
//!   id SERIAL PRIMARY KEY,
//!   name VARCHAR NOT NULL,
//!   hair_color VARCHAR
//! );
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/down.sql
//! DROP TABLE users;
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/up.sql
//! CREATE TABLE posts (
//!   id SERIAL PRIMARY KEY,
//!   user_id INTEGER NOT NULL,
//!   title VARCHAR NOT NULL,
//!   body TEXT
//! );
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/down.sql
//! DROP TABLE posts;
//! ```
#[macro_use]
extern crate diesel;

#[cfg(feature = "barrel")]
extern crate barrel;

#[doc(hidden)]
pub mod connection;
pub mod migration;
#[doc(hidden)]
pub mod schema;

#[doc(inline)]
pub use self::connection::MigrationConnection;
#[doc(inline)]
pub use self::migration::*;
pub use diesel::migration::*;

use std::fs::DirEntry;
use std::io::{stdout, Write};

use self::schema::__diesel_schema_migrations::dsl::*;
use diesel::expression_methods::*;
use diesel::{Connection, QueryDsl, QueryResult, RunQueryDsl};

use std::env;
use std::path::{Path, PathBuf};

pub static TIMESTAMP_FORMAT: &str = "%Y-%m-%d-%H%M%S";

/// Runs all migrations that have not yet been run. This function will print all progress to
/// stdout. This function will return an `Err` if some error occurs reading the migrations, or if
/// any migration fails to run. Each migration is run in its own transaction, so some migrations
/// may be committed, even if a later migration fails to run.
///
/// It should be noted that this runs all migrations that have not already been run, regardless of
/// whether or not their version is later than the latest run migration. This is generally not a
/// problem, and eases the more common case of two developers generating independent migrations on
/// a branch. Whoever created the second one will eventually need to run the first when both
/// branches are merged.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn run_pending_migrations<Conn>(conn: &Conn) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations_dir = find_migrations_directory()?;
    run_pending_migrations_in_directory(conn, &migrations_dir, &mut stdout())
}

#[doc(hidden)]
pub fn run_pending_migrations_in_directory<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let all_migrations = migrations_in_directory(migrations_dir)?;
    run_migrations(conn, all_migrations, output)
}

/// Compares migrations found in `migrations_dir` to those that have been applied.
/// Returns a list of pathbufs and whether they have been applied.
pub fn mark_migrations_in_directory<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
) -> Result<Vec<(Box<dyn Migration>, bool)>, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations = migrations_in_directory(migrations_dir)?;
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;
    let migrations = migrations
        .into_iter()
        .map(|m| {
            let applied = already_run.contains(&m.version().to_string());
            (m, applied)
        })
        .collect();
    Ok(migrations)
}

// Returns true if there are outstanding migrations in the migrations directory, otherwise
// returns false. Returns an `Err` if there are problems with migration setup.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn any_pending_migrations<Conn>(conn: &Conn) -> Result<bool, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations_dir = find_migrations_directory()?;
    any_pending_migrations_in_directory(conn, &migrations_dir)
}

pub fn any_pending_migrations_in_directory<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
) -> Result<bool, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let all_migrations = migrations_in_directory(&migrations_dir)?;
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;

    let pending = all_migrations
        .into_iter()
        .any(|m| !already_run.contains(&m.version().to_string()));

    Ok(pending)
}

/// Reverts the last migration that was run. Returns the version that was reverted. Returns an
/// `Err` if no migrations have ever been run.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn revert_latest_migration<Conn>(conn: &Conn) -> Result<String, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    let migrations_dir = find_migrations_directory()?;
    revert_latest_migration_in_directory(conn, &migrations_dir)
}

pub fn revert_latest_migration_in_directory<Conn>(
    conn: &Conn,
    path: &Path,
) -> Result<String, RunMigrationsError>
where
    Conn: MigrationConnection,
{
    setup_database(conn)?;
    let latest_migration_version = conn
        .latest_run_migration_version()?
        .ok_or_else(|| RunMigrationsError::MigrationError(MigrationError::NoMigrationRun))?;
    revert_migration_with_version(conn, path, &latest_migration_version, &mut stdout())
        .map(|_| latest_migration_version)
}

#[doc(hidden)]
pub fn revert_migration_with_version<Conn: Connection>(
    conn: &Conn,
    migrations_dir: &Path,
    ver: &str,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError> {
    migration_with_version(migrations_dir, ver)
        .map_err(Into::into)
        .and_then(|m| revert_migration(conn, &m, output))
}

#[doc(hidden)]
pub fn run_migration_with_version<Conn>(
    conn: &Conn,
    migrations_dir: &Path,
    ver: &str,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    migration_with_version(migrations_dir, ver)
        .map_err(Into::into)
        .and_then(|m| run_migration(conn, &*m, output))
}

fn migration_with_version(
    migrations_dir: &Path,
    ver: &str,
) -> Result<Box<dyn Migration>, MigrationError> {
    let all_migrations = migrations_in_directory(migrations_dir)?;
    let migration = all_migrations.into_iter().find(|m| m.version() == ver);
    match migration {
        Some(m) => Ok(m),
        None => Err(MigrationError::UnknownMigrationVersion(ver.into())),
    }
}

#[doc(hidden)]
pub fn setup_database<Conn: MigrationConnection>(conn: &Conn) -> QueryResult<usize> {
    conn.setup()
}

#[doc(hidden)]
pub fn migration_paths_in_directory(path: &Path) -> Result<Vec<DirEntry>, MigrationError> {
    path.read_dir()?
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if entry.file_name().to_string_lossy().starts_with('.') {
                None
            } else {
                Some(Ok(entry))
            }
        })
        .collect()
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<dyn Migration>>, MigrationError> {
    migration_paths_in_directory(path)?
        .iter()
        .map(|e| migration_from(e.path()))
        .collect()
}

/// Run all pending migrations in the given list. Apps should likely be calling
/// `run_pending_migrations` or `run_pending_migrations_in_directory` instead.
pub fn run_migrations<Conn, List>(
    conn: &Conn,
    migrations: List,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
    List: IntoIterator,
    List::Item: Migration,
{
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;
    let mut pending_migrations: Vec<_> = migrations
        .into_iter()
        .filter(|m| !already_run.contains(&m.version().to_string()))
        .collect();

    pending_migrations.sort_by(|a, b| a.version().cmp(b.version()));
    for migration in pending_migrations {
        run_migration(conn, &migration, output)?;
    }
    Ok(())
}

fn run_migration<Conn>(
    conn: &Conn,
    migration: &dyn Migration,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError>
where
    Conn: MigrationConnection,
{
    conn.transaction(|| {
        if migration.version() != "00000000000000" {
            writeln!(output, "Running migration {}", name(&migration))?;
        }
        if let Err(e) = migration.run(conn) {
            writeln!(
                output,
                "Executing migration script {}",
                file_name(&migration, "up.sql")
            )?;
            return Err(e);
        }
        conn.insert_new_migration(migration.version())?;
        Ok(())
    })
}

fn revert_migration<Conn: Connection>(
    conn: &Conn,
    migration: &dyn Migration,
    output: &mut dyn Write,
) -> Result<(), RunMigrationsError> {
    conn.transaction(|| {
        writeln!(output, "Rolling back migration {}", name(&migration))?;
        if let Err(e) = migration.revert(conn) {
            writeln!(
                output,
                "Executing migration script {}",
                file_name(&migration, "down.sql")
            )?;
            return Err(e);
        }
        let target = __diesel_schema_migrations.filter(version.eq(migration.version()));
        ::diesel::delete(target).execute(conn)?;
        Ok(())
    })
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents of the
/// current directory, until it reaches the root directory.  Returns
/// `MigrationError::MigrationDirectoryNotFound` if no directory is found.
pub fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&env::current_dir()?)
}

/// Searches for the migrations directory relative to the given path. See
/// `find_migrations_directory` for more details.
pub fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else {
        path.parent()
            .map(|p| search_for_migrations_directory(p))
            .unwrap_or_else(|| Err(MigrationError::MigrationDirectoryNotFound(path.into())))
            .map_err(|_| MigrationError::MigrationDirectoryNotFound(path.into()))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempfile;

    use super::*;

    use self::tempfile::Builder;
    use std::fs;

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = Builder::new().prefix("diesel").tempdir().unwrap();

        assert_eq!(
            Err(MigrationError::MigrationDirectoryNotFound(
                dir.path().into()
            )),
            search_for_migrations_directory(dir.path())
        );
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = Builder::new().prefix("diesel").tempdir().unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");

        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(
            Ok(migrations_path),
            search_for_migrations_directory(&temp_path)
        );
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = Builder::new().prefix("diesel").tempdir().unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(
            Ok(migrations_path),
            search_for_migrations_directory(&child_path)
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "duplicate lang item found" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]

#![stable(feature = "core", since = "1.6.0")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(deny(warnings))),
       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]

#![no_core]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(associated_type_defaults)]
#![feature(attr_literals)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(const_int_ops)]
#![feature(core_float)]
#![feature(custom_attribute)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(macro_at_most_once_rep)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(simd_ffi)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(doc_alias)]
#![feature(inclusive_range_methods)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]
#![cfg_attr(stage0, feature(repr_transparent))]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"] pub mod isize;
#[path = "num/i8.rs"]    pub mod i8;
#[path = "num/i16.rs"]   pub mod i16;
#[path = "num/i32.rs"]   pub mod i32;
#[path = "num/i64.rs"]   pub mod i64;
#[path = "num/i128.rs"]  pub mod i128;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]    pub mod u8;
#[path = "num/u16.rs"]   pub mod u16;
#[path = "num/u32.rs"]   pub mod u32;
#[path = "num/u64.rs"]   pub mod u64;
#[path = "num/u128.rs"]  pub mod u128;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;
pub mod hint;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod ascii;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panic;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;
pub mod time;

pub mod unicode;

/* Async */
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod iter_private;
mod nonzero;
mod tuple;
mod unit;

// Pull in the the `coresimd` crate directly into libcore. This is where all the
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
// things like SIMD and such. Note that the actual source for all this lies in a
// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
// a bit wonky.
#[allow(unused_macros)]
macro_rules! test_v16 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v32 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v64 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v128 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v256 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v512 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
#[path = "../stdsimd/coresimd/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
mod coresimd;

#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))]
pub use coresimd::simd;
#[stable(feature = "simd_arch", since = "1.27.0")]
#[cfg(not(stage0))]
pub use coresimd::arch;
<commit_msg>Rollup merge of #52104 - tmccombs:repr_trans_stable, r=Mark-Simulacrum<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always necessary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! # How to use the core library
//!
//! Please note that all of these details are currently not considered stable.
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
//!   dictate the panic message, the file at which panic was invoked, and the
//!   line and column inside the file. It is up to consumers of this core
//!   library to define this panic function; it is only required to never
//!   return. This requires a `lang` attribute named `panic_impl`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//!    compiler. This is often mapped to GCC's personality function, but crates
//!    which do not trigger a panic can be assured that this function is never
//!    called. The `lang` attribute is called `eh_personality`.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.
//
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
// this, both the generated test artifact and the linked libtest (which
// transitively includes libcore) will both define the same set of lang items,
// and this will cause the E0152 "duplicate lang item found" error. See
// discussion in #50466 for details.
//
// This cfg won't affect doc tests.
#![cfg(not(test))]

#![stable(feature = "core", since = "1.6.0")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
       test(no_crate_inject, attr(deny(warnings))),
       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]

#![no_core]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(associated_type_defaults)]
#![feature(attr_literals)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(const_int_ops)]
#![feature(core_float)]
#![feature(custom_attribute)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(macro_at_most_once_rep)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(prelude_import)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(rustc_const_unstable)]
#![feature(simd_ffi)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(unboxed_closures)]
#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(doc_alias)]
#![feature(inclusive_range_methods)]
#![feature(mmx_target_feature)]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
#![feature(powerpc_target_feature)]
#![feature(mips_target_feature)]
#![feature(aarch64_target_feature)]
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]

#[prelude_import]
#[allow(unused)]
use prelude::v1::*;

#[macro_use]
mod macros;

#[macro_use]
mod internal_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"] pub mod isize;
#[path = "num/i8.rs"]    pub mod i8;
#[path = "num/i16.rs"]   pub mod i16;
#[path = "num/i32.rs"]   pub mod i32;
#[path = "num/i64.rs"]   pub mod i64;
#[path = "num/i128.rs"]  pub mod i128;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]    pub mod u8;
#[path = "num/u16.rs"]   pub mod u16;
#[path = "num/u32.rs"]   pub mod u32;
#[path = "num/u64.rs"]   pub mod u64;
#[path = "num/u128.rs"]  pub mod u128;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod ptr;
pub mod hint;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod ascii;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panic;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;
pub mod time;

pub mod unicode;

/* Async */
pub mod future;
pub mod task;

/* Heap memory allocator trait */
#[allow(missing_docs)]
pub mod alloc;

// note: does not need to be public
mod iter_private;
mod nonzero;
mod tuple;
mod unit;

// Pull in the the `coresimd` crate directly into libcore. This is where all the
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
// things like SIMD and such. Note that the actual source for all this lies in a
// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
// a bit wonky.
#[allow(unused_macros)]
macro_rules! test_v16 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v32 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v64 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v128 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v256 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! test_v512 { ($item:item) => {}; }
#[allow(unused_macros)]
macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
#[path = "../stdsimd/coresimd/mod.rs"]
#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
mod coresimd;

#[unstable(feature = "stdsimd", issue = "48556")]
#[cfg(not(stage0))]
pub use coresimd::simd;
#[stable(feature = "simd_arch", since = "1.27.0")]
#[cfg(not(stage0))]
pub use coresimd::arch;
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This example shows some Rust subclasses of C++ classes.

use autocxx::include_cpp;
use autocxx::subclass::{is_subclass, CppSubclass};
use cxx::CxxString;
use std::cell::RefCell;
use std::rc::Rc;

include_cpp! {
    // C++ headers we want to include.
    #include "messages.h"
    // Safety policy. We are marking that this whole C++ inclusion is unsafe
    // which means the functions themselves do not need to be marked
    // as unsafe. Other policies are possible.
    safety!(unsafe)
    // What types and functions we want to generate
    generate!("run_demo")
    generate!("register_cpp_thingies")
    generate!("register_producer")
    generate!("register_displayer")
    // Declare some C++ classes have Rust subclasses.
    subclass!("MessageDisplayer",UwuDisplayer)
    subclass!("MessageDisplayer",BoxDisplayer)
    subclass!("MessageProducer",QuoteProducer)
}

static SHAKESPEARE_QUOTES: [&str; 10] = [
    "All that glitters is not gold",
    "Hell is empty and all the devils are here.",
    "Good night, good night! parting is such sweet sorrow, That I shall say good night till it be morrow.",
    "These violent delights have violent ends...",
    "Something is rotten in the state of Denmark.",
    "Love all, trust a few, do wrong to none.",
    "The lady doth protest too much, methinks.",
    "Brevity is the soul of wit.",
    "Uneasy lies the head that wears a crown.",
    "Now is the winter of our discontent.",
];

// Here's the definition of MessageDisplayer from src/messages.h:
// ```cpp
// class MessageDisplayer {
// public:
//     virtual void display_message(const std::string& message) const = 0;
//     virtual ~MessageDisplayer() {};
// };
// ```
// The following lines define a subclass of MessageDisplayer,
// together with the "subclass!" directive above in the include_cpp!
// macro. See the main function at the bottom for how this subclass
// is instantiated.

#[is_subclass]
#[derive(Default)]
pub struct UwuDisplayer {}

impl UwuDisplayer {
    fn new() -> Rc<RefCell<Self>> {
        // We create and pass an instance of
        // the subclass on the Rust side - that's the first parameter -
        // and also a closure which calls an appropriate C++ constructor for
        // the C++ side peer object. Constructors exist for each superclass
        // constructor, so effectively this is a call to the C++ superclass
        // constructor.
        // The `new_rust_owned` function in the `CppSubclass` trait
        // (which we implement) takes care of gluing the C++ and Rust side
        // objects together.
        Self::new_rust_owned(Self::default(), ffi::UwuDisplayerCpp::make_unique)
    }
}

impl ffi::MessageDisplayer_methods for UwuDisplayer {
    fn display_message(&self, _msg: &CxxString) {
        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
        let uwu = uwuifier::uwuify_str_sse(_msg.to_str().unwrap());
        #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
        let uwu = "uwuification is unavailable for this pwatform :(";
        println!("{}", uwu);
    }
}

// And here's a different pure virtual class.
// Here's its definition from src/messages.h:
// ```cpp
// class MessageProducer {
// public:
//     virtual std::string get_message() const = 0;
//     virtual ~MessageProducer() {};
// };
// ```
// This one is notable only in that the interface of the C++ class
// involves std::string, yet in Rust the subclass uses
// std::unique_ptr<std::string> (for all the normal reasons in autocxx -
// for now, at least, we can't hold non-trivial C++ objects on the Rust stack.)
// All the boxing and unboxing is done automatically by autocxx layers.

#[is_subclass]
#[derive(Default)]
pub struct QuoteProducer {}

impl QuoteProducer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(Self::default(), ffi::QuoteProducerCpp::make_unique)
    }
}

impl ffi::MessageProducer_methods for QuoteProducer {
    fn get_message(&self) -> cxx::UniquePtr<CxxString> {
        use ffi::ToCppString;
        SHAKESPEARE_QUOTES[fastrand::usize(0..SHAKESPEARE_QUOTES.len())].into_cpp()
    }
}

// Here's another subclass of the same 'displayer' class.
// This one is more complex in two ways.
//
// First, we actually want to store some data here in our subclass.
// That means we can't just allocate ourselves with Default::default().
// And that means we need to be aware of the cpp_peer field which is
// added by the #[subclass] macro.
//
// Second, we're going to simulate the observer/listener type pattern
// in C++ where a const* is used to send messages around a codebase yet
// recipients need to react by mutating themselves or otherwise actively
// doing stuff. In C++ you'd probably need a const_cast. Here we use
// interior mutability.

#[is_subclass]
pub struct BoxDisplayer {
    message_count: RefCell<usize>,
}

impl BoxDisplayer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(
            Self {
                // As we're allocating this class ourselves instead of using [`Default`]
                // we need to initialize the `cpp_peer` member ourselves. This member is
                // inserted by the `#[is_subclass]` annotation. autocxx will
                // later use this to store a pointer back to the C++ peer.
                cpp_peer: Default::default(),
                message_count: RefCell::new(1usize),
            },
            ffi::BoxDisplayerCpp::make_unique,
        )
    }
}

impl ffi::MessageDisplayer_methods for BoxDisplayer {
    fn display_message(&self, msg: &CxxString) {
        let msg = textwrap::fill(msg.to_str().unwrap(), 70);
        let horz_line = std::iter::repeat("#").take(74).collect::<String>();
        println!("{}", horz_line);
        let msgmsg = format!("Message {}", self.message_count.borrow());
        self.message_count.replace_with(|old| *old + 1usize);
        println!("# {:^70} #", msgmsg);
        println!("{}", horz_line);
        for l in msg.lines() {
            println!("# {:^70} #", l);
        }
        println!("{}", horz_line);
    }
}

fn main() {
    // Register some C++ example classes.
    ffi::register_cpp_thingies();
    // Create a message displayer.
    let uwu = UwuDisplayer::new();
    // The next line casts the &UwuDisplayerCpp to a &MessageDisplayer.
    ffi::register_displayer(uwu.as_ref().borrow().as_ref());
    // Same again for the next message displayer object.
    // In each case, we could have said `new_cpp_owned` instead, which would
    // have given us a cxx::UniquePtr that we could have passed to C++.
    let boxd = BoxDisplayer::new();
    ffi::register_displayer(boxd.as_ref().borrow().as_ref());
    // Let's register a producer too.
    let shakespeare = QuoteProducer::new();
    ffi::register_producer(shakespeare.as_ref().borrow().as_ref());
    ffi::run_demo();
    ffi::run_demo();
}
<commit_msg>Comment updates.<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This example shows some Rust subclasses of C++ classes.

use autocxx::include_cpp;
use autocxx::subclass::{is_subclass, CppSubclass};
use cxx::CxxString;
use std::cell::RefCell;
use std::rc::Rc;

include_cpp! {
    #include "messages.h"
    safety!(unsafe)
    // What types and functions we want to generate
    generate!("run_demo")
    generate!("register_cpp_thingies")
    generate!("register_producer")
    generate!("register_displayer")
    // Declare some C++ classes have Rust subclasses.
    subclass!("MessageDisplayer",UwuDisplayer)
    subclass!("MessageDisplayer",BoxDisplayer)
    subclass!("MessageProducer",QuoteProducer)
}

static SHAKESPEARE_QUOTES: [&str; 10] = [
    "All that glitters is not gold",
    "Hell is empty and all the devils are here.",
    "Good night, good night! parting is such sweet sorrow, That I shall say good night till it be morrow.",
    "These violent delights have violent ends...",
    "Something is rotten in the state of Denmark.",
    "Love all, trust a few, do wrong to none.",
    "The lady doth protest too much, methinks.",
    "Brevity is the soul of wit.",
    "Uneasy lies the head that wears a crown.",
    "Now is the winter of our discontent.",
];

// Here's the definition of MessageDisplayer from src/messages.h:
// ```cpp
// class MessageDisplayer {
// public:
//     virtual void display_message(const std::string& message) const = 0;
//     virtual ~MessageDisplayer() {};
// };
// ```
// The following lines define a subclass of MessageDisplayer,
// together with the "subclass!" directive above in the include_cpp!
// macro. See the main function at the bottom for how this subclass
// is instantiated.

#[is_subclass]
#[derive(Default)]
pub struct UwuDisplayer {}

impl UwuDisplayer {
    fn new() -> Rc<RefCell<Self>> {
        // We create and pass an instance of
        // the subclass on the Rust side - that's the first parameter -
        // and also a closure which calls an appropriate C++ constructor for
        // the C++ side peer object. Constructors exist for each superclass
        // constructor, so effectively this is a call to the C++ superclass
        // constructor.
        // The `new_rust_owned` function in the `CppSubclass` trait
        // (which we implement) takes care of gluing the C++ and Rust side
        // objects together.
        // We could have said `new_cpp_owned` instead, which would
        // have given us a cxx::UniquePtr that we could have passed to C++.
        Self::new_rust_owned(Self::default(), ffi::UwuDisplayerCpp::make_unique)
    }
}

impl ffi::MessageDisplayer_methods for UwuDisplayer {
    fn display_message(&self, _msg: &CxxString) {
        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
        let uwu = uwuifier::uwuify_str_sse(_msg.to_str().unwrap());
        #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
        let uwu = "uwuification is unavailable for this pwatform :(";
        println!("{}", uwu);
    }
}

// And here's a different pure virtual class.
// Here's its definition from src/messages.h:
// ```cpp
// class MessageProducer {
// public:
//     virtual std::string get_message() const = 0;
//     virtual ~MessageProducer() {};
// };
// ```
// This one is notable only in that the interface of the C++ class
// involves std::string, yet in Rust the subclass uses
// std::unique_ptr<std::string> (for all the normal reasons in autocxx -
// for now, at least, we can't hold non-trivial C++ objects on the Rust stack.)
// All the boxing and unboxing is done automatically by autocxx layers.

#[is_subclass]
#[derive(Default)]
pub struct QuoteProducer {}

impl QuoteProducer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(Self::default(), ffi::QuoteProducerCpp::make_unique)
    }
}

impl ffi::MessageProducer_methods for QuoteProducer {
    fn get_message(&self) -> cxx::UniquePtr<CxxString> {
        use ffi::ToCppString;
        SHAKESPEARE_QUOTES[fastrand::usize(0..SHAKESPEARE_QUOTES.len())].into_cpp()
    }
}

// Here's another subclass of the same 'displayer' class.
// This one is more complex in two ways.
//
// First, we actually want to store some data here in our subclass.
// That means we can't just allocate ourselves with Default::default().
// And that means we need to be aware of the cpp_peer field which is
// added by the #[subclass] macro.
//
// Second, we're going to simulate the observer/listener type pattern
// in C++ where a const* is used to send messages around a codebase yet
// recipients need to react by mutating themselves or otherwise actively
// doing stuff. In C++ you'd probably need a const_cast. Here we use
// interior mutability.

#[is_subclass]
pub struct BoxDisplayer {
    message_count: RefCell<usize>,
}

impl BoxDisplayer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(
            Self {
                // As we're allocating this class ourselves instead of using [`Default`]
                // we need to initialize the `cpp_peer` member ourselves. This member is
                // inserted by the `#[is_subclass]` annotation. autocxx will
                // later use this to store a pointer back to the C++ peer.
                cpp_peer: Default::default(),
                message_count: RefCell::new(1usize),
            },
            ffi::BoxDisplayerCpp::make_unique,
        )
    }
}

impl ffi::MessageDisplayer_methods for BoxDisplayer {
    fn display_message(&self, msg: &CxxString) {
        let msg = textwrap::fill(msg.to_str().unwrap(), 70);
        let horz_line = std::iter::repeat("#").take(74).collect::<String>();
        println!("{}", horz_line);
        let msgmsg = format!("Message {}", self.message_count.borrow());
        self.message_count.replace_with(|old| *old + 1usize);
        println!("# {:^70} #", msgmsg);
        println!("{}", horz_line);
        for l in msg.lines() {
            println!("# {:^70} #", l);
        }
        println!("{}", horz_line);
    }
}

fn main() {
    ffi::register_cpp_thingies();
    let uwu = UwuDisplayer::new();
    // The next line casts the &UwuDisplayerCpp to a &MessageDisplayer.
    ffi::register_displayer(uwu.as_ref().borrow().as_ref());
    let boxd = BoxDisplayer::new();
    ffi::register_displayer(boxd.as_ref().borrow().as_ref());
    let shakespeare = QuoteProducer::new();
    ffi::register_producer(shakespeare.as_ref().borrow().as_ref());
    ffi::run_demo();
    ffi::run_demo();
}
<|endoftext|>


<commit_before>extern crate sdl;

struct Screen {
    surface sdl::video::Surface,
    on_color : sdl::video::Color,
    off_color :sdl::video::Color,
    x_max :uint,
    y_max :uint

}

impl Screen {

    fn new(width :uint, height :uint, x_max :uint, y_max :uint) -> Screen {
        sdl::init([sdl::InitVideo]);
        sdl::wm::set_caption("CHIP-8 Emulator");

        let surface =
            match sdl::video::set_video_mode(width, height, 32,
            [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {

                Ok(screen) => screen,
                Err(err) => fail!("failed to set video mode: {}", err)
            };

        Screen { surface:surface,
                 on_color:sdl::video::Color  { r:0, g:255, b:0},
                 off_color:sdl::video::Color { r:0, g:0,   b:0},
                 x_max:x_max,
                 y_max:y_max
               }
        }
   }

    fn draw_pix(&mut self, x_pos :uint, y_pos :uint, set:bool) {
        let x_unit = screen.ll.w/screen.x_max;
        let y_uint = screen.ll.h/screen.y_max;

        self.screen.fill_rect(Some(sdl:Rect {
            x: x_pos * x_unit,
            y: y_pos * y_unit,
            w: x_unit,
            h: y_unit,
        }), match set { true => self.on_color, false => self.off_color });
    }

    pub fn clear_screen(&mut self) {
        self.screen.fill_rect(Some(sdl:Rect {
            x: 0,
            y: 0,
            w: self.ll.w,
            h: self.ll.h,
        }), self.off_color);
    }

}

/*
  // Note: You'll want to put this and the flip call inside the main loop
  // but we don't as to not startle epileptics
  for i in range(0, 10) {
      for j in range(0, 10) {
          screen.fill_rect(Some(sdl::Rect {
              x: (i as i16) * 800 / 10,
              y: (j as i16) * 600 / 10,
              w: 800 / 10,
              h: 600 / 10
          }), rng.gen::<sdl::video::Color>());
      }
  }

  screen.flip();

  'main : loop {
      'event : loop {
          match sdl::event::poll_event() {
              sdl::event::QuitEvent => break 'main,
              sdl::event::NoEvent => break 'event,
              sdl::event::KeyEvent(k, _, _, _)
                  if k == sdl::event::EscapeKey
                      => break 'main,
              _ => {}
          }
      }
  }

  sdl::quit();
}
*/
<commit_msg>Corrections to sdl_graphics<commit_after>#![crate_id = "graphics_impl"]
extern crate sdl;

struct Screen {
    surface :sdl::video::Surface,
    on_color : sdl::video::Color,
    off_color :sdl::video::Color,
    width: uint,
    height: uint,
    x_max :uint,
    y_max :uint

}

impl Screen {

    fn new(width :int, height :int, x_max :uint, y_max :uint) -> Screen {
        sdl::init([sdl::InitVideo]);
        sdl::wm::set_caption("CHIP-8 Emulator", "sdl");

        let surface =
            match sdl::video::set_video_mode(width, height, 32,
            [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {

                Ok(screen) => screen,
                Err(err) => fail!("failed to set video mode: {}", err)
            };

        Screen { surface:surface,
                 on_color:  sdl::video::RGB(0, 255, 0), /* Green */
                 off_color: sdl::video::RGB(0, 0,   0), /* Black */
                 width:width as uint,
                 height:height as uint,
                 x_max:x_max,
                 y_max:y_max
               }
        }

    fn draw_pix(&mut self, x_pos :int, y_pos :int, set:bool) {
        let x_unit = (self.width/self.x_max) as u16;
        let y_unit = (self.height/self.y_max) as u16;

        self.surface.fill_rect(Some(sdl::Rect {
            x: x_pos as i16 * x_unit as i16,
            y: y_pos as i16 * y_unit as i16,
            w: x_unit,
            h: y_unit,
        }), match set { true => self.on_color, false => self.off_color });
    }

    pub fn clear_screen(&mut self) {
        self.surface.fill_rect(Some(sdl::Rect {
            x: 0,
            y: 0,
            w: self.width as u16,
            h: self.height as u16,
        }), self.off_color);
    }

}

/*
  // Note: You'll want to put this and the flip call inside the main loop
  // but we don't as to not startle epileptics
  for i in range(0, 10) {
      for j in range(0, 10) {
          screen.fill_rect(Some(sdl::Rect {
              x: (i as i16) * 800 / 10,
              y: (j as i16) * 600 / 10,
              w: 800 / 10,
              h: 600 / 10
          }), rng.gen::<sdl::video::Color>());
      }
  }

  screen.flip();

  'main : loop {
      'event : loop {
          match sdl::event::poll_event() {
              sdl::event::QuitEvent => break 'main,
              sdl::event::NoEvent => break 'event,
              sdl::event::KeyEvent(k, _, _, _)
                  if k == sdl::event::EscapeKey
                      => break 'main,
              _ => {}
          }
      }
  }

  sdl::quit();
}
*/
<|endoftext|>


<commit_before>extern mod extra;
use std::vec::from_elem;
use grid::{Row, Column, alive, dead, Cell, Grid};
mod grid;

/****************************************************************************
 * Something to say Ben??
 ****************************************************************************/

/*
 * Constructs an immutable grid from the contents of an array of strings.
 * The grid is declared mutable, and mutated only inside this fn.
*/
pub fn build_from_file_contents(file_contents: ~[~str]) -> Grid
{
  let height = file_contents.len();
  assert!(height > 0u);
  let width = file_contents[0].len();
  let cells = from_elem(width, Cell { value: alive } );

  let mut result = Grid {
      inner: from_elem(height, cells.clone())
  };
  for row in range(0, height) {
    for column in range(0, width) {
      let file_value: char = file_contents[row][column] as char;
      let cell_value = match file_value {
        'o' => alive,
        '.' => dead,
         _  => fail!("Unexpected cell value found in file.")
      };
      result.inner[row][column] = Cell { value: cell_value };
   }
  }
  return result;
} // fn build_from_file_contents

enum direction {
  above, below, left, right
}  // enum CellValue

/*
  Calculates the neighbor's position given the inputs.
*/
fn neighbor_pos(Row(row): Row, Column(column): Column, dir: direction)
    -> (Row, Column)
{
  return match dir {
    above => (Row(row - 1), Column(column)),
    below => (Row(row + 1), Column(column)),
    right => (Row(row), Column(column + 1)),
    left  => (Row(row), Column(column - 1))
  };
}  // fn neighbor_pos

/*
 * Returns a count for how many neighbors of a cell in the grid
 * are alive.
*/
pub fn count_neighbors(row: Row, column: Column, grid: &Grid)
    -> uint
{
  let (same_row, left_column)  = neighbor_pos(row, column, left);
  let (same_row, right_column) = neighbor_pos(row, column, right);
  let (above_row, same_column) = neighbor_pos(row, column, above);
  let (below_row, same_column) = neighbor_pos(row, column, below);

  let (above_left_row, above_left_column) = neighbor_pos(above_row, same_column, left);
  let (above_right_row, above_right_column) = neighbor_pos(above_row, same_column, right);
  let (below_left_row, below_left_column) = neighbor_pos(below_row, same_column, left);
  let (below_right_row, below_right_column) = neighbor_pos(below_row, same_column, right);

  let c0 = grid.cell_alive(same_row, left_column);
  let c1 = grid.cell_alive(same_row, right_column);
  let c2 = grid.cell_alive(above_row, same_column);
  let c3 = grid.cell_alive(below_row, same_column);

  let c4 = grid.cell_alive(above_left_row, above_left_column);
  let c5 = grid.cell_alive(above_right_row, above_right_column);
  let c6 = grid.cell_alive(below_left_row, below_left_column);
  let c7 = grid.cell_alive(below_right_row, below_right_column);
  return c0 + c1 + c2 + c3 + c4 + c5 + c6 + c7;
}

/*pub fn print_neighbor_count(grid: &Grid) {
  let x = grid.inner.len();
  for row in range(0, x) {
    for column in range(0, x) {
      let r = Row(row);
      let c = Column(column);
      let n = count_neighbors(r, c, grid);
      print!("{:u}", n);
    }
    println!("");
  }
}  // fn print_neighbor_count
*/

// 1)Any live cell with fewer than two live neighbours dies, as if caused by
// under-population.
// 2) Any live cell with two or three live neighbours lives on to the next
// generation.
// 3) Any live cell with more than three live neighbours dies, as if by
// overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as
// if by reproduction.
pub fn build_from_grid(prevg: &Grid) -> Grid
{
  let mut result = prevg.clone();
  for row in range(0, prevg.height()) {
    for column in range(0, prevg.width()) {
      let ncount = count_neighbors(Row(row), Column(column), prevg);
      result.inner[row][column] = Cell { value:
        match (prevg.inner[row][column].value, ncount) {
          (dead, 3)     => alive,
          (alive, 2..3) => alive,
          _             => dead
        }
      };
    }
  }
  return result;
}  // fn build_from_grid
<commit_msg>Trying to reduce nesting here ..<commit_after>extern mod extra;
use std::vec::from_elem;
use grid::{Row, Column, alive, dead, Cell, Grid};
mod grid;

/****************************************************************************
 * Something to say Ben??
 ****************************************************************************/

/*
 * Constructs an immutable grid from the contents of an array of strings.
 * The grid is declared mutable, and mutated only inside this fn.
*/
pub fn build_from_file_contents(file_contents: ~[~str]) -> Grid
{
  let height = file_contents.len();
  assert!(height > 0u);
  let width = file_contents[0].len();
  let cells = from_elem(width, Cell { value: alive } );

  let mut result = Grid {
      inner: from_elem(height, cells.clone())
  };
  for row in range(0, height) {
    for column in range(0, width) {
      let file_value: char = file_contents[row][column] as char;
      let cell_value = match file_value {
        'o' => alive,
        '.' => dead,
         _  => fail!("Unexpected cell value found in file.")
      };
      result.inner[row][column] = Cell { value: cell_value };
   }
  }
  return result;
} // fn build_from_file_contents

enum direction {
  above, below, left, right
}  // enum CellValue

/*
  Calculates the neighbor's position given the inputs.
*/
fn neighbor_pos(Row(row): Row, Column(column): Column, dir: direction)
    -> (Row, Column)
{
  return match dir {
    above => (Row(row - 1), Column(column)),
    below => (Row(row + 1), Column(column)),
    right => (Row(row), Column(column + 1)),
    left  => (Row(row), Column(column - 1))
  };
}  // fn neighbor_pos

/*
 * Returns a count for how many neighbors of a cell in the grid
 * are alive.
*/
pub fn count_neighbors(row: Row, column: Column, grid: &Grid)
    -> uint
{
  let (same_row, left_column)  = neighbor_pos(row, column, left);
  let (same_row, right_column) = neighbor_pos(row, column, right);
  let (above_row, same_column) = neighbor_pos(row, column, above);
  let (below_row, same_column) = neighbor_pos(row, column, below);

  let (above_left_row, above_left_column) = neighbor_pos(above_row, same_column, left);
  let (above_right_row, above_right_column) = neighbor_pos(above_row, same_column, right);
  let (below_left_row, below_left_column) = neighbor_pos(below_row, same_column, left);
  let (below_right_row, below_right_column) = neighbor_pos(below_row, same_column, right);

  let c0 = grid.cell_alive(same_row, left_column);
  let c1 = grid.cell_alive(same_row, right_column);
  let c2 = grid.cell_alive(above_row, same_column);
  let c3 = grid.cell_alive(below_row, same_column);

  let c4 = grid.cell_alive(above_left_row, above_left_column);
  let c5 = grid.cell_alive(above_right_row, above_right_column);
  let c6 = grid.cell_alive(below_left_row, below_left_column);
  let c7 = grid.cell_alive(below_right_row, below_right_column);
  return c0 + c1 + c2 + c3 + c4 + c5 + c6 + c7;
}

/*pub fn print_neighbor_count(grid: &Grid) {
  let x = grid.inner.len();
  for row in range(0, x) {
    for column in range(0, x) {
      let r = Row(row);
      let c = Column(column);
      let n = count_neighbors(r, c, grid);
      print!("{:u}", n);
    }
    println!("");
  }
}  // fn print_neighbor_count
*/

// 1)Any live cell with fewer than two live neighbours dies, as if caused by
// under-population.
// 2) Any live cell with two or three live neighbours lives on to the next
// generation.
// 3) Any live cell with more than three live neighbours dies, as if by
// overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as
// if by reproduction.
pub fn build_from_grid(prevg: &Grid) -> Grid
{
  let cell_value = |row: uint, column: uint| {
    let ncount = count_neighbors(Row(row), Column(column), prevg);
    let cv = match (prevg.inner[row][column].value, ncount) {
      (dead, 3)       => alive,
      (alive, 2..3)   => alive,
      _               => dead
    };
    return Cell { value: cv };
  };
  let mut result = prevg.clone();
  for row in range(0, prevg.height()) {
    for column in range(0, prevg.width()) {
      result.inner[row][column] = cell_value(row, column);
    }
  }
  return result;
}  // fn build_from_grid
<|endoftext|>