<commit_before>#[macro_use]
extern crate rocket;

mod database;
mod domain;

use std::path::Path;

use chrono::{DateTime, SecondsFormat, Utc};
use dotenv::dotenv;
use rocket::data::ToByteUnit;
use rocket::outcome::{try_outcome, Outcome};
use rocket::request::FromRequest;
use rocket::request::{self, FromParam};
use rocket::serde::json::Json;
use rocket::serde::Serialize;
use rocket::{Data, Request};
use rocket_db_pools::{Connection, Database};
use tokio::fs::File;

use database::Db;
use domain::entities::{ApiKeyId, DropId, User, UserId};
use domain::ApiKeyValue;

impl<'a> FromParam<'a> for DropId {
    type Error = String;

    fn from_param(param: &'a str) -> Result<Self, Self::Error> {
        DropId::try_from(param)
            .map_err(|err| format!("failed to parse '{}' as a drop ID: {}", param, err))
    }
}

impl<'a> FromParam<'a> for UserId {
    type Error = String;

    fn from_param(param: &'a str) -> Result<Self, Self::Error> {
        UserId::try_from(param)
            .map_err(|err| format!("failed to parse '{}' as a user ID: {}", param, err))
    }
}

pub struct ApiKeyBearer {
    user: User,
}

struct ApiKeyLookup {
    pub id: String,
    pub username: String,
    pub full_name: Option<String>,
}

#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKeyBearer {
    type Error = String;

    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
        let mut db = try_outcome!(req
            .guard::<Connection<Db>>()
            .await
            .map_failure(|f| (f.0, "failed to acquire database connection".to_string())));

        match req.headers().get_one("Authorization") {
            Some(authorization) => {
                let token = authorization.replace("Bearer ", "");

                let api_key = sqlx::query_as!(
                    ApiKeyLookup,
                    "select user.id, user.username, user.full_name from api_key
                     inner join user on user.id = api_key.user_id
                     where api_key.value = $1
                    ",
                    token
                )
                .fetch_one(&mut *db)
                .await
                .unwrap();

                Outcome::Success(ApiKeyBearer {
                    user: User {
                        id: UserId::try_from(api_key.id).unwrap(),
                        username: api_key.username,
                        full_name: api_key.full_name,
                    },
                })
            }
            _ => Outcome::Forward(()),
        }
    }
}

#[get("/")]
async fn index() -> &'static str {
    "滴"
}

#[post("/drops", data = "<drop>")]
async fn upload_drop(_bearer: ApiKeyBearer, drop: Data<'_>) -> std::io::Result<String> {
    let id = DropId::new();

    let upload_dir = "upload";
    let filepath = Path::new(upload_dir).join(id.unprefixed());

    drop.open(2.mebibytes()).into_file(filepath).await?;

    Ok(id.to_string())
}

#[get("/drops/<id>")]
async fn get_drop(id: DropId) -> Option<File> {
    let upload_dir = "upload";
    let filepath = Path::new(upload_dir).join(id.unprefixed());

    File::open(&filepath).await.ok()
}

#[derive(Debug, Serialize)]
pub struct DropMetadata {
    pub created_at: DateTime<Utc>,
    pub size_in_bytes: u64,
}

#[get("/drops/<id>/meta")]
async fn get_drop_metadata(id: DropId) -> Json<DropMetadata> {
    let upload_dir = "upload";
    let filepath = Path::new(upload_dir).join(id.unprefixed());

    let file = File::open(&filepath).await.unwrap();
    let file_metadata = File::metadata(&file).await.unwrap();

    Json(DropMetadata {
        created_at: id.created_at(),
        size_in_bytes: file_metadata.len(),
    })
}

#[derive(Debug, Serialize)]
pub struct UserJson {
    pub id: String,
    pub username: String,
    pub full_name: Option<String>,
}

#[post("/users")]
async fn create_user(mut db: Connection<Db>) -> database::Result<Json<UserJson>> {
    let id = UserId::new();

    let username = "maxdeviant";
    let full_name = "Marshall Bowers";

    let unprefixed_id = id.unprefixed();
    let now = Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true);

    sqlx::query!(
        "insert into user (id, created_at, updated_at, username, full_name) values (?, ?, ?, ?, ?)",
        unprefixed_id,
        now,
        now,
        username,
        full_name
    )
    .execute(&mut *db)
    .await?;

    Ok(Json(UserJson {
        id: id.to_string(),
        username: username.to_string(),
        full_name: Some(full_name.to_string()),
    }))
}

#[derive(Debug, Serialize)]
pub struct ApiKeyJson {
    pub id: String,
    pub value: String,
}

#[post("/keys")]
async fn generate_api_key(
    bearer: ApiKeyBearer,
    mut db: Connection<Db>,
) -> database::Result<Json<ApiKeyJson>> {
    let id = ApiKeyId::new();
    let value = ApiKeyValue::new();

    let unprefixed_id = id.unprefixed();
    let unprefixed_user_id = bearer.user.id.unprefixed();
    let key_value = value.to_string();
    let now = Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true);

    sqlx::query!(
        "insert into api_key (id, created_at, updated_at, user_id, value) values (?, ?, ?, ?, ?)",
        unprefixed_id,
        now,
        now,
        unprefixed_user_id,
        key_value
    )
    .execute(&mut *db)
    .await?;

    Ok(Json(ApiKeyJson {
        id: id.to_string(),
        value: value.to_string(),
    }))
}

#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
    dotenv().ok();

    let rocket = rocket::build()
        .mount(
            "/",
            routes![index, upload_drop, get_drop, get_drop_metadata,],
        )
        .mount("/x/", routes![create_user, generate_api_key])
        .attach(Db::init())
        .ignite()
        .await?;

    let _ = rocket.launch().await?;

    Ok(())
}
<commit_msg>Add ability to provision a root user<commit_after>#[macro_use]
extern crate rocket;

mod database;
mod domain;

use std::path::Path;

use chrono::{DateTime, SecondsFormat, Utc};
use dotenv::dotenv;
use rocket::data::ToByteUnit;
use rocket::outcome::{try_outcome, Outcome};
use rocket::request::FromRequest;
use rocket::request::{self, FromParam};
use rocket::serde::json::Json;
use rocket::serde::Serialize;
use rocket::{Data, Request};
use rocket_db_pools::{Connection, Database};
use tokio::fs::File;

use database::Db;
use domain::entities::{ApiKeyId, DropId, User, UserId};
use domain::ApiKeyValue;

impl<'a> FromParam<'a> for DropId {
    type Error = String;

    fn from_param(param: &'a str) -> Result<Self, Self::Error> {
        DropId::try_from(param)
            .map_err(|err| format!("failed to parse '{}' as a drop ID: {}", param, err))
    }
}

impl<'a> FromParam<'a> for UserId {
    type Error = String;

    fn from_param(param: &'a str) -> Result<Self, Self::Error> {
        UserId::try_from(param)
            .map_err(|err| format!("failed to parse '{}' as a user ID: {}", param, err))
    }
}

pub struct ApiKeyBearer {
    user: User,
}

struct ApiKeyLookup {
    pub id: String,
    pub username: String,
    pub full_name: Option<String>,
}

#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKeyBearer {
    type Error = String;

    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
        let mut db = try_outcome!(req
            .guard::<Connection<Db>>()
            .await
            .map_failure(|f| (f.0, "failed to acquire database connection".to_string())));

        match req.headers().get_one("Authorization") {
            Some(authorization) => {
                let token = authorization.replace("Bearer ", "");

                let api_key = sqlx::query_as!(
                    ApiKeyLookup,
                    "
                    select user.id, user.username, user.full_name from api_key
                    inner join user on user.id = api_key.user_id
                    where api_key.value = $1
                    ",
                    token
                )
                .fetch_one(&mut *db)
                .await
                .unwrap();

                Outcome::Success(ApiKeyBearer {
                    user: User {
                        id: UserId::try_from(api_key.id).unwrap(),
                        username: api_key.username,
                        full_name: api_key.full_name,
                    },
                })
            }
            _ => Outcome::Forward(()),
        }
    }
}

#[get("/")]
async fn index() -> &'static str {
    "滴"
}

#[post("/drops", data = "<drop>")]
async fn upload_drop(_bearer: ApiKeyBearer, drop: Data<'_>) -> std::io::Result<String> {
    let id = DropId::new();

    let upload_dir = "upload";
    let filepath = Path::new(upload_dir).join(id.unprefixed());

    drop.open(2.mebibytes()).into_file(filepath).await?;

    Ok(id.to_string())
}

#[get("/drops/<id>")]
async fn get_drop(id: DropId) -> Option<File> {
    let upload_dir = "upload";
    let filepath = Path::new(upload_dir).join(id.unprefixed());

    File::open(&filepath).await.ok()
}

#[derive(Debug, Serialize)]
pub struct DropMetadata {
    pub created_at: DateTime<Utc>,
    pub size_in_bytes: u64,
}

#[get("/drops/<id>/meta")]
async fn get_drop_metadata(id: DropId) -> Json<DropMetadata> {
    let upload_dir = "upload";
    let filepath = Path::new(upload_dir).join(id.unprefixed());

    let file = File::open(&filepath).await.unwrap();
    let file_metadata = File::metadata(&file).await.unwrap();

    Json(DropMetadata {
        created_at: id.created_at(),
        size_in_bytes: file_metadata.len(),
    })
}

#[derive(Debug, Serialize)]
pub struct UserJson {
    pub id: String,
    pub username: String,
    pub full_name: Option<String>,
}

#[post("/users")]
async fn create_user(mut db: Connection<Db>) -> database::Result<Json<UserJson>> {
    let id = UserId::new();

    let username = "maxdeviant";
    let full_name = "Marshall Bowers";

    let unprefixed_id = id.unprefixed();
    let now = Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true);

    sqlx::query!(
        "
        insert into user (id, created_at, updated_at, username, full_name)
        values (?, ?, ?, ?, ?)
        ",
        unprefixed_id,
        now,
        now,
        username,
        full_name
    )
    .execute(&mut *db)
    .await?;

    Ok(Json(UserJson {
        id: id.to_string(),
        username: username.to_string(),
        full_name: Some(full_name.to_string()),
    }))
}

#[derive(Debug, Serialize)]
pub struct ApiKeyJson {
    pub id: String,
    pub value: String,
}

#[post("/keys")]
async fn generate_api_key(
    bearer: ApiKeyBearer,
    mut db: Connection<Db>,
) -> database::Result<Json<ApiKeyJson>> {
    let id = ApiKeyId::new();
    let value = ApiKeyValue::new();

    let unprefixed_id = id.unprefixed();
    let unprefixed_user_id = bearer.user.id.unprefixed();
    let key_value = value.to_string();
    let now = Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true);

    sqlx::query!(
        "
        insert into api_key (id, created_at, updated_at, user_id, value)
        values (?, ?, ?, ?, ?)
        ",
        unprefixed_id,
        now,
        now,
        unprefixed_user_id,
        key_value
    )
    .execute(&mut *db)
    .await?;

    Ok(Json(ApiKeyJson {
        id: id.to_string(),
        value: value.to_string(),
    }))
}

async fn ensure_root_user_exists() {
    use sqlx::{Connection, SqliteConnection};

    let root_username = env!("ROOT_USERNAME");
    let root_api_key = env!("ROOT_API_KEY");

    let database_url = env!("DATABASE_URL");
    let mut connection = SqliteConnection::connect(database_url).await.unwrap();

    let user_id = UserId::new();
    let unprefixed_user_id = user_id.unprefixed();
    let now = Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true);

    #[derive(Debug)]
    struct RootUser {
        id: String,
    }

    let root_user = sqlx::query_as!(
        RootUser,
        "
        insert into user (id, created_at, updated_at, username)
        values (?, ?, ?, ?)
        -- This is a no-op update just so we can get the `id` returned.
        on conflict (username) do update set updated_at = updated_at
        returning id
        ",
        unprefixed_user_id,
        now,
        now,
        root_username
    )
    .fetch_one(&mut connection)
    .await
    .expect("failed to insert root user");

    println!("Root user: {:?}", root_user);

    let key_id = ApiKeyId::new();
    let unprefixed_key_id = key_id.unprefixed();
    let now = Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true);

    sqlx::query!(
        "
        insert into api_key (id, created_at, updated_at, user_id, value)
        values (?, ?, ?, ?, ?)
        on conflict (value) do nothing
        ",
        unprefixed_key_id,
        now,
        now,
        root_user.id,
        root_api_key
    )
    .execute(&mut connection)
    .await
    .unwrap();
}

#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
    dotenv().ok();

    ensure_root_user_exists().await;

    let rocket = rocket::build()
        .mount(
            "/",
            routes![index, upload_drop, get_drop, get_drop_metadata,],
        )
        .mount("/x/", routes![create_user, generate_api_key])
        .attach(Db::init())
        .ignite()
        .await?;

    let _ = rocket.launch().await?;

    Ok(())
}
<|endoftext|>


<commit_before>pub mod internal {
    pub struct r#mod;

    /// See [name], [other name]
    ///
    /// [name]: mod
    /// [other name]: ../internal/struct.mod.html
    // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//a[@href="../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'name'
    // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//a[@href="../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'other name'
    pub struct B;
}

/// See [name].
///
/// [name]: internal::mod
// @has 'raw_ident_eliminate_r_hashtag/struct.A.html' '//a[@href="../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'name'
struct A;
<commit_msg>Ignore tidy linelength<commit_after>// ignore-tidy-linelength

pub mod internal {
    pub struct r#mod;

    /// See [name], [other name]
    ///
    /// [name]: mod
    /// [other name]: ../internal/struct.mod.html
    // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//a[@href="../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'name'
    // @has 'raw_ident_eliminate_r_hashtag/internal/struct.B.html' '//a[@href="../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'other name'
    pub struct B;
}

/// See [name].
///
/// [name]: internal::mod
// @has 'raw_ident_eliminate_r_hashtag/struct.A.html' '//a[@href="../raw_ident_eliminate_r_hashtag/internal/struct.mod.html"]' 'name'
struct A;
<|endoftext|>


<commit_before>use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::{Parse, ParseValue};
use crate::property_defs::ColorInterpolationFilters;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Input, Primitive, PrimitiveParams, ResolvedPrimitive};

/// Enumeration of the possible blending modes.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum Mode {
    Normal,
    Multiply,
    Screen,
    Darken,
    Lighten,
    Overlay,
    ColorDodge,
    ColorBurn,
    HardLight,
    SoftLight,
    Difference,
    Exclusion,
    HslHue,
    HslSaturation,
    HslColor,
    HslLuminosity,
}

enum_default!(Mode, Mode::Normal);

/// The `feBlend` filter primitive.
pub struct FeBlend {
    base: Primitive,
    in1: Input,
    in2: Input,
    mode: Mode,
}

/// Resolved `feBlend` primitive for rendering.
pub struct Blend {
    in1: Input,
    in2: Input,
    mode: Mode,
    color_interpolation_filters: ColorInterpolationFilters,
}

impl Default for FeBlend {
    /// Constructs a new `Blend` with empty properties.
    #[inline]
    fn default() -> FeBlend {
        FeBlend {
            base: Default::default(),
            in1: Default::default(),
            in2: Default::default(),
            mode: Mode::default(),
        }
    }
}

impl SetAttributes for FeBlend {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        let (in1, in2) = self.base.parse_two_inputs(attrs)?;
        self.in1 = in1;
        self.in2 = in2;

        for (attr, value) in attrs.iter() {
            if let expanded_name!("", "mode") = attr.expanded() {
                self.mode = attr.parse(value)?;
            }
        }

        Ok(())
    }
}

impl Blend {
    pub fn render(
        &self,
        primitive: &ResolvedPrimitive,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input_1 = ctx.get_input(
            acquired_nodes,
            draw_ctx,
            &self.in1,
            self.color_interpolation_filters,
        )?;
        let input_2 = ctx.get_input(
            acquired_nodes,
            draw_ctx,
            &self.in2,
            self.color_interpolation_filters,
        )?;
        let bounds = primitive
            .get_bounds(ctx)?
            .add_input(&input_1)
            .add_input(&input_2)
            .into_irect(ctx, draw_ctx);

        let surface = input_1.surface().compose(
            input_2.surface(),
            bounds,
            cairo::Operator::from(self.mode),
        )?;

        Ok(FilterResult {
            name: primitive.result.clone(),
            output: FilterOutput { surface, bounds },
        })
    }
}

impl FilterEffect for FeBlend {
    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
        let cascaded = CascadedValues::new_from_node(node);
        let values = cascaded.get();

        Ok((
            self.base.clone(),
            PrimitiveParams::Blend(Blend {
                in1: self.in1.clone(),
                in2: self.in2.clone(),
                mode: self.mode,
                color_interpolation_filters: values.color_interpolation_filters(),
            }),
        ))
    }
}

impl Parse for Mode {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "normal" => Mode::Normal,
            "multiply" => Mode::Multiply,
            "screen" => Mode::Screen,
            "darken" => Mode::Darken,
            "lighten" => Mode::Lighten,
            "overlay" => Mode::Overlay,
            "color-dodge" => Mode::ColorDodge,
            "color-burn" => Mode::ColorBurn,
            "hard-light" => Mode::HardLight,
            "soft-light" => Mode::SoftLight,
            "difference" => Mode::Difference,
            "exclusion" => Mode::Exclusion,
            "hue" => Mode::HslHue,
            "saturation" => Mode::HslSaturation,
            "color" => Mode::HslColor,
            "luminosity" => Mode::HslLuminosity,
        )?)
    }
}

impl From<Mode> for cairo::Operator {
    #[inline]
    fn from(x: Mode) -> Self {
        match x {
            Mode::Normal => cairo::Operator::Over,
            Mode::Multiply => cairo::Operator::Multiply,
            Mode::Screen => cairo::Operator::Screen,
            Mode::Darken => cairo::Operator::Darken,
            Mode::Lighten => cairo::Operator::Lighten,
            Mode::Overlay => cairo::Operator::Overlay,
            Mode::ColorDodge => cairo::Operator::ColorDodge,
            Mode::ColorBurn => cairo::Operator::ColorBurn,
            Mode::HardLight => cairo::Operator::HardLight,
            Mode::SoftLight => cairo::Operator::SoftLight,
            Mode::Difference => cairo::Operator::Difference,
            Mode::Exclusion => cairo::Operator::Exclusion,
            Mode::HslHue => cairo::Operator::HslHue,
            Mode::HslSaturation => cairo::Operator::HslSaturation,
            Mode::HslColor => cairo::Operator::HslColor,
            Mode::HslLuminosity => cairo::Operator::HslLuminosity,
        }
    }
}
<commit_msg>feBlend: shorten code by implementing Default and Clone for its parameters<commit_after>use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::{Parse, ParseValue};
use crate::property_defs::ColorInterpolationFilters;
use crate::xml::Attributes;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, Input, Primitive, PrimitiveParams, ResolvedPrimitive};

/// Enumeration of the possible blending modes.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum Mode {
    Normal,
    Multiply,
    Screen,
    Darken,
    Lighten,
    Overlay,
    ColorDodge,
    ColorBurn,
    HardLight,
    SoftLight,
    Difference,
    Exclusion,
    HslHue,
    HslSaturation,
    HslColor,
    HslLuminosity,
}

enum_default!(Mode, Mode::Normal);

/// The `feBlend` filter primitive.
#[derive(Default)]
pub struct FeBlend {
    base: Primitive,
    params: Blend,
}

/// Resolved `feBlend` primitive for rendering.
#[derive(Clone, Default)]
pub struct Blend {
    in1: Input,
    in2: Input,
    mode: Mode,
    color_interpolation_filters: ColorInterpolationFilters,
}

impl SetAttributes for FeBlend {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        let (in1, in2) = self.base.parse_two_inputs(attrs)?;
        self.params.in1 = in1;
        self.params.in2 = in2;

        for (attr, value) in attrs.iter() {
            if let expanded_name!("", "mode") = attr.expanded() {
                self.params.mode = attr.parse(value)?;
            }
        }

        Ok(())
    }
}

impl Blend {
    pub fn render(
        &self,
        primitive: &ResolvedPrimitive,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input_1 = ctx.get_input(
            acquired_nodes,
            draw_ctx,
            &self.in1,
            self.color_interpolation_filters,
        )?;
        let input_2 = ctx.get_input(
            acquired_nodes,
            draw_ctx,
            &self.in2,
            self.color_interpolation_filters,
        )?;
        let bounds = primitive
            .get_bounds(ctx)?
            .add_input(&input_1)
            .add_input(&input_2)
            .into_irect(ctx, draw_ctx);

        let surface = input_1.surface().compose(
            input_2.surface(),
            bounds,
            cairo::Operator::from(self.mode),
        )?;

        Ok(FilterResult {
            name: primitive.result.clone(),
            output: FilterOutput { surface, bounds },
        })
    }
}

impl FilterEffect for FeBlend {
    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
        let cascaded = CascadedValues::new_from_node(node);
        let values = cascaded.get();

        let mut params = self.params.clone();
        params.color_interpolation_filters = values.color_interpolation_filters();

        Ok((self.base.clone(), PrimitiveParams::Blend(params)))
    }
}

impl Parse for Mode {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "normal" => Mode::Normal,
            "multiply" => Mode::Multiply,
            "screen" => Mode::Screen,
            "darken" => Mode::Darken,
            "lighten" => Mode::Lighten,
            "overlay" => Mode::Overlay,
            "color-dodge" => Mode::ColorDodge,
            "color-burn" => Mode::ColorBurn,
            "hard-light" => Mode::HardLight,
            "soft-light" => Mode::SoftLight,
            "difference" => Mode::Difference,
            "exclusion" => Mode::Exclusion,
            "hue" => Mode::HslHue,
            "saturation" => Mode::HslSaturation,
            "color" => Mode::HslColor,
            "luminosity" => Mode::HslLuminosity,
        )?)
    }
}

impl From<Mode> for cairo::Operator {
    #[inline]
    fn from(x: Mode) -> Self {
        match x {
            Mode::Normal => cairo::Operator::Over,
            Mode::Multiply => cairo::Operator::Multiply,
            Mode::Screen => cairo::Operator::Screen,
            Mode::Darken => cairo::Operator::Darken,
            Mode::Lighten => cairo::Operator::Lighten,
            Mode::Overlay => cairo::Operator::Overlay,
            Mode::ColorDodge => cairo::Operator::ColorDodge,
            Mode::ColorBurn => cairo::Operator::ColorBurn,
            Mode::HardLight => cairo::Operator::HardLight,
            Mode::SoftLight => cairo::Operator::SoftLight,
            Mode::Difference => cairo::Operator::Difference,
            Mode::Exclusion => cairo::Operator::Exclusion,
            Mode::HslHue => cairo::Operator::HslHue,
            Mode::HslSaturation => cairo::Operator::HslSaturation,
            Mode::HslColor => cairo::Operator::HslColor,
            Mode::HslLuminosity => cairo::Operator::HslLuminosity,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

use callbacks::cubeb_device_changed_callback;
use channel::cubeb_channel_layout;
use device::cubeb_device;
use format::cubeb_sample_format;
use std::{fmt, mem};
use std::os::raw::{c_float, c_int, c_uint, c_void};

cubeb_enum! {
    pub enum cubeb_stream_prefs {
        CUBEB_STREAM_PREF_NONE = 0x00,
        CUBEB_STREAM_PREF_LOOPBACK = 0x01,
        CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING = 0x02,
        CUBEB_STREAM_PREF_VOICE = 0x04,
    }
}

cubeb_enum! {
    pub enum cubeb_state {
        CUBEB_STATE_STARTED,
        CUBEB_STATE_STOPPED,
        CUBEB_STATE_DRAINED,
        CUBEB_STATE_ERROR,
    }
}

pub enum cubeb_stream {}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct cubeb_stream_params {
    pub format: cubeb_sample_format,
    pub rate: c_uint,
    pub channels: c_uint,
    pub layout: cubeb_channel_layout,
    pub prefs: cubeb_stream_prefs,
}

impl Default for cubeb_stream_params {
    fn default() -> Self {
        unsafe { mem::zeroed() }
    }
}

// Explicit Debug impl to work around bug in ctest
impl fmt::Debug for cubeb_stream_params {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("cubeb_stream_params")
            .field("format", &self.format)
            .field("rate", &self.rate)
            .field("channels", &self.channels)
            .field("layout", &self.layout)
            .field("prefs", &self.prefs)
            .finish()
    }
}

extern "C" {
    pub fn cubeb_stream_destroy(stream: *mut cubeb_stream);
    pub fn cubeb_stream_start(stream: *mut cubeb_stream) -> c_int;
    pub fn cubeb_stream_stop(stream: *mut cubeb_stream) -> c_int;
    pub fn cubeb_stream_reset_default_device(stream: *mut cubeb_stream) -> c_int;
    pub fn cubeb_stream_get_position(stream: *mut cubeb_stream, position: *mut u64) -> c_int;
    pub fn cubeb_stream_get_latency(stream: *mut cubeb_stream, latency: *mut c_uint) -> c_int;
    pub fn cubeb_stream_set_volume(stream: *mut cubeb_stream, volume: c_float) -> c_int;
    pub fn cubeb_stream_set_panning(stream: *mut cubeb_stream, panning: c_float) -> c_int;
    pub fn cubeb_stream_get_current_device(
        stream: *mut cubeb_stream,
        device: *mut *mut cubeb_device,
    ) -> c_int;
    pub fn cubeb_stream_device_destroy(
        stream: *mut cubeb_stream,
        devices: *mut cubeb_device,
    ) -> c_int;
    pub fn cubeb_stream_register_device_changed_callback(
        stream: *mut cubeb_stream,
        device_changed_callback: cubeb_device_changed_callback,
    ) -> c_int;
    pub fn cubeb_stream_user_ptr(stream: *mut cubeb_stream) -> *mut c_void;
}
<commit_msg>cubeb-sys: Remove missed cubeb_stream_set_panning reference.<commit_after>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

use callbacks::cubeb_device_changed_callback;
use channel::cubeb_channel_layout;
use device::cubeb_device;
use format::cubeb_sample_format;
use std::{fmt, mem};
use std::os::raw::{c_float, c_int, c_uint, c_void};

cubeb_enum! {
    pub enum cubeb_stream_prefs {
        CUBEB_STREAM_PREF_NONE = 0x00,
        CUBEB_STREAM_PREF_LOOPBACK = 0x01,
        CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING = 0x02,
        CUBEB_STREAM_PREF_VOICE = 0x04,
    }
}

cubeb_enum! {
    pub enum cubeb_state {
        CUBEB_STATE_STARTED,
        CUBEB_STATE_STOPPED,
        CUBEB_STATE_DRAINED,
        CUBEB_STATE_ERROR,
    }
}

pub enum cubeb_stream {}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct cubeb_stream_params {
    pub format: cubeb_sample_format,
    pub rate: c_uint,
    pub channels: c_uint,
    pub layout: cubeb_channel_layout,
    pub prefs: cubeb_stream_prefs,
}

impl Default for cubeb_stream_params {
    fn default() -> Self {
        unsafe { mem::zeroed() }
    }
}

// Explicit Debug impl to work around bug in ctest
impl fmt::Debug for cubeb_stream_params {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("cubeb_stream_params")
            .field("format", &self.format)
            .field("rate", &self.rate)
            .field("channels", &self.channels)
            .field("layout", &self.layout)
            .field("prefs", &self.prefs)
            .finish()
    }
}

extern "C" {
    pub fn cubeb_stream_destroy(stream: *mut cubeb_stream);
    pub fn cubeb_stream_start(stream: *mut cubeb_stream) -> c_int;
    pub fn cubeb_stream_stop(stream: *mut cubeb_stream) -> c_int;
    pub fn cubeb_stream_reset_default_device(stream: *mut cubeb_stream) -> c_int;
    pub fn cubeb_stream_get_position(stream: *mut cubeb_stream, position: *mut u64) -> c_int;
    pub fn cubeb_stream_get_latency(stream: *mut cubeb_stream, latency: *mut c_uint) -> c_int;
    pub fn cubeb_stream_set_volume(stream: *mut cubeb_stream, volume: c_float) -> c_int;
    pub fn cubeb_stream_get_current_device(
        stream: *mut cubeb_stream,
        device: *mut *mut cubeb_device,
    ) -> c_int;
    pub fn cubeb_stream_device_destroy(
        stream: *mut cubeb_stream,
        devices: *mut cubeb_device,
    ) -> c_int;
    pub fn cubeb_stream_register_device_changed_callback(
        stream: *mut cubeb_stream,
        device_changed_callback: cubeb_device_changed_callback,
    ) -> c_int;
    pub fn cubeb_stream_user_ptr(stream: *mut cubeb_stream) -> *mut c_void;
}
<|endoftext|>


<commit_before>//! A lazily populated index for looking up entities by name.
#![allow(dead_code)]

use clang::{self, Entity, EntityKind};
use std::collections::HashMap;
use std::fmt::{self, Debug, Display};
use std::iter::{FromIterator, IntoIterator};
use thiserror::Error;

/// Represents errors which can occur while looking up entities in the index.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum LookupError {
    #[error("couldn't find `{0}`")]
    NotFound(Path),
}

/// The result of a lookup operation.
type Result<T> = std::result::Result<T, LookupError>;

/// An ID assigned to a `Path` in the index.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NodeId(u32);

impl NodeId {
    #[inline(always)]
    fn from_usize(n: usize) -> NodeId {
        NodeId(n as u32)
    }
    #[allow(dead_code)]
    #[inline(always)]
    fn as_usize(&self) -> usize {
        self.0 as usize
    }
}

/// A C++ unqualified identifier.
///
/// Examples: `std`, `vector`, or `MyClass`.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct Ident {
    s: String,
}
impl From<&str> for Ident {
    /// Creates an identifier. Can panic if the identifier is invalid.
    fn from(id: &str) -> Ident {
        assert!(!id.contains("::"), "invalid identifier `{}`", id);
        Ident { s: id.to_string() }
    }
}
impl From<String> for Ident {
    fn from(id: String) -> Ident {
        From::from(id.as_str())
    }
}
impl Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.s)
    }
}

/// A C++ fully-qualified name.
///
/// Example: `std::vector`.
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct Path {
    components: Vec<Ident>,
}
impl From<&str> for Path {
    fn from(mut path: &str) -> Path {
        if path.starts_with("::") {
            path = &path[2..];
        }
        Path {
            components: path.split("::").map(Ident::from).collect(),
        }
    }
}
impl From<String> for Path {
    fn from(path: String) -> Path {
        From::from(path.as_str())
    }
}
impl FromIterator<Ident> for Path {
    fn from_iter<T: IntoIterator<Item = Ident>>(iter: T) -> Path {
        Path {
            components: iter.into_iter().collect(),
        }
    }
}
impl Path {
    pub fn iter(&self) -> impl Iterator<Item = &Ident> {
        self.components.iter()
    }
}
impl Display for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iter = self.components.iter();
        let mut next = iter.next();
        while let Some(id) = next {
            write!(f, "{}", id)?;
            next = iter.next();
            if next.is_some() {
                write!(f, "::")?;
            }
        }
        Ok(())
    }
}
impl Debug for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

/// An index `Node` is the entity or set of entities referred to by a `Path`.
///
/// For example, `std` and `std::vector` are both nodes.
///
/// Nodes may contain children, and they may be represented by multiple
/// entities. Namespaces, for example, can have many AST entities associated
/// with them. Template specializations are another example.
#[derive(Debug, Default)]
pub struct Node<'tu> {
    //kind: EntityKind,
    entities: Vec<Entity<'tu>>,
    items: Option<HashMap<Ident, NodeId>>,
    inline_items: Vec<NodeId>,
}
impl<'tu> Node<'tu> {
    fn items_mut(&mut self) -> &mut HashMap<Ident, NodeId> {
        self.items.as_mut().unwrap()
    }
}

/// A lazily populated index for looking up `Node`s by name.
pub struct Index<'tu> {
    nodes: Vec<Node<'tu>>,
}
impl<'tu> Index<'tu> {
    /// Creates an index from the given TranslationUnit.
    pub fn new(file: &'tu clang::TranslationUnit<'_>) -> Index<'tu> {
        let entity = file.get_entity();
        let file_node = Node {
            //kind: entity.get_kind(),
            entities: vec![entity],
            items: None,
            inline_items: vec![],
        };
        Index {
            nodes: vec![file_node],
        }
    }

    #[inline(always)]
    pub fn node(&self, id: NodeId) -> &Node<'tu> {
        &self.nodes[id.0 as usize]
    }

    #[inline(always)]
    fn node_mut(&mut self, id: NodeId) -> &mut Node<'tu> {
        &mut self.nodes[id.0 as usize]
    }

    /// Returns the `Node` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup(&mut self, path: &Path) -> Result<&Node<'tu>> {
        self.lookup_id(&path).map(move |id| self.node(id))
    }

    /// Returns the `NodeId` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup_id(&mut self, path: &Path) -> Result<NodeId> {
        let mut cur = NodeId(0);
        for (idx, name) in path.iter().enumerate() {
            cur = match self.child_id_of(cur, name)? {
                Some(child) => child,
                None => {
                    let err_path = path.iter().take(idx + 1).cloned().collect::<Path>();
                    return Err(LookupError::NotFound(err_path));
                }
            };
        }
        Ok(cur)
    }

    /// Returns the child named `child` of the given `node`.
    #[allow(dead_code)]
    pub fn child_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<&Node>> {
        self.child_id_of(node, child)
            .map(|opt| opt.map(move |id| self.node(id)))
    }

    /// Returns the `NodeId` of the child named `child` of the given `node`.
    pub fn child_id_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<NodeId>> {
        if self.node(node).items.is_none() {
            self.expand(node)?;
        }
        let children = self.node(node).items.as_ref().unwrap();
        Ok(children.get(child).copied())
    }

    fn expand(&mut self, node: NodeId) -> Result<()> {
        self.node_mut(node).items = Some(HashMap::new());
        let num_entities = self.node(node).entities.len();
        for ent_idx in 0..num_entities {
            let ent = self.node(node).entities[ent_idx];

            // TODO: Looking up children of unsupported entity types will result
            // in confusing NotFound errors.
            if should_expand(ent) {
                self.populate_children(node, ent)?;
            }
        }
        Ok(())
    }

    fn populate_children(&mut self, parent: NodeId, ent: Entity<'tu>) -> Result<()> {
        for child in ent.get_children() {
            let name = match child.get_name() {
                Some(name) => Ident::from(name),
                None => continue,
            };
            let child_id = self.get_or_insert_child(parent, name);
            self.node_mut(child_id).entities.push(child);

            if should_inline(child) {
                //self.node_mut(parent).inline_items.push(child_id);
                // Populate the parent with all of this node's children.
                self.populate_children(parent, child)?;
            }
        }
        Ok(())
    }

    fn get_or_insert_child(&mut self, parent: NodeId, child: Ident) -> NodeId {
        let next_id = self.next_node_id();
        let child_id = *self
            .node_mut(parent)
            .items_mut()
            .entry(child)
            .or_insert(next_id);
        if child_id == next_id {
            self.nodes.push(Default::default());
        }
        child_id
    }

    #[inline(always)]
    fn next_node_id(&self) -> NodeId {
        NodeId::from_usize(self.nodes.len())
    }
}

fn should_expand(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        TranslationUnit => true,
        Namespace | StructDecl | ClassDecl | ClassTemplate => true,
        _ => false,
    }
}

fn should_inline(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        Namespace | EnumDecl => !ent.is_scoped(),
        _ => false,
    }
}

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

    #[test]
    fn inline_namespace() {
        let clang = clang::Clang::new().unwrap();
        let index = clang::Index::new(&clang, true, true);
        let file = cpp_parse!(&index, {
            namespace std {
                inline namespace __1 {
                    struct vector {};
                }
                namespace notinline {
                    struct foo {};
                }
            }
        });
        let mut index = Index::new(&file);
        assert!(index.lookup(&Path::from("std::vector")).is_ok());
        // FIXME: doesn't work :(
        assert!(index.lookup(&Path::from("std::foo")).is_err());
    }

    #[test]
    fn paths() {
        assert_eq!(
            Path::from("::std::stuff::basic_iterator"),
            Path::from("std::stuff::basic_iterator")
        );
        assert_eq!(
            Path::from("::std::vector<bool>::basic_iterator")
                .iter()
                .cloned()
                .collect::<Vec<_>>(),
            ["std", "vector<bool>", "basic_iterator"]
                .into_iter()
                .copied()
                .map(Ident::from)
                .collect::<Vec<_>>()
        );
    }
}
<commit_msg>index: Don't inline any namespaces (fix test)<commit_after>//! A lazily populated index for looking up entities by name.
#![allow(dead_code)]

use clang::{self, Entity, EntityKind};
use std::collections::HashMap;
use std::fmt::{self, Debug, Display};
use std::iter::{FromIterator, IntoIterator};
use thiserror::Error;

/// Represents errors which can occur while looking up entities in the index.
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum LookupError {
    #[error("couldn't find `{0}`")]
    NotFound(Path),
}

/// The result of a lookup operation.
type Result<T> = std::result::Result<T, LookupError>;

/// An ID assigned to a `Path` in the index.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct NodeId(u32);

impl NodeId {
    #[inline(always)]
    fn from_usize(n: usize) -> NodeId {
        NodeId(n as u32)
    }
    #[allow(dead_code)]
    #[inline(always)]
    fn as_usize(&self) -> usize {
        self.0 as usize
    }
}

/// A C++ unqualified identifier.
///
/// Examples: `std`, `vector`, or `MyClass`.
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub struct Ident {
    s: String,
}
impl From<&str> for Ident {
    /// Creates an identifier. Can panic if the identifier is invalid.
    fn from(id: &str) -> Ident {
        assert!(!id.contains("::"), "invalid identifier `{}`", id);
        Ident { s: id.to_string() }
    }
}
impl From<String> for Ident {
    fn from(id: String) -> Ident {
        From::from(id.as_str())
    }
}
impl Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.s)
    }
}

/// A C++ fully-qualified name.
///
/// Example: `std::vector`.
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct Path {
    components: Vec<Ident>,
}
impl From<&str> for Path {
    fn from(mut path: &str) -> Path {
        if path.starts_with("::") {
            path = &path[2..];
        }
        Path {
            components: path.split("::").map(Ident::from).collect(),
        }
    }
}
impl From<String> for Path {
    fn from(path: String) -> Path {
        From::from(path.as_str())
    }
}
impl FromIterator<Ident> for Path {
    fn from_iter<T: IntoIterator<Item = Ident>>(iter: T) -> Path {
        Path {
            components: iter.into_iter().collect(),
        }
    }
}
impl Path {
    pub fn iter(&self) -> impl Iterator<Item = &Ident> {
        self.components.iter()
    }
}
impl Display for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iter = self.components.iter();
        let mut next = iter.next();
        while let Some(id) = next {
            write!(f, "{}", id)?;
            next = iter.next();
            if next.is_some() {
                write!(f, "::")?;
            }
        }
        Ok(())
    }
}
impl Debug for Path {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

/// An index `Node` is the entity or set of entities referred to by a `Path`.
///
/// For example, `std` and `std::vector` are both nodes.
///
/// Nodes may contain children, and they may be represented by multiple
/// entities. Namespaces, for example, can have many AST entities associated
/// with them. Template specializations are another example.
#[derive(Debug, Default)]
pub struct Node<'tu> {
    //kind: EntityKind,
    entities: Vec<Entity<'tu>>,
    items: Option<HashMap<Ident, NodeId>>,
    inline_items: Vec<NodeId>,
}
impl<'tu> Node<'tu> {
    fn items_mut(&mut self) -> &mut HashMap<Ident, NodeId> {
        self.items.as_mut().unwrap()
    }
}

/// A lazily populated index for looking up `Node`s by name.
pub struct Index<'tu> {
    nodes: Vec<Node<'tu>>,
}
impl<'tu> Index<'tu> {
    /// Creates an index from the given TranslationUnit.
    pub fn new(file: &'tu clang::TranslationUnit<'_>) -> Index<'tu> {
        let entity = file.get_entity();
        let file_node = Node {
            //kind: entity.get_kind(),
            entities: vec![entity],
            items: None,
            inline_items: vec![],
        };
        Index {
            nodes: vec![file_node],
        }
    }

    #[inline(always)]
    pub fn node(&self, id: NodeId) -> &Node<'tu> {
        &self.nodes[id.0 as usize]
    }

    #[inline(always)]
    fn node_mut(&mut self, id: NodeId) -> &mut Node<'tu> {
        &mut self.nodes[id.0 as usize]
    }

    /// Returns the `Node` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup(&mut self, path: &Path) -> Result<&Node<'tu>> {
        self.lookup_id(&path).map(move |id| self.node(id))
    }

    /// Returns the `NodeId` corresponding to the given `Path`.
    ///
    /// If the path does not exist, returns `LookupError::NotFound`.
    pub fn lookup_id(&mut self, path: &Path) -> Result<NodeId> {
        let mut cur = NodeId(0);
        for (idx, name) in path.iter().enumerate() {
            cur = match self.child_id_of(cur, name)? {
                Some(child) => child,
                None => {
                    let err_path = path.iter().take(idx + 1).cloned().collect::<Path>();
                    return Err(LookupError::NotFound(err_path));
                }
            };
        }
        Ok(cur)
    }

    /// Returns the child named `child` of the given `node`.
    #[allow(dead_code)]
    pub fn child_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<&Node>> {
        self.child_id_of(node, child)
            .map(|opt| opt.map(move |id| self.node(id)))
    }

    /// Returns the `NodeId` of the child named `child` of the given `node`.
    pub fn child_id_of(&mut self, node: NodeId, child: &Ident) -> Result<Option<NodeId>> {
        if self.node(node).items.is_none() {
            self.expand(node)?;
        }
        let children = self.node(node).items.as_ref().unwrap();
        Ok(children.get(child).copied())
    }

    fn expand(&mut self, node: NodeId) -> Result<()> {
        self.node_mut(node).items = Some(HashMap::new());
        let num_entities = self.node(node).entities.len();
        for ent_idx in 0..num_entities {
            let ent = self.node(node).entities[ent_idx];

            // TODO: Looking up children of unsupported entity types will result
            // in confusing NotFound errors.
            if should_expand(ent) {
                self.populate_children(node, ent)?;
            }
        }
        Ok(())
    }

    fn populate_children(&mut self, parent: NodeId, ent: Entity<'tu>) -> Result<()> {
        for child in ent.get_children() {
            let name = match child.get_name() {
                Some(name) => Ident::from(name),
                None => continue,
            };
            let child_id = self.get_or_insert_child(parent, name);
            self.node_mut(child_id).entities.push(child);

            if should_inline(child) {
                //self.node_mut(parent).inline_items.push(child_id);
                // Populate the parent with all of this node's children.
                self.populate_children(parent, child)?;
            }
        }
        Ok(())
    }

    fn get_or_insert_child(&mut self, parent: NodeId, child: Ident) -> NodeId {
        let next_id = self.next_node_id();
        let child_id = *self
            .node_mut(parent)
            .items_mut()
            .entry(child)
            .or_insert(next_id);
        if child_id == next_id {
            self.nodes.push(Default::default());
        }
        child_id
    }

    #[inline(always)]
    fn next_node_id(&self) -> NodeId {
        NodeId::from_usize(self.nodes.len())
    }
}

fn should_expand(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        TranslationUnit => true,
        Namespace | StructDecl | ClassDecl | ClassTemplate => true,
        _ => false,
    }
}

fn should_inline(ent: Entity<'_>) -> bool {
    use EntityKind::*;
    match ent.get_kind() {
        Namespace => false,
        EnumDecl => !ent.is_scoped(),
        _ => false,
    }
}

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

    #[test]
    fn inline_namespace() {
        let clang = clang::Clang::new().unwrap();
        let index = clang::Index::new(&clang, true, true);
        let file = cpp_parse!(&index, {
            namespace std {
                inline namespace __1 {
                    struct vector {};
                }
                namespace notinline {
                    struct foo {};
                }
            }
        });
        let mut index = Index::new(&file);
        assert!(index.lookup(&Path::from("std::__1::vector")).is_ok());
        assert!(index.lookup(&Path::from("std::notinline::foo")).is_ok());
        assert!(index.lookup(&Path::from("std::foo")).is_err());
    }

    #[test]
    fn paths() {
        assert_eq!(
            Path::from("::std::stuff::basic_iterator"),
            Path::from("std::stuff::basic_iterator")
        );
        assert_eq!(
            Path::from("::std::vector<bool>::basic_iterator")
                .iter()
                .cloned()
                .collect::<Vec<_>>(),
            ["std", "vector<bool>", "basic_iterator"]
                .into_iter()
                .copied()
                .map(Ident::from)
                .collect::<Vec<_>>()
        );
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::str;

use cargo_process;
use support::paths;
use support::{execs, project, mkdir_recursive, ProjectBuilder, ERROR};
use hamcrest::{assert_that};

fn setup() {
}

/// Add an empty file with executable flags (and platform-dependent suffix).
/// TODO: move this to `ProjectBuilder` if other cases using this emerge.
fn fake_executable(proj: ProjectBuilder, dir: &Path, name: &str) -> ProjectBuilder {
    let path = proj.root().join(dir).join(&format!("{}{}", name,
                                                   env::consts::EXE_SUFFIX));
    mkdir_recursive(path.parent().unwrap()).unwrap();
    File::create(&path).unwrap();
    make_executable(&path);
    return proj;

    #[cfg(unix)]
    fn make_executable(p: &Path) {
        use std::os::unix::prelude::*;

        let mut perms = fs::metadata(p).unwrap().permissions();;
        let mode = perms.mode();
        perms.set_mode(mode | 0o111);
        fs::set_permissions(p, perms).unwrap();
    }
    #[cfg(windows)]
    fn make_executable(_: &Path) {}
}

fn path() -> Vec<PathBuf> {
    env::split_paths(&env::var_os("PATH").unwrap_or(OsString::new())).collect()
}

test!(list_commands_looks_at_path {
    let proj = project("list-non-overlapping");
    let proj = fake_executable(proj, &Path::new("path-test"), "cargo-1");
    let mut pr = cargo_process();

    let mut path = path();
    path.push(proj.root().join("path-test"));
    let path = env::join_paths(path.iter()).unwrap();
    let output = pr.arg("-v").arg("--list")
                   .env("PATH", &path);
    let output = output.exec_with_output().unwrap();
    let output = str::from_utf8(&output.stdout).unwrap();
    assert!(output.contains("\n    1\n"), "missing 1: {}", output);
});

test!(find_closest_biuld_to_build {
    let mut pr = cargo_process();
    pr.arg("biuld");

    assert_that(pr,
                execs().with_status(101)
                       .with_stderr(&format!("{error} no such subcommand

<tab>Did you mean `build`?

",
error = ERROR)));
});

// if a subcommand is more than 3 edit distance away, we don't make a suggestion
test!(find_closest_dont_correct_nonsense {
    let mut pr = cargo_process();
    pr.arg("there-is-no-way-that-there-is-a-command-close-to-this")
      .cwd(&paths::root());

    assert_that(pr,
                execs().with_status(101)
                       .with_stderr(&format!("{error} no such subcommand
",
error = ERROR)));
});

test!(override_cargo_home {
    let root = paths::root();
    let my_home = root.join("my_home");
    fs::create_dir(&my_home).unwrap();
    File::create(&my_home.join("config")).unwrap().write_all(br#"
        [cargo-new]
        name = "foo"
        email = "bar"
        git = false
    "#).unwrap();

    assert_that(cargo_process()
                    .arg("new").arg("foo")
                    .env("USER", "foo")
                    .env("CARGO_HOME", &my_home),
                execs().with_status(0));

    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
});

test!(cargo_help {
    assert_that(cargo_process(),
                execs().with_status(0));
    assert_that(cargo_process().arg("help"),
                execs().with_status(0));
    assert_that(cargo_process().arg("-h"),
                execs().with_status(0));
    assert_that(cargo_process().arg("help").arg("build"),
                execs().with_status(0));
    assert_that(cargo_process().arg("build").arg("-h"),
                execs().with_status(0));
    assert_that(cargo_process().arg("help").arg("-h"),
                execs().with_status(0));
    assert_that(cargo_process().arg("help").arg("help"),
                execs().with_status(0));
});
<commit_msg>Tests: fix grammar and extra semicolon<commit_after>use std::env;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::str;

use cargo_process;
use support::paths;
use support::{execs, project, mkdir_recursive, ProjectBuilder, ERROR};
use hamcrest::{assert_that};

fn setup() {
}

/// Add an empty file with executable flags (and platform-dependent suffix).
/// TODO: move this to `ProjectBuilder` if other cases using this emerge.
fn fake_executable(proj: ProjectBuilder, dir: &Path, name: &str) -> ProjectBuilder {
    let path = proj.root().join(dir).join(&format!("{}{}", name,
                                                   env::consts::EXE_SUFFIX));
    mkdir_recursive(path.parent().unwrap()).unwrap();
    File::create(&path).unwrap();
    make_executable(&path);
    return proj;

    #[cfg(unix)]
    fn make_executable(p: &Path) {
        use std::os::unix::prelude::*;

        let mut perms = fs::metadata(p).unwrap().permissions();
        let mode = perms.mode();
        perms.set_mode(mode | 0o111);
        fs::set_permissions(p, perms).unwrap();
    }
    #[cfg(windows)]
    fn make_executable(_: &Path) {}
}

fn path() -> Vec<PathBuf> {
    env::split_paths(&env::var_os("PATH").unwrap_or(OsString::new())).collect()
}

test!(list_command_looks_at_path {
    let proj = project("list-non-overlapping");
    let proj = fake_executable(proj, &Path::new("path-test"), "cargo-1");
    let mut pr = cargo_process();

    let mut path = path();
    path.push(proj.root().join("path-test"));
    let path = env::join_paths(path.iter()).unwrap();
    let output = pr.arg("-v").arg("--list")
                   .env("PATH", &path);
    let output = output.exec_with_output().unwrap();
    let output = str::from_utf8(&output.stdout).unwrap();
    assert!(output.contains("\n    1\n"), "missing 1: {}", output);
});

test!(find_closest_biuld_to_build {
    let mut pr = cargo_process();
    pr.arg("biuld");

    assert_that(pr,
                execs().with_status(101)
                       .with_stderr(&format!("{error} no such subcommand

<tab>Did you mean `build`?

",
error = ERROR)));
});

// if a subcommand is more than 3 edit distance away, we don't make a suggestion
test!(find_closest_dont_correct_nonsense {
    let mut pr = cargo_process();
    pr.arg("there-is-no-way-that-there-is-a-command-close-to-this")
      .cwd(&paths::root());

    assert_that(pr,
                execs().with_status(101)
                       .with_stderr(&format!("{error} no such subcommand
",
error = ERROR)));
});

test!(override_cargo_home {
    let root = paths::root();
    let my_home = root.join("my_home");
    fs::create_dir(&my_home).unwrap();
    File::create(&my_home.join("config")).unwrap().write_all(br#"
        [cargo-new]
        name = "foo"
        email = "bar"
        git = false
    "#).unwrap();

    assert_that(cargo_process()
                    .arg("new").arg("foo")
                    .env("USER", "foo")
                    .env("CARGO_HOME", &my_home),
                execs().with_status(0));

    let toml = paths::root().join("foo/Cargo.toml");
    let mut contents = String::new();
    File::open(&toml).unwrap().read_to_string(&mut contents).unwrap();
    assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
});

test!(cargo_help {
    assert_that(cargo_process(),
                execs().with_status(0));
    assert_that(cargo_process().arg("help"),
                execs().with_status(0));
    assert_that(cargo_process().arg("-h"),
                execs().with_status(0));
    assert_that(cargo_process().arg("help").arg("build"),
                execs().with_status(0));
    assert_that(cargo_process().arg("build").arg("-h"),
                execs().with_status(0));
    assert_that(cargo_process().arg("help").arg("-h"),
                execs().with_status(0));
    assert_that(cargo_process().arg("help").arg("help"),
                execs().with_status(0));
});
<|endoftext|>


<commit_before>extern crate sourcemap;

use std::collections::HashMap;
use sourcemap::SourceMapIndex;

#[test]
fn test_basic_indexed_sourcemap() {
    let input: &[_] = br#"{
        "version": 3,
        "file": "min.js",
        "sections": [
            {
                "offset": {
                    "line": 0,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file1.js"],
                    "names":["add","a","b"],
                    "mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
                    "file":"file1.min.js"
                }
            },
            {
                "offset": {
                    "line": 1,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file2.js"],
                    "names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
                    "mappings":"AAAA,QAASA,UAASC,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASC,QAAOF,EAAGC,GAClB,YACA,KACC,MAAOF,UAASI,IAAIH,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
                    "file":"file2.min.js"
                }
            }
        ]
    }"#;

    let file1 : Vec<_> = "function add(a, b) {\n \"use strict\";\n \
                          return a + b; // fôo\n}".lines().collect();
    let file2 : Vec<_> = "function multiply(a, b) {\n \"use strict\";\n \
                          return a * b;\n}\nfunction divide(a, b) {\n \
                          \"use strict\";\n try {\n  return multiply(add(a, \
                          b), a, b) / c;\n } catch (e) {\n  \
                          Raven.captureException(e);\n }\n}".lines().collect();

    let mut files = HashMap::new();
    files.insert("file1.js", file1);
    files.insert("file2.js", file2);

    let ism = SourceMapIndex::from_reader(input).unwrap();
    let flat_map = ism.flatten().unwrap();

    for token in flat_map.tokens() {
        let src = files.get(token.get_source().unwrap()).unwrap();
        if let Some(name) = token.get_name() {
            let line = src[token.get_src_line() as usize];
            let idx = token.get_src_col() as usize;
            let span = &line[idx..idx + name.len()];
            assert_eq!(span, name);
        }
    }
}
<commit_msg>Shorten variables<commit_after>extern crate sourcemap;

use std::collections::HashMap;
use sourcemap::SourceMapIndex;

#[test]
fn test_basic_indexed_sourcemap() {
    let input: &[_] = br#"{
        "version": 3,
        "file": "min.js",
        "sections": [
            {
                "offset": {
                    "line": 0,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file1.js"],
                    "names":["add","a","b"],
                    "mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC",
                    "file":"file1.min.js"
                }
            },
            {
                "offset": {
                    "line": 1,
                    "column": 0
                },
                "map": {
                    "version":3,
                    "sources":["file2.js"],
                    "names":["multiply","a","b","divide","add","c","e","Raven","captureException"],
                    "mappings":"AAAA,QAASA,UAASC,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASC,QAAOF,EAAGC,GAClB,YACA,KACC,MAAOF,UAASI,IAAIH,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF",
                    "file":"file2.min.js"
                }
            }
        ]
    }"#;

    let f1 : Vec<_> = "function add(a, b) {\n \"use strict\";\n \
                       return a + b; // fôo\n}".lines().collect();
    let f2 : Vec<_> = "function multiply(a, b) {\n \"use strict\";\n \
                       return a * b;\n}\nfunction divide(a, b) {\n \
                       \"use strict\";\n try {\n  return multiply(add(a, \
                       b), a, b) / c;\n } catch (e) {\n  \
                       Raven.captureException(e);\n }\n}".lines().collect();

    let mut files = HashMap::new();
    files.insert("file1.js", f1);
    files.insert("file2.js", f2);

    let ism = SourceMapIndex::from_reader(input).unwrap();
    let flat_map = ism.flatten().unwrap();

    for token in flat_map.tokens() {
        let src = files.get(token.get_source().unwrap()).unwrap();
        if let Some(name) = token.get_name() {
            let line = src[token.get_src_line() as usize];
            let idx = token.get_src_col() as usize;
            let span = &line[idx..idx + name.len()];
            assert_eq!(span, name);
        }
    }
}
<|endoftext|>


<commit_before>pub const JOY_PENDANT: u8 = 0x1F;
pub const TELESCOPE: u8 = 0x20;
pub const TINGLE_TUNER: u8 = 0x21;
pub const WIND_WAKER: u8 = 0x22;
pub const PICTO_BOX: u8 = 0x23;
pub const SPOILS_BAG: u8 = 0x24;
pub const GRAPPLING_HOOK: u8 = 0x25;
pub const DELUXE_PICTO_BOX: u8 = 0x26;
pub const BOW: u8 = 0x27;
pub const POWER_BRACELETS: u8 = 0x28; // also 0x2e
pub const IRON_BOOTS: u8 = 0x29;
pub const MAGIC_ARMOR: u8 = 0x2A;
pub const WATER_BOOTS: u8 = 0x2B;
pub const BAIT_BAG: u8 = 0x2C;
pub const BOOMERANG: u8 = 0x2D;
pub const HOOKSHOT: u8 = 0x2F;
pub const DELIVERY_BAG: u8 = 0x30;
pub const BOMBS: u8 = 0x31;
pub const TUNIC: u8 = 0x32; // also 0x37
pub const SKULL_HAMMER: u8 = 0x33;
pub const DEKU_LEAF: u8 = 0x34;
pub const BOW_WITH_FIRE_AND_ICE_ARROWS: u8 = 0x35;
pub const BOW_WITH_LIGHT_ARROWS: u8 = 0x36;
pub const HEROS_SWORD: u8 = 0x38;
pub const UNCHARGED_MASTER_SWORD: u8 = 0x39;
pub const HALF_CHARGED_MASTER_SWORD: u8 = 0x3A;
pub const HEROS_SHIELD: u8 = 0x3B;
pub const MIRROR_SHIELD: u8 = 0x3C;
pub const FULLY_CHARGED_MASTER_SWORD: u8 = 0x3E;
pub const PIRATES_CHARM: u8 = 0x42;
pub const HEROS_CHARM: u8 = 0x43;
pub const SKULL_NECKLACE: u8 = 0x45;
pub const BOKO_BABA_SEED: u8 = 0x46;
pub const GOLDEN_FEATHER: u8 = 0x47;
pub const KNIGHTS_CREST: u8 = 0x48;
pub const RED_CHU_JELLY: u8 = 0x49;
pub const GREEN_CHU_JELLY: u8 = 0x4A;
pub const BLUE_CHU_JELLY: u8 = 0x4B;
pub const MAP: u8 = 0x4C;
pub const COMPASS: u8 = 0x4D;
pub const BIG_KEY: u8 = 0x4E;
pub const EMPTY_BOTTLE: u8 = 0x50;
pub const RED_POTION: u8 = 0x51;
pub const GREEN_POTION: u8 = 0x52;
pub const BLUE_POTION: u8 = 0x53;
pub const ELIXIR_SOUP_HALF: u8 = 0x54;
pub const ELIXIR_SOUP: u8 = 0x55;
pub const WATER: u8 = 0x56;
pub const FAIRY: u8 = 0x57;
pub const FOREST_FIREFLY: u8 = 0x58;
pub const FOREST_WATER: u8 = 0x59;
pub const TRIFORCE_PIECE_1: u8 = 0x61;
pub const TRIFORCE_PIECE_2: u8 = 0x62;
pub const TRIFORCE_PIECE_3: u8 = 0x63;
pub const TRIFORCE_PIECE_4: u8 = 0x64;
pub const TRIFORCE_PIECE_5: u8 = 0x65;
pub const TRIFORCE_PIECE_6: u8 = 0x66;
pub const TRIFORCE_PIECE_7: u8 = 0x67;
pub const TRIFORCE_PIECE_8: u8 = 0x68;
pub const NAYRUS_PEARL: u8 = 0x69;
pub const DINS_PEARL: u8 = 0x6A;
pub const FARORES_PEARL: u8 = 0x6B;
pub const SAIL: u8 = 0x78;
pub const TRIFORCE_CHART: u8 = 0x79;
pub const ALL_PURPOSE_BAIT: u8 = 0x82;
pub const HYOI_PEAR: u8 = 0x83;
pub const TOWN_FLOWER: u8 = 0x8C;
pub const SEA_FLOWER: u8 = 0x8D;
pub const EXOTIC_FLOWER: u8 = 0x8E;
pub const HEROS_FLAG: u8 = 0x8F;
pub const BIG_CATCH_FLAG: u8 = 0x90;
pub const BIG_SALE_FLAG: u8 = 0x91;
pub const PINWHEEL: u8 = 0x92;
pub const SICKLE_MOON_FLAG: u8 = 0x93;
pub const SKULL_TOWER_IDOL: u8 = 0x94;
pub const FOUNTAIN_IDOL: u8 = 0x95;
pub const POSTMAN_STATUE: u8 = 0x96;
pub const SHOP_GURU_STATUE: u8 = 0x97;
pub const FATHERS_LETTER: u8 = 0x98;
pub const NOTE_TO_MOM: u8 = 0x99;
pub const MAGGIES_LETTER: u8 = 0x9A;
pub const MOBLINS_LETTER: u8 = 0x9B;
pub const CABANA_DEED: u8 = 0x9C;
pub const COMPLIMENTARY_ID: u8 = 0x9D;
pub const FILL_UP_COUPON: u8 = 0x9E;
pub const GOLDEN_TINGLE_HEAD: u8 = 0xA3;
pub const EMPTY: u8 = 0xFF;
<commit_msg>Add Item Drop IDs<commit_after>pub const HEART_DROP: u8 = 0x00;
pub const GREEN_RUPEE_DROP: u8 = 0x01;
pub const BLUE_RUPEE_DROP: u8 = 0x02;
pub const YELLOW_RUPEE_DROP: u8 = 0x03;
pub const RED_RUPEE_DROP: u8 = 0x04;
pub const PURPLE_RUPEE_DROP: u8 = 0x05;
pub const ORANGE_RUPEE_DROP: u8 = 0x06;
pub const HEART_PIECE: u8 = 0x07;
pub const HEART_CONTAINER: u8 = 0x08;
pub const SMALL_MAGIC_DROP: u8 = 0x09;
pub const LARGE_MAGIC_DROP: u8 = 0x0A;
pub const BOMB_DROP: u8 = 0x0B;
pub const SILVER_RUPEE_DROP: u8 = 0x0F;
pub const SINGLE_ARROW_DROP: u8 = 0x10;
pub const DOUBLE_ARROW_DROP: u8 = 0x11;
pub const TRIPLE_ARROW_DROP: u8 = 0x12;
pub const KEY_DROP: u8 = 0x15;
pub const FAIRY_DROP: u8 = 0x16;
pub const TRIPLE_HEART_DROP: u8 = 0x1E;
pub const JOY_PENDANT: u8 = 0x1F;
pub const TELESCOPE: u8 = 0x20;
pub const TINGLE_TUNER: u8 = 0x21;
pub const WIND_WAKER: u8 = 0x22;
pub const PICTO_BOX: u8 = 0x23;
pub const SPOILS_BAG: u8 = 0x24;
pub const GRAPPLING_HOOK: u8 = 0x25;
pub const DELUXE_PICTO_BOX: u8 = 0x26;
pub const BOW: u8 = 0x27;
pub const POWER_BRACELETS: u8 = 0x28;
pub const IRON_BOOTS: u8 = 0x29;
pub const MAGIC_ARMOR: u8 = 0x2A;
pub const WATER_BOOTS: u8 = 0x2B;
pub const BAIT_BAG: u8 = 0x2C;
pub const BOOMERANG: u8 = 0x2D;
pub const HOOKSHOT: u8 = 0x2F;
pub const DELIVERY_BAG: u8 = 0x30;
pub const BOMBS: u8 = 0x31;
pub const TUNIC: u8 = 0x32;
pub const SKULL_HAMMER: u8 = 0x33;
pub const DEKU_LEAF: u8 = 0x34;
pub const BOW_WITH_FIRE_AND_ICE_ARROWS: u8 = 0x35;
pub const BOW_WITH_LIGHT_ARROWS: u8 = 0x36;
pub const HEROS_SWORD: u8 = 0x38;
pub const UNCHARGED_MASTER_SWORD: u8 = 0x39;
pub const HALF_CHARGED_MASTER_SWORD: u8 = 0x3A;
pub const HEROS_SHIELD: u8 = 0x3B;
pub const MIRROR_SHIELD: u8 = 0x3C;
pub const FULLY_CHARGED_MASTER_SWORD: u8 = 0x3E;
pub const PIRATES_CHARM: u8 = 0x42;
pub const HEROS_CHARM: u8 = 0x43;
pub const SKULL_NECKLACE: u8 = 0x45;
pub const BOKO_BABA_SEED: u8 = 0x46;
pub const GOLDEN_FEATHER: u8 = 0x47;
pub const KNIGHTS_CREST: u8 = 0x48;
pub const RED_CHU_JELLY: u8 = 0x49;
pub const GREEN_CHU_JELLY: u8 = 0x4A;
pub const BLUE_CHU_JELLY: u8 = 0x4B;
pub const MAP: u8 = 0x4C;
pub const COMPASS: u8 = 0x4D;
pub const BIG_KEY: u8 = 0x4E;
pub const EMPTY_BOTTLE: u8 = 0x50;
pub const RED_POTION: u8 = 0x51;
pub const GREEN_POTION: u8 = 0x52;
pub const BLUE_POTION: u8 = 0x53;
pub const ELIXIR_SOUP_HALF: u8 = 0x54;
pub const ELIXIR_SOUP: u8 = 0x55;
pub const WATER: u8 = 0x56;
pub const FAIRY: u8 = 0x57;
pub const FOREST_FIREFLY: u8 = 0x58;
pub const FOREST_WATER: u8 = 0x59;
pub const TRIFORCE_PIECE_1: u8 = 0x61;
pub const TRIFORCE_PIECE_2: u8 = 0x62;
pub const TRIFORCE_PIECE_3: u8 = 0x63;
pub const TRIFORCE_PIECE_4: u8 = 0x64;
pub const TRIFORCE_PIECE_5: u8 = 0x65;
pub const TRIFORCE_PIECE_6: u8 = 0x66;
pub const TRIFORCE_PIECE_7: u8 = 0x67;
pub const TRIFORCE_PIECE_8: u8 = 0x68;
pub const NAYRUS_PEARL: u8 = 0x69;
pub const DINS_PEARL: u8 = 0x6A;
pub const FARORES_PEARL: u8 = 0x6B;
pub const SAIL: u8 = 0x78;
pub const TRIFORCE_CHART: u8 = 0x79;
pub const ALL_PURPOSE_BAIT: u8 = 0x82;
pub const HYOI_PEAR: u8 = 0x83;
pub const TOWN_FLOWER: u8 = 0x8C;
pub const SEA_FLOWER: u8 = 0x8D;
pub const EXOTIC_FLOWER: u8 = 0x8E;
pub const HEROS_FLAG: u8 = 0x8F;
pub const BIG_CATCH_FLAG: u8 = 0x90;
pub const BIG_SALE_FLAG: u8 = 0x91;
pub const PINWHEEL: u8 = 0x92;
pub const SICKLE_MOON_FLAG: u8 = 0x93;
pub const SKULL_TOWER_IDOL: u8 = 0x94;
pub const FOUNTAIN_IDOL: u8 = 0x95;
pub const POSTMAN_STATUE: u8 = 0x96;
pub const SHOP_GURU_STATUE: u8 = 0x97;
pub const FATHERS_LETTER: u8 = 0x98;
pub const NOTE_TO_MOM: u8 = 0x99;
pub const MAGGIES_LETTER: u8 = 0x9A;
pub const MOBLINS_LETTER: u8 = 0x9B;
pub const CABANA_DEED: u8 = 0x9C;
pub const COMPLIMENTARY_ID: u8 = 0x9D;
pub const FILL_UP_COUPON: u8 = 0x9E;
pub const GOLDEN_TINGLE_HEAD: u8 = 0xA3;
pub const EMPTY: u8 = 0xFF;
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Bytes;

#[derive(Debug)]
pub enum Mnemonic {
    Add, Call, Cls, Drw,
    Jp, Ld, Or, Ret,
    Rnd, Se, Shl, Shr,
    Sknp, Skp, Sne, Sub,
    Subn, Sys, Xor,
}

#[derive(Debug)]
pub enum Register {
    V0, V1, V2, V3,
    V4, V5, V6, V7,
    V8, V9, Va, Vb,
    Vc, Vd, Ve, Vf,
    Sp, Pc, I, St, Dt, IVal,
}

#[derive(Debug)]
pub enum Token {
    Opcode(Mnemonic, u32),
    Reg(Register, u32),
    ImmConst(u16, u32),
}

pub struct Stream {
    input: Bytes<File>,
    line: u32,
}

impl Stream {
    pub fn new(input: Bytes<File>) -> Stream {
        Stream {
            input: input,
            line: 1,
        }
    }

    pub fn next_token(&mut self) -> Option<Token> {
        let mut buffer: Vec<u8> = vec![];

        loop {
            let bs = self.input.next().map_or(None, |bm| match bm {
                Ok(b) => Some(b),
                _ => None
            });

            match bs {
                Some(b) => {
                    if Stream::is_separator(b) {
                        if buffer.len() > 0 {
                            return Stream::create_token(buffer, self.line);
                        }
                        if (b as char) == '\n' {
                            self.line += 1;
                        }
                    } else {
                        buffer.push(b);
                    }
                },
                None => {
                    return Stream::create_token(buffer, self.line);
                }
            }
        }
    }

    pub fn line(&self) -> u32 {
        self.line
    }

    fn create_token(input: Vec<u8>, line: u32) -> Option<Token> {
        let token_str: String = String::from_utf8(input).unwrap_or_else(|err| {
            println!("Error: {:?}", err);
            "".to_owned()
        }).to_lowercase();

        let (numeric, radix) = Stream::is_numeric(&token_str);
        if numeric {
            return match radix {
                // base 10
                0 => Some(Token::ImmConst(token_str.parse::<u16>().unwrap(), line)),
                // base 16
                1 => Some(Token::ImmConst(u16::from_str_radix(&token_str[2..], 16).unwrap(), line)),
                _ => None,
            }

        }

        if Stream::is_register(&token_str) {
            return match token_str.as_str() {
                "v0"   => Some(Token::Reg(Register::V0, line)),
                "v1"   => Some(Token::Reg(Register::V1, line)),
                "v2"   => Some(Token::Reg(Register::V2, line)),
                "v3"   => Some(Token::Reg(Register::V3, line)),
                "v4"   => Some(Token::Reg(Register::V4, line)),
                "v5"   => Some(Token::Reg(Register::V5, line)),
                "v6"   => Some(Token::Reg(Register::V6, line)),
                "v7"   => Some(Token::Reg(Register::V7, line)),
                "v8"   => Some(Token::Reg(Register::V8, line)),
                "v9"   => Some(Token::Reg(Register::V9, line)),
                "va"   => Some(Token::Reg(Register::Va, line)),
                "vb"   => Some(Token::Reg(Register::Vb, line)),
                "vc"   => Some(Token::Reg(Register::Vc, line)),
                "vd"   => Some(Token::Reg(Register::Vd, line)),
                "ve"   => Some(Token::Reg(Register::Ve, line)),
                "vf"   => Some(Token::Reg(Register::Vf, line)),
                "sp"   => Some(Token::Reg(Register::Sp, line)),
                "st"   => Some(Token::Reg(Register::St, line)),
                "dt"   => Some(Token::Reg(Register::Dt, line)),
                "pc"   => Some(Token::Reg(Register::Pc, line)),
                "i"    => Some(Token::Reg(Register::I, line)),
                "[i]"  => Some(Token::Reg(Register::IVal, line)),
                _      => None
            }
        }

        match token_str.as_str() {
            "add"   => Some(Token::Opcode(Mnemonic::Add, line)),
            "call"  => Some(Token::Opcode(Mnemonic::Call, line)),
            "cls"   => Some(Token::Opcode(Mnemonic::Cls, line)),
            "drw"   => Some(Token::Opcode(Mnemonic::Drw, line)),
            "jp"    => Some(Token::Opcode(Mnemonic::Jp, line)),
            "ld"    => Some(Token::Opcode(Mnemonic::Ld, line)),
            "or"    => Some(Token::Opcode(Mnemonic::Or, line)),
            "ret"   => Some(Token::Opcode(Mnemonic::Ret, line)),
            "rnd"   => Some(Token::Opcode(Mnemonic::Rnd, line)),
            "se"    => Some(Token::Opcode(Mnemonic::Se, line)),
            "shl"   => Some(Token::Opcode(Mnemonic::Shl, line)),
            "shr"   => Some(Token::Opcode(Mnemonic::Shr, line)),
            "sknp"  => Some(Token::Opcode(Mnemonic::Sknp, line)),
            "skp"   => Some(Token::Opcode(Mnemonic::Skp, line)),
            "sne"   => Some(Token::Opcode(Mnemonic::Sne, line)),
            "sub"   => Some(Token::Opcode(Mnemonic::Sub, line)),
            "subn"  => Some(Token::Opcode(Mnemonic::Subn, line)),
            "sys"   => Some(Token::Opcode(Mnemonic::Sys, line)),
            "xor"   => Some(Token::Opcode(Mnemonic::Xor, line)),
            _       => None
        }
    }

    fn is_separator(b: u8) -> bool {
        match b as char {
            ','|' '|'\n' | '\t' => { true }
            _ => { false }
        }
    }

    fn is_register(input: &str) -> bool {
        input == "v0" || input == "v1" || input == "v2" ||
        input == "v3" || input == "v4" || input == "v5" ||
        input == "v6" || input == "v7" || input == "v8" ||
        input == "v9" || input == "va" || input == "vb" ||
        input == "vc" || input == "vd" || input == "ve" ||
        input == "vf" || input == "sp" || input == "st" ||
        input == "dt" || input == "pc" || input == "i" ||
        input == "[i]"
    }

    // Returns a tuple of boolean and integer
    // The input is numeric if the boolean component of the result is true
    // Integer component of result:
    //   0 => base 10
    //   1 => base 16
    fn is_numeric(input: &str) -> (bool, u8) {
        if input.len() < 1 {
            return (false, ::std::u8::MAX);
        }

        let in_bytes = input.as_bytes();
        if !Stream::is_ascii_numeric(in_bytes[0]) {
            return (false, ::std::u8::MAX);
        }

        // hex
        if input.starts_with("0x") {
            for i in 2..(in_bytes.len()) {
                if !Stream::is_ascii_hex(in_bytes[i]) {
                    return (false, ::std::u8::MAX);
                }
                return (true, 1);
            }
        } else {
            for b in in_bytes {
                if !Stream::is_ascii_numeric(*b) {
                    return (false, ::std::u8::MAX);
                }
                return (true, 0);
            }
        }
        return (false, ::std::u8::MAX);
    }

    fn is_ascii_numeric(input: u8) -> bool {
        input >= 48 && input <= 57
    }

    fn is_ascii_hex(input: u8) -> bool {
        (input >= 48 && input <= 57) || ((input >= 97 && input <= 102) || (input >= 65 && input <= 70))
    }
}
<commit_msg>Something something codegen<commit_after>use std::fs::File;
use std::io::Bytes;

#[derive(Debug)]
pub enum Mnemonic {
    Add, Call, Cls, Drw,
    Jp, Ld, Or, Ret,
    Rnd, Se, Shl, Shr,
    Sknp, Skp, Sne, Sub,
    Subn, Sys, Xor,
}

#[derive(Debug)]
pub enum Register {
    V0, V1, V2, V3,
    V4, V5, V6, V7,
    V8, V9, Va, Vb,
    Vc, Vd, Ve, Vf,
    Sp, Pc, I, St, Dt, IVal,
}

#[derive(Debug)]
pub enum Token {
    Opcode(Mnemonic, u32),
    Reg(Register, u32),
    ImmConst(u16, u32),
}

pub struct Stream {
    input: Bytes<File>,
    line: u32,
}

impl Stream {
    pub fn new(input: Bytes<File>) -> Stream {
        Stream {
            input: input,
            line: 1,
        }
    }

    pub fn next_token(&mut self) -> Option<Token> {
        let mut buffer: Vec<u8> = vec![];

        loop {
            let bs = self.input.next().map_or(None, |bm| match bm {
                Ok(b) => Some(b),
                _ => None
            });

            match bs {
                Some(b) => {
                    if Stream::is_separator(b) {
                        if buffer.len() > 0 {
                            return Stream::create_token(buffer, self.line);
                        }
                        if (b as char) == '\n' {
                            self.line += 1;
                        }
                    } else {
                        buffer.push(b);
                    }
                },
                None => {
                    return Stream::create_token(buffer, self.line);
                }
            }
        }
    }

    pub fn line(&self) -> u32 {
        self.line
    }

    fn create_token(input: Vec<u8>, line: u32) -> Option<Token> {
        let token_str: String = String::from_utf8(input).unwrap_or_else(|err| {
            println!("Error: {:?}", err);
            "".to_owned()
        }).to_lowercase();

        let (numeric, radix) = Stream::is_numeric(&token_str);
        if numeric {
            return match radix {
                // base 10
                0 => Some(Token::ImmConst(token_str.parse::<u16>().unwrap(), line)),
                // base 16
                1 => Some(Token::ImmConst(u16::from_str_radix(&token_str[2..], 16).unwrap(), line)),
                _ => None,
            }

        }

        if Stream::is_register(&token_str) {
            return match token_str.as_str() {
                "v0"   => Some(Token::Reg(Register::V0, line)),
                "v1"   => Some(Token::Reg(Register::V1, line)),
                "v2"   => Some(Token::Reg(Register::V2, line)),
                "v3"   => Some(Token::Reg(Register::V3, line)),
                "v4"   => Some(Token::Reg(Register::V4, line)),
                "v5"   => Some(Token::Reg(Register::V5, line)),
                "v6"   => Some(Token::Reg(Register::V6, line)),
                "v7"   => Some(Token::Reg(Register::V7, line)),
                "v8"   => Some(Token::Reg(Register::V8, line)),
                "v9"   => Some(Token::Reg(Register::V9, line)),
                "va"   => Some(Token::Reg(Register::Va, line)),
                "vb"   => Some(Token::Reg(Register::Vb, line)),
                "vc"   => Some(Token::Reg(Register::Vc, line)),
                "vd"   => Some(Token::Reg(Register::Vd, line)),
                "ve"   => Some(Token::Reg(Register::Ve, line)),
                "vf"   => Some(Token::Reg(Register::Vf, line)),
                "sp"   => Some(Token::Reg(Register::Sp, line)),
                "st"   => Some(Token::Reg(Register::St, line)),
                "dt"   => Some(Token::Reg(Register::Dt, line)),
                "pc"   => Some(Token::Reg(Register::Pc, line)),
                "i"    => Some(Token::Reg(Register::I, line)),
                "[i]"  => Some(Token::Reg(Register::IVal, line)),
                _      => None
            }
        }

        match token_str.as_str() {
            "add"   => Some(Token::Opcode(Mnemonic::Add, line)),
            "call"  => Some(Token::Opcode(Mnemonic::Call, line)),
            "cls"   => Some(Token::Opcode(Mnemonic::Cls, line)),
            "drw"   => Some(Token::Opcode(Mnemonic::Drw, line)),
            "jp"    => Some(Token::Opcode(Mnemonic::Jp, line)),
            "ld"    => Some(Token::Opcode(Mnemonic::Ld, line)),
            "or"    => Some(Token::Opcode(Mnemonic::Or, line)),
            "ret"   => Some(Token::Opcode(Mnemonic::Ret, line)),
            "rnd"   => Some(Token::Opcode(Mnemonic::Rnd, line)),
            "se"    => Some(Token::Opcode(Mnemonic::Se, line)),
            "shl"   => Some(Token::Opcode(Mnemonic::Shl, line)),
            "shr"   => Some(Token::Opcode(Mnemonic::Shr, line)),
            "sknp"  => Some(Token::Opcode(Mnemonic::Sknp, line)),
            "skp"   => Some(Token::Opcode(Mnemonic::Skp, line)),
            "sne"   => Some(Token::Opcode(Mnemonic::Sne, line)),
            "sub"   => Some(Token::Opcode(Mnemonic::Sub, line)),
            "subn"  => Some(Token::Opcode(Mnemonic::Subn, line)),
            "sys"   => Some(Token::Opcode(Mnemonic::Sys, line)),
            "xor"   => Some(Token::Opcode(Mnemonic::Xor, line)),
            _       => None
        }
    }

    fn is_separator(b: u8) -> bool {
        match b as char {
            ','|' '|'\n' | '\t' => { true }
            _ => { false }
        }
    }

    fn is_register(input: &str) -> bool {
        input == "v0" || input == "v1" || input == "v2" ||
        input == "v3" || input == "v4" || input == "v5" ||
        input == "v6" || input == "v7" || input == "v8" ||
        input == "v9" || input == "va" || input == "vb" ||
        input == "vc" || input == "vd" || input == "ve" ||
        input == "vf" || input == "sp" || input == "st" ||
        input == "dt" || input == "pc" || input == "i" ||
        input == "[i]"
    }

    // Returns a tuple of boolean and integer
    // The input is numeric if the boolean component of the result is true
    // Integer component of result:
    //   0 => base 10
    //   1 => base 16
    fn is_numeric(input: &str) -> (bool, u8) {
        if input.len() < 1 {
            return (false, ::std::u8::MAX);
        }

        let in_bytes = input.as_bytes();
        if !Stream::is_ascii_numeric(in_bytes[0]) {
            return (false, ::std::u8::MAX);
        }

        // hex
        if input.starts_with("0x") {
            for i in 2..(in_bytes.len()) {
                if !Stream::is_ascii_hex(in_bytes[i]) {
                    return (false, ::std::u8::MAX);
                }
                return (true, 1);
            }
        } else {
            for b in in_bytes {
                if !Stream::is_ascii_numeric(*b) {
                    return (false, ::std::u8::MAX);
                }
                return (true, 0);
            }
        }
        return (false, ::std::u8::MAX);
    }

    fn is_ascii_numeric(input: u8) -> bool {
        input >= 48 && input <= 57
    }

    fn is_ascii_hex(input: u8) -> bool {
        (input >= 48 && input <= 57) || ((input >= 97 && input <= 102) || (input >= 65 && input <= 70))
    }
}

pub fn code_gen(tokens: &Vec<Token>) -> Result<Vec<u8>, u8> {
    let mut result: Vec<u8> = vec![];

    let mut curr_opcode: Option<&Mnemonic> = None;

    for token in tokens {
        match token {
            &Token::Reg(ref r, l) => {
                println!("{:?}: {}", r, l);
            },
            &Token::Opcode(ref o, l) => {
                curr_opcode = Some(o);
                println!("{:?}: {}", o, l);
            },
            &Token::ImmConst(ref c, l) => {
                println!("{}: {}", c, l);
            }
        }
    }
    Ok(result)
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
extern crate lapin_futures as lapin;
extern crate amq_protocol;
extern crate futures;
extern crate tokio_core;
extern crate env_logger;

use amq_protocol::types::FieldTable;
use futures::future::Future;
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicConsumeOptions,BasicGetOptions,BasicPublishOptions,BasicProperties,QueueDeclareOptions};

fn main() {
  env_logger::init().unwrap();
  let mut core = Core::new().unwrap();

  let handle = core.handle();
  let addr = "127.0.0.1:5672".parse().unwrap();

  core.run(
    TcpStream::connect(&addr, &handle).and_then(|stream| {
      lapin::client::Client::connect(stream, &ConnectionOptions::default())
    }).and_then(|client| {

      client.create_confirm_channel().and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
          info!("channel {} declared queue {}", id, "hello");

          channel.basic_publish(
            "hello",
            b"hello from tokio",
            &BasicPublishOptions::default(),
            BasicProperties::default().with_user_id("guest".to_string()).with_reply_to("foobar".to_string())
          ).map(|confirmation| {
            info!("publish got confirmation: {:?}", confirmation)
          })
        })
      }).and_then(move |_| {
        client.create_channel()
      }).and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        let c = channel.clone();
        channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
          info!("channel {} declared queue {}", id, "hello");

          let ch = channel.clone();
          channel.basic_get("hello", &BasicGetOptions::default()).and_then(move |message| {
            info!("got message: {:?}", message);
            info!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
            channel.basic_ack(message.delivery_tag);
            Ok(())
          }).and_then(move |_| {
            ch.basic_consume("hello", "my_consumer", &BasicConsumeOptions::default())
          })
        }).and_then(|stream| {
          info!("got consumer stream");

          stream.for_each(move |message| {
            debug!("got message: {:?}", message);
            info!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
            c.basic_ack(message.delivery_tag);
            Ok(())
          })
        })
      })
    })
  ).unwrap();
}
<commit_msg>futures: create exchange and bind queue to it in example<commit_after>#[macro_use] extern crate log;
extern crate lapin_futures as lapin;
extern crate amq_protocol;
extern crate futures;
extern crate tokio_core;
extern crate env_logger;

use amq_protocol::types::FieldTable;
use futures::future::Future;
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
use lapin::client::ConnectionOptions;
use lapin::channel::{BasicConsumeOptions,BasicGetOptions,BasicPublishOptions,BasicProperties,ExchangeDeclareOptions,QueueBindOptions,QueueDeclareOptions};

fn main() {
  env_logger::init().unwrap();
  let mut core = Core::new().unwrap();

  let handle = core.handle();
  let addr = "127.0.0.1:5672".parse().unwrap();

  core.run(
    TcpStream::connect(&addr, &handle).and_then(|stream| {
      lapin::client::Client::connect(stream, &ConnectionOptions::default())
    }).and_then(|client| {

      client.create_confirm_channel().and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
          info!("channel {} declared queue {}", id, "hello");

          channel.exchange_declare("hello_exchange", "direct", &ExchangeDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
            channel.queue_bind("hello", "hello_exchange", "hello_2", &QueueBindOptions::default(), FieldTable::new()).and_then(move |_| {
              channel.basic_publish(
                "hello_2",
                b"hello from tokio",
                &BasicPublishOptions {
                  exchange: "hello_exchange".to_string(),
                  ..Default::default()
                },
                BasicProperties::default().with_user_id("guest".to_string()).with_reply_to("foobar".to_string())
              ).map(|confirmation| {
                info!("publish got confirmation: {:?}", confirmation)
              })
            })
          })
        })
      }).and_then(move |_| {
        client.create_channel()
      }).and_then(|channel| {
        let id = channel.id;
        info!("created channel with id: {}", id);

        let c = channel.clone();
        channel.queue_declare("hello", &QueueDeclareOptions::default(), FieldTable::new()).and_then(move |_| {
          info!("channel {} declared queue {}", id, "hello");

          let ch = channel.clone();
          channel.basic_get("hello", &BasicGetOptions::default()).and_then(move |message| {
            info!("got message: {:?}", message);
            info!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
            channel.basic_ack(message.delivery_tag);
            Ok(())
          }).and_then(move |_| {
            ch.basic_consume("hello", "my_consumer", &BasicConsumeOptions::default())
          })
        }).and_then(|stream| {
          info!("got consumer stream");

          stream.for_each(move |message| {
            debug!("got message: {:?}", message);
            info!("decoded message: {:?}", std::str::from_utf8(&message.data).unwrap());
            c.basic_ack(message.delivery_tag);
            Ok(())
          })
        })
      })
    })
  ).unwrap();
}
<|endoftext|>