<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;

use toml::Value;
use clap::App;

use error::RuntimeError as RE;
use error::RuntimeErrorKind as REK;
use error::Result;
use error::ResultExt;

/// Get a new configuration object.
///
/// The passed runtimepath is used for searching the configuration file, whereas several file
/// names are tested. If that does not work, the home directory and the XDG basedir are tested
/// with all variants.
///
/// If that doesn't work either, an error is returned.
pub fn fetch_config(searchpath: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;
    use libimagerror::trace::trace_error;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(String::from(v));
        base
    };

    vec![
        vec![searchpath.clone()],
        gen_vars(searchpath.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .filter_map(|path| {
            let content = {
                let f = File::open(path);
                if f.is_err() {
                    let _ = write!(stderr(), "Error opening file: {:?}", f);
                    return None
                }
                let mut f = f.unwrap();

                let mut s = String::new();
                f.read_to_string(&mut s).ok();
                s
            };

            ::toml::de::from_str::<::toml::Value>(&content[..])
                .map(Some)
                .unwrap_or_else(|e| {
                    let line_col = e
                        .line_col()
                        .map(|(line, col)| format!("Line {}, Column {}", line, col))
                        .unwrap_or_else(|| String::from("Line unknown, Column unknown"));

                    let _ = write!(stderr(), "Config file parser error at {}", line_col);
                    trace_error(&e);
                    None
                })
        })
        .nth(0)
        .ok_or(RE::from_kind(REK::ConfigNoConfigFileFound))
}

/// Override the configuration.
/// The `v` parameter is expected to contain 'key=value' pairs where the key is a path in the
/// TOML tree, the value to be an appropriate value.
///
/// The override fails if the configuration which is about to be overridden does not exist or
/// the `value` part cannot be converted to the type of the configuration value.
///
/// If `v` is empty, this is considered to be a successful `override_config()` call.
pub fn override_config(val: &mut Value, v: Vec<String>) -> Result<()> {
    use libimagutil::key_value_split::*;
    use toml_query::read::TomlValueReadExt;

    let iter = v.into_iter()
        .map(|s| { debug!("Trying to process '{}'", s); s })
        .filter_map(|s| s.into_kv().map(Into::into).or_else(|| {
            warn!("Could split at '=' - will be ignore override");
            None
        }))
        .map(|(k, v)| val
             .read(&k[..])
             .chain_err(|| REK::ConfigTOMLParserError)
             .map(|toml| match toml {
                Some(value) => match into_value(value, v) {
                    Some(v) => {
                        info!("Successfully overridden: {} = {}", k, v);
                        Ok(())
                    },
                    None => Err(RE::from_kind(REK::ConfigOverrideTypeNotMatching)),
                },
                None => Err(RE::from_kind(REK::ConfigOverrideKeyNotAvailable)),
            })
        );

    for elem in iter {
        let _ = try!(elem.chain_err(|| REK::ConfigOverrideError));
    }

    Ok(())
}

/// Tries to convert the String `s` into the same type as `value`.
///
/// Returns None if string cannot be converted.
///
/// Arrays and Tables are not supported and will yield `None`.
fn into_value(value: &Value, s: String) -> Option<Value> {
    use std::str::FromStr;

    match *value {
        Value::String(_)  => Some(Value::String(s)),
        Value::Integer(_) => FromStr::from_str(&s[..]).ok().map(Value::Integer),
        Value::Float(_)   => FromStr::from_str(&s[..]).ok().map(Value::Float),
        Value::Boolean(_) => {
            if s == "true" { Some(Value::Boolean(true)) }
            else if s == "false" { Some(Value::Boolean(false)) }
            else { None }
        }
        Value::Datetime(_) => Value::try_from(s).ok(),
        _ => None,
    }
}

pub trait InternalConfiguration {
    fn enable_logging(&self) -> bool {
        true
    }

    fn use_inmemory_fs(&self) -> bool {
        false
    }
}

impl<'a> InternalConfiguration for App<'a, 'a> {}

<commit_msg>Replace matching with function chaining<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;

use toml::Value;
use clap::App;

use error::RuntimeError as RE;
use error::RuntimeErrorKind as REK;
use error::Result;
use error::ResultExt;

/// Get a new configuration object.
///
/// The passed runtimepath is used for searching the configuration file, whereas several file
/// names are tested. If that does not work, the home directory and the XDG basedir are tested
/// with all variants.
///
/// If that doesn't work either, an error is returned.
pub fn fetch_config(searchpath: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;
    use libimagerror::trace::trace_error;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(String::from(v));
        base
    };

    vec![
        vec![searchpath.clone()],
        gen_vars(searchpath.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .filter_map(|path| {
            let content = {
                let f = File::open(path);
                if f.is_err() {
                    let _ = write!(stderr(), "Error opening file: {:?}", f);
                    return None
                }
                let mut f = f.unwrap();

                let mut s = String::new();
                f.read_to_string(&mut s).ok();
                s
            };

            ::toml::de::from_str::<::toml::Value>(&content[..])
                .map(Some)
                .unwrap_or_else(|e| {
                    let line_col = e
                        .line_col()
                        .map(|(line, col)| format!("Line {}, Column {}", line, col))
                        .unwrap_or_else(|| String::from("Line unknown, Column unknown"));

                    let _ = write!(stderr(), "Config file parser error at {}", line_col);
                    trace_error(&e);
                    None
                })
        })
        .nth(0)
        .ok_or(RE::from_kind(REK::ConfigNoConfigFileFound))
}

/// Override the configuration.
/// The `v` parameter is expected to contain 'key=value' pairs where the key is a path in the
/// TOML tree, the value to be an appropriate value.
///
/// The override fails if the configuration which is about to be overridden does not exist or
/// the `value` part cannot be converted to the type of the configuration value.
///
/// If `v` is empty, this is considered to be a successful `override_config()` call.
pub fn override_config(val: &mut Value, v: Vec<String>) -> Result<()> {
    use libimagutil::key_value_split::*;
    use toml_query::read::TomlValueReadExt;

    let iter = v.into_iter()
        .map(|s| { debug!("Trying to process '{}'", s); s })
        .filter_map(|s| s.into_kv().map(Into::into).or_else(|| {
            warn!("Could split at '=' - will be ignore override");
            None
        }))
        .map(|(k, v)| {
            let value = val
                .read(&k)
                .chain_err(|| REK::ConfigTOMLParserError)?
                .ok_or(RE::from_kind(REK::ConfigOverrideKeyNotAvailable))?;

            into_value(value, v)
                .map(|v| info!("Successfully overridden: {} = {}", k, v))
                .ok_or_else(|| RE::from_kind(REK::ConfigOverrideTypeNotMatching))
        });

    for elem in iter {
        let _ = try!(elem.chain_err(|| REK::ConfigOverrideError));
    }

    Ok(())
}

/// Tries to convert the String `s` into the same type as `value`.
///
/// Returns None if string cannot be converted.
///
/// Arrays and Tables are not supported and will yield `None`.
fn into_value(value: &Value, s: String) -> Option<Value> {
    use std::str::FromStr;

    match *value {
        Value::String(_)  => Some(Value::String(s)),
        Value::Integer(_) => FromStr::from_str(&s[..]).ok().map(Value::Integer),
        Value::Float(_)   => FromStr::from_str(&s[..]).ok().map(Value::Float),
        Value::Boolean(_) => {
            if s == "true" { Some(Value::Boolean(true)) }
            else if s == "false" { Some(Value::Boolean(false)) }
            else { None }
        }
        Value::Datetime(_) => Value::try_from(s).ok(),
        _ => None,
    }
}

pub trait InternalConfiguration {
    fn enable_logging(&self) -> bool {
        true
    }

    fn use_inmemory_fs(&self) -> bool {
        false
    }
}

impl<'a> InternalConfiguration for App<'a, 'a> {}

<|endoftext|>


<commit_before>use crate::server::ServerData;
use crate::Database;
use actix_web::{error::ResponseError, get, http::StatusCode, web, HttpRequest, HttpResponse};
use cemu_smm::proto::SMMCourse::{
    SMMCourse_AutoScroll, SMMCourse_CourseTheme, SMMCourse_GameStyle,
};
use mongodb::{oid::ObjectId, ordered::OrderedDocument, Bson};
use protobuf::ProtobufEnum;
use serde::Deserialize;
use serde_qs::actix::QsQuery;
use std::sync::MutexGuard;

#[get("/getcourses")]
pub fn get_courses(
    data: web::Data<ServerData>,
    query: QsQuery<GetCourses>,
    req: HttpRequest,
) -> Result<String, GetCoursesError> {
    data.get_courses(query.into_inner())
}

#[derive(Deserialize, Debug)]
pub struct GetCourses {
    #[serde(default)]
    limit: Limit,
    skip: Option<u32>,
    id: Option<String>,
    ids: Option<Vec<String>>,
    title: Option<String>,
    maker: Option<String>,
    owner: Option<String>,
    uploader: Option<String>,
    game_style: Option<Vec<SMMCourse_GameStyle>>,
    course_theme: Option<Vec<SMMCourse_CourseTheme>>,
    course_theme_sub: Option<Vec<SMMCourse_CourseTheme>>,
    auto_scroll: Option<Vec<SMMCourse_AutoScroll>>,
    auto_scroll_sub: Option<Vec<SMMCourse_AutoScroll>>,
    width_from: Option<i32>,
    width_to: Option<i32>,
    width_sub_from: Option<i32>,
    width_sub_to: Option<i32>,
    nintendoid: Option<String>,
    difficulty_from: Option<u32>,
    difficulty_to: Option<u32>,
    videoid: Option<String>,
    lastmodified_from: Option<u32>,
    lastmodified_to: Option<u32>,
    uploaded_from: Option<u32>,
    uploaded_to: Option<u32>,
    stars_from: Option<u32>,
    stars_to: Option<u32>,
}

impl GetCourses {
    pub fn into_ordered_document(
        self,
        database: &MutexGuard<Database>,
    ) -> Result<Vec<OrderedDocument>, GetCoursesError> {
        let mut pipeline = vec![];

        if let Some(pipeline_match) = self.get_match(database)? {
            pipeline.push(doc! { "$match" => pipeline_match });
        }

        let limit = self.get_limit()?;
        pipeline.push(doc! {
            "$limit" => limit
        });

        if let Some(skip) = self.skip {
            pipeline.push(doc! {
                "$skip" => skip
            });
        }

        Ok(pipeline)
    }

    fn get_match(
        &self,
        database: &MutexGuard<Database>,
    ) -> Result<Option<OrderedDocument>, GetCoursesError> {
        let mut res = doc! {};
        if let Some(id) = &self.id {
            GetCourses::insert_objectid(&mut res, "_id".to_string(), id)?;
        }

        if let Some(ids) = self.ids.clone() {
            let ids: Vec<Bson> = ids
                .iter()
                .map(|id| -> Result<Bson, GetCoursesError> {
                    let object_id = ObjectId::with_string(id)
                        .map_err(|_| GetCoursesError::DeserializeError("ids".to_string()))?;
                    Ok(Bson::ObjectId(object_id))
                })
                .filter_map(Result::ok)
                .collect();
            res.insert_bson(
                "_id".to_string(),
                Bson::Document(doc! {
                    "$in" => ids
                }),
            );
        }

        if let Some(title) = self.title.clone() {
            GetCourses::insert_regexp(&mut res, "title".to_string(), title);
        }

        if let Some(maker) = self.maker.clone() {
            GetCourses::insert_regexp(&mut res, "maker".to_string(), maker);
        }

        if let Some(owner) = &self.owner {
            GetCourses::insert_objectid(&mut res, "owner".to_string(), owner)?;
        }

        if let Some(uploader) = &self.uploader {
            let filter = doc! {
                "username" => Bson::RegExp(format!("^{}$", uploader), "i".to_string())
            };
            match database.find_account(filter) {
                Some(account) => {
                    res.insert_bson("owner".to_string(), Bson::ObjectId(account.get_id()));
                }
                None => return Err(GetCoursesError::UploaderUnknown(uploader.clone())),
            };
        }

        if let Some(game_styles) = &self.game_style {
            let game_styles: Vec<Bson> = game_styles
                .iter()
                .map(|game_style| Bson::I32(game_style.value()))
                .collect();
            res.insert_bson(
                "gameStyle".to_string(),
                Bson::Document(doc! {
                    "$in" => game_styles
                }),
            );
        }

        if let Some(course_themes) = &self.course_theme {
            let course_themes: Vec<Bson> = course_themes
                .iter()
                .map(|course_theme| Bson::I32(course_theme.value()))
                .collect();
            res.insert_bson(
                "courseTheme".to_string(),
                Bson::Document(doc! {
                    "$in" => course_themes
                }),
            );
        }

        if let Some(course_themes) = &self.course_theme_sub {
            let course_themes: Vec<Bson> = course_themes
                .iter()
                .map(|course_theme| Bson::I32(course_theme.value()))
                .collect();
            res.insert_bson(
                "courseThemeSub".to_string(),
                Bson::Document(doc! {
                    "$in" => course_themes
                }),
            );
        }

        match res.is_empty() {
            true => Ok(None),
            false => Ok(Some(res)),
        }
    }

    fn get_limit(&self) -> Result<u32, GetCoursesError> {
        let limit = self.limit.0;
        if limit <= 0 {
            return Err(GetCoursesError::LimitTooLow);
        }
        if limit > 120 {
            return Err(GetCoursesError::LimitTooHigh);
        }
        Ok(limit + self.skip.unwrap_or_default())
    }

    fn insert_regexp(doc: &mut OrderedDocument, key: String, regexp: String) {
        doc.insert_bson(
            key,
            Bson::RegExp(format!(".*{}.*", regexp), "i".to_string()),
        );
    }

    fn insert_objectid(
        doc: &mut OrderedDocument,
        key: String,
        oid: &str,
    ) -> Result<(), GetCoursesError> {
        doc.insert_bson(
            key.clone(),
            Bson::ObjectId(
                ObjectId::with_string(oid).map_err(|_| GetCoursesError::DeserializeError(key))?,
            ),
        );
        Ok(())
    }
}

#[derive(Deserialize, Debug)]
struct Limit(u32);

impl Default for Limit {
    fn default() -> Limit {
        Limit(120)
    }
}

#[derive(Fail, Debug)]
pub enum GetCoursesError {
    #[fail(display = "limit must be at least 1")]
    LimitTooLow,
    #[fail(display = "limit must be at most 120")]
    LimitTooHigh,
    #[fail(display = "could not deserialize {} fom hex string", _0)]
    DeserializeError(String),
    #[fail(display = "uploader with name {} unknown", _0)]
    UploaderUnknown(String),
}

impl ResponseError for GetCoursesError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            GetCoursesError::LimitTooLow => HttpResponse::new(StatusCode::BAD_REQUEST),
            GetCoursesError::LimitTooHigh => HttpResponse::new(StatusCode::BAD_REQUEST),
            GetCoursesError::DeserializeError(_) => HttpResponse::new(StatusCode::BAD_REQUEST),
            GetCoursesError::UploaderUnknown(_) => HttpResponse::new(StatusCode::BAD_REQUEST),
        }
    }
}
<commit_msg>add autoscroll filter<commit_after>use crate::server::ServerData;
use crate::Database;

use actix_web::{error::ResponseError, get, http::StatusCode, web, HttpRequest, HttpResponse};
use cemu_smm::proto::SMMCourse::{
    SMMCourse_AutoScroll, SMMCourse_CourseTheme, SMMCourse_GameStyle,
};
use mongodb::{oid::ObjectId, ordered::OrderedDocument, Bson};
use protobuf::ProtobufEnum;
use serde::Deserialize;
use serde_qs::actix::QsQuery;
use std::sync::MutexGuard;

#[get("/getcourses")]
pub fn get_courses(
    data: web::Data<ServerData>,
    query: QsQuery<GetCourses>,
    req: HttpRequest,
) -> Result<String, GetCoursesError> {
    data.get_courses(query.into_inner())
}

#[derive(Deserialize, Debug)]
pub struct GetCourses {
    #[serde(default)]
    limit: Limit,
    skip: Option<u32>,
    id: Option<String>,
    ids: Option<Vec<String>>,
    title: Option<String>,
    maker: Option<String>,
    owner: Option<String>,
    uploader: Option<String>,
    game_style: Option<Vec<SMMCourse_GameStyle>>,
    course_theme: Option<Vec<SMMCourse_CourseTheme>>,
    course_theme_sub: Option<Vec<SMMCourse_CourseTheme>>,
    auto_scroll: Option<Vec<SMMCourse_AutoScroll>>,
    auto_scroll_sub: Option<Vec<SMMCourse_AutoScroll>>,
    width_from: Option<i32>,
    width_to: Option<i32>,
    width_sub_from: Option<i32>,
    width_sub_to: Option<i32>,
    nintendoid: Option<String>,
    difficulty_from: Option<u32>,
    difficulty_to: Option<u32>,
    videoid: Option<String>,
    lastmodified_from: Option<u32>,
    lastmodified_to: Option<u32>,
    uploaded_from: Option<u32>,
    uploaded_to: Option<u32>,
    stars_from: Option<u32>,
    stars_to: Option<u32>,
}

impl GetCourses {
    pub fn into_ordered_document(
        self,
        database: &MutexGuard<Database>,
    ) -> Result<Vec<OrderedDocument>, GetCoursesError> {
        let mut pipeline = vec![];

        if let Some(pipeline_match) = self.get_match(database)? {
            pipeline.push(doc! { "$match" => pipeline_match });
        }

        let limit = self.get_limit()?;
        pipeline.push(doc! {
            "$limit" => limit
        });

        if let Some(skip) = self.skip {
            pipeline.push(doc! {
                "$skip" => skip
            });
        }

        Ok(pipeline)
    }

    fn get_match(
        &self,
        database: &MutexGuard<Database>,
    ) -> Result<Option<OrderedDocument>, GetCoursesError> {
        let mut res = doc! {};
        if let Some(id) = &self.id {
            GetCourses::insert_objectid(&mut res, "_id".to_string(), id)?;
        }

        if let Some(ids) = self.ids.clone() {
            let ids: Vec<Bson> = ids
                .iter()
                .map(|id| -> Result<Bson, GetCoursesError> {
                    let object_id = ObjectId::with_string(id)
                        .map_err(|_| GetCoursesError::DeserializeError("ids".to_string()))?;
                    Ok(Bson::ObjectId(object_id))
                })
                .filter_map(Result::ok)
                .collect();
            res.insert_bson(
                "_id".to_string(),
                Bson::Document(doc! {
                    "$in" => ids
                }),
            );
        }

        if let Some(title) = self.title.clone() {
            GetCourses::insert_regexp(&mut res, "title".to_string(), title);
        }

        if let Some(maker) = self.maker.clone() {
            GetCourses::insert_regexp(&mut res, "maker".to_string(), maker);
        }

        if let Some(owner) = &self.owner {
            GetCourses::insert_objectid(&mut res, "owner".to_string(), owner)?;
        }

        if let Some(uploader) = &self.uploader {
            let filter = doc! {
                "username" => Bson::RegExp(format!("^{}$", uploader), "i".to_string())
            };
            match database.find_account(filter) {
                Some(account) => {
                    res.insert_bson("owner".to_string(), Bson::ObjectId(account.get_id()));
                }
                None => return Err(GetCoursesError::UploaderUnknown(uploader.clone())),
            };
        }

        if let Some(game_styles) = &self.game_style {
            GetCourses::insert_enum(&mut res, "gameStyle".to_string(), game_styles);
        }

        if let Some(course_themes) = &self.course_theme {
            GetCourses::insert_enum(&mut res, "courseTheme".to_string(), course_themes);
        }

        if let Some(course_themes) = &self.course_theme_sub {
            GetCourses::insert_enum(&mut res, "courseThemeSub".to_string(), course_themes);
        }

        if let Some(auto_scrolls) = &self.auto_scroll {
            GetCourses::insert_enum(&mut res, "autoScroll".to_string(), auto_scrolls);
        }

        if let Some(auto_scrolls) = &self.auto_scroll_sub {
            GetCourses::insert_enum(&mut res, "autoScrollSub".to_string(), auto_scrolls);
        }

        match res.is_empty() {
            true => Ok(None),
            false => Ok(Some(res)),
        }
    }

    fn get_limit(&self) -> Result<u32, GetCoursesError> {
        let limit = self.limit.0;
        if limit <= 0 {
            return Err(GetCoursesError::LimitTooLow);
        }
        if limit > 120 {
            return Err(GetCoursesError::LimitTooHigh);
        }
        Ok(limit + self.skip.unwrap_or_default())
    }

    fn insert_regexp(doc: &mut OrderedDocument, key: String, regexp: String) {
        doc.insert_bson(
            key,
            Bson::RegExp(format!(".*{}.*", regexp), "i".to_string()),
        );
    }

    fn insert_objectid(
        doc: &mut OrderedDocument,
        key: String,
        oid: &str,
    ) -> Result<(), GetCoursesError> {
        doc.insert_bson(
            key.clone(),
            Bson::ObjectId(
                ObjectId::with_string(oid).map_err(|_| GetCoursesError::DeserializeError(key))?,
            ),
        );
        Ok(())
    }

    fn insert_enum<T>(doc: &mut OrderedDocument, key: String, enums: &Vec<T>)
    where
        T: ProtobufEnum,
    {
        let enums: Vec<Bson> = enums.iter().map(|val| Bson::I32(val.value())).collect();
        doc.insert_bson(
            key.to_string(),
            Bson::Document(doc! {
                "$in" => enums
            }),
        );
    }
}

#[derive(Deserialize, Debug)]
struct Limit(u32);

impl Default for Limit {
    fn default() -> Limit {
        Limit(120)
    }
}

#[derive(Fail, Debug)]
pub enum GetCoursesError {
    #[fail(display = "limit must be at least 1")]
    LimitTooLow,
    #[fail(display = "limit must be at most 120")]
    LimitTooHigh,
    #[fail(display = "could not deserialize {} fom hex string", _0)]
    DeserializeError(String),
    #[fail(display = "uploader with name {} unknown", _0)]
    UploaderUnknown(String),
}

impl ResponseError for GetCoursesError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            GetCoursesError::LimitTooLow => HttpResponse::new(StatusCode::BAD_REQUEST),
            GetCoursesError::LimitTooHigh => HttpResponse::new(StatusCode::BAD_REQUEST),
            GetCoursesError::DeserializeError(_) => HttpResponse::new(StatusCode::BAD_REQUEST),
            GetCoursesError::UploaderUnknown(_) => HttpResponse::new(StatusCode::BAD_REQUEST),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Evgeniy Reizner
//
// 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.

use std::fmt;

use {
    AspectRatio,
    AttributeId,
    Color,
    Length,
    LengthList,
    LengthUnit,
    Node,
    NumberList,
    PaintFallback,
    Path,
    Points,
    Transform,
    ValueWriteBuffer,
    ViewBox,
    WriteBuffer,
    WriteOptions,
};

// TODO: custom debug

/// Value of the SVG attribute.
#[derive(Clone,PartialEq,Debug)]
#[allow(missing_docs)]
pub enum AttributeValue {
    None,
    Inherit,
    CurrentColor,
    AspectRatio(AspectRatio),
    Color(Color),
    /// FuncIRI
    FuncLink(Node),
    Paint(Node, Option<PaintFallback>),
    Length(Length),
    LengthList(LengthList),
    /// IRI
    Link(Node),
    Number(f64),
    NumberList(NumberList),
    Path(Path),
    Points(Points),
    Transform(Transform),
    ViewBox(ViewBox),
    String(String),
}

macro_rules! impl_from {
    ($vt:ty, $vtn:ident) => (
        impl From<$vt> for AttributeValue {
            fn from(value: $vt) -> AttributeValue {
                AttributeValue::$vtn(value)
            }
        }
    )
}

impl_from!(AspectRatio, AspectRatio);
impl_from!(Color, Color);
impl_from!(Length, Length);
impl_from!(LengthList, LengthList);
impl_from!(f64, Number);
impl_from!(NumberList, NumberList);
impl_from!(Path, Path);
impl_from!(Points, Points);
impl_from!(String, String);
impl_from!(Transform, Transform);
impl_from!(ViewBox, ViewBox);

// TODO: bad, hidden allocation
impl<'a> From<&'a str> for AttributeValue {
    fn from(value: &str) -> AttributeValue {
        AttributeValue::String(value.to_owned())
    }
}

impl From<i32> for AttributeValue {
    fn from(value: i32) -> AttributeValue {
        AttributeValue::Number(f64::from(value))
    }
}

impl From<(i32, LengthUnit)> for AttributeValue {
    fn from(value: (i32, LengthUnit)) -> AttributeValue {
        AttributeValue::Length(Length::new(f64::from(value.0), value.1))
    }
}

impl From<(f64, LengthUnit)> for AttributeValue {
    fn from(value: (f64, LengthUnit)) -> AttributeValue {
        AttributeValue::Length(Length::new(value.0, value.1))
    }
}

// TODO: fix docs
macro_rules! impl_is_type {
    ($name:ident, $t:ident) => (
        #[allow(missing_docs)]
        pub fn $name(&self) -> bool {
            match *self {
                AttributeValue::$t(..) => true,
                _ => false,
            }
        }
    )
}

macro_rules! impl_is_type_without_value {
    ($name:ident, $t:ident) => (
        #[allow(missing_docs)]
        pub fn $name(&self) -> bool {
            match *self {
                AttributeValue::$t => true,
                _ => false,
            }
        }
    )
}

impl AttributeValue {
    impl_is_type_without_value!(is_none, None);
    impl_is_type_without_value!(is_inherit, Inherit);
    impl_is_type_without_value!(is_current_color, CurrentColor);
    impl_is_type!(is_aspect_ratio, AspectRatio);
    impl_is_type!(is_color, Color);
    impl_is_type!(is_length, Length);
    impl_is_type!(is_length_list, LengthList);
    impl_is_type!(is_link, Link);
    impl_is_type!(is_func_link, FuncLink);
    impl_is_type!(is_paint, Paint);
    impl_is_type!(is_number, Number);
    impl_is_type!(is_number_list, NumberList);
    impl_is_type!(is_path, Path);
    impl_is_type!(is_points, Points);
    impl_is_type!(is_string, String);
    impl_is_type!(is_transform, Transform);
    impl_is_type!(is_viewbox, ViewBox);

    /// Constructs a new attribute value with a default value, if it's known.
    pub fn default_value(id: AttributeId) -> Option<AttributeValue> {
        macro_rules! some {
            ($expr:expr) => (Some(AttributeValue::from($expr)))
        }

        match id {
              AttributeId::AlignmentBaseline
            | AttributeId::Clip
            | AttributeId::ColorProfile
            | AttributeId::ColorRendering
            | AttributeId::Cursor
            | AttributeId::DominantBaseline
            | AttributeId::GlyphOrientationVertical
            | AttributeId::ImageRendering
            | AttributeId::Kerning
            | AttributeId::ShapeRendering
            | AttributeId::TextRendering => some!("auto"),

              AttributeId::ClipPath
            | AttributeId::Filter
            | AttributeId::FontSizeAdjust
            | AttributeId::Marker
            | AttributeId::MarkerEnd
            | AttributeId::MarkerMid
            | AttributeId::MarkerStart
            | AttributeId::Mask
            | AttributeId::Stroke
            | AttributeId::StrokeDasharray
            | AttributeId::TextDecoration => Some(AttributeValue::None),

              AttributeId::FontStretch
            | AttributeId::FontStyle
            | AttributeId::FontVariant
            | AttributeId::FontWeight
            | AttributeId::LetterSpacing
            | AttributeId::UnicodeBidi
            | AttributeId::WordSpacing => some!("normal"),

              AttributeId::Fill
            | AttributeId::FloodColor
            | AttributeId::StopColor => some!(Color::new(0, 0, 0)),

              AttributeId::FillOpacity
            | AttributeId::FloodOpacity
            | AttributeId::Opacity
            | AttributeId::StopOpacity
            | AttributeId::StrokeOpacity => some!(1.0),

              AttributeId::ClipRule
            | AttributeId::FillRule => some!("nonzero"),

            AttributeId::BaselineShift =>               some!("baseline"),
            AttributeId::ColorInterpolation =>          some!("sRGB"),
            AttributeId::ColorInterpolationFilters =>   some!("linearRGB"),
            AttributeId::Direction =>                   some!("ltr"),
            AttributeId::Display =>                     some!("inline"),
            AttributeId::EnableBackground =>            some!("accumulate"),
            AttributeId::FontSize =>                    some!("medium"),
            AttributeId::GlyphOrientationHorizontal =>  some!("0deg"),
            AttributeId::LightingColor =>               some!(Color::new(255, 255, 255)),
            AttributeId::StrokeDashoffset =>            some!((0.0, LengthUnit::None)),
            AttributeId::StrokeLinecap =>               some!("butt"),
            AttributeId::StrokeLinejoin =>              some!("miter"),
            AttributeId::StrokeMiterlimit =>            some!((4.0, LengthUnit::None)),
            AttributeId::StrokeWidth =>                 some!((1.0, LengthUnit::None)),
            AttributeId::TextAnchor =>                  some!("start"),
            AttributeId::Visibility =>                  some!("visible"),
            AttributeId::WritingMode =>                 some!("lr-tb"),
            _ => None,
        }
    }
}

impl WriteBuffer for AttributeValue {
    fn write_buf_opt(&self, opt: &WriteOptions, buf: &mut Vec<u8>) {
        match *self {
            AttributeValue::None => {
                buf.extend_from_slice(b"none");
            }
            AttributeValue::Inherit => {
                buf.extend_from_slice(b"inherit");
            }
            AttributeValue::CurrentColor => {
                buf.extend_from_slice(b"currentColor");
            }
            AttributeValue::String(ref s) => {
                for c in s.as_bytes() {
                    match *c {
                        b'"' if !opt.use_single_quote => buf.extend_from_slice(b"""),
                        b'\'' if opt.use_single_quote => buf.extend_from_slice(b"'"),
                        _ => buf.push(*c),
                    }
                }
            }
            AttributeValue::Number(ref n) => {
                n.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::NumberList(ref list) => {
                list.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Length(ref l) => {
                l.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::LengthList(ref list) => {
                list.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Transform(ref t) => {
                t.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Path(ref p) => {
                p.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Points(ref p) => {
                p.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Link(ref n) => {
                buf.push(b'#');
                buf.extend_from_slice(n.id().as_bytes());
            }
            AttributeValue::FuncLink(ref n) => {
                buf.extend_from_slice(b"url(#");
                buf.extend_from_slice(n.id().as_bytes());
                buf.push(b')');
            }
            AttributeValue::Paint(ref n, ref fallback) => {
                buf.extend_from_slice(b"url(#");
                buf.extend_from_slice(n.id().as_bytes());
                buf.push(b')');

                if let Some(fallback) = fallback {
                    buf.push(b' ');
                    match fallback {
                        PaintFallback::None => buf.extend_from_slice(b"none"),
                        PaintFallback::CurrentColor => buf.extend_from_slice(b"currentColor"),
                        PaintFallback::Color(ref c) => c.write_buf_opt(&opt.values, buf),
                    }
                }
            }
            AttributeValue::Color(ref c) => {
                c.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::ViewBox(vb) => {
                vb.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::AspectRatio(ratio) => {
                ratio.write_buf_opt(&opt.values, buf);
            }
        }
    }
}

impl fmt::Display for AttributeValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.with_write_opt(&WriteOptions::default()))
    }
}
<commit_msg>Fixed build on 1.18.<commit_after>// Copyright 2018 Evgeniy Reizner
//
// 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.

use std::fmt;

use {
    AspectRatio,
    AttributeId,
    Color,
    Length,
    LengthList,
    LengthUnit,
    Node,
    NumberList,
    PaintFallback,
    Path,
    Points,
    Transform,
    ValueWriteBuffer,
    ViewBox,
    WriteBuffer,
    WriteOptions,
};

// TODO: custom debug

/// Value of the SVG attribute.
#[derive(Clone,PartialEq,Debug)]
#[allow(missing_docs)]
pub enum AttributeValue {
    None,
    Inherit,
    CurrentColor,
    AspectRatio(AspectRatio),
    Color(Color),
    /// FuncIRI
    FuncLink(Node),
    Paint(Node, Option<PaintFallback>),
    Length(Length),
    LengthList(LengthList),
    /// IRI
    Link(Node),
    Number(f64),
    NumberList(NumberList),
    Path(Path),
    Points(Points),
    Transform(Transform),
    ViewBox(ViewBox),
    String(String),
}

macro_rules! impl_from {
    ($vt:ty, $vtn:ident) => (
        impl From<$vt> for AttributeValue {
            fn from(value: $vt) -> AttributeValue {
                AttributeValue::$vtn(value)
            }
        }
    )
}

impl_from!(AspectRatio, AspectRatio);
impl_from!(Color, Color);
impl_from!(Length, Length);
impl_from!(LengthList, LengthList);
impl_from!(f64, Number);
impl_from!(NumberList, NumberList);
impl_from!(Path, Path);
impl_from!(Points, Points);
impl_from!(String, String);
impl_from!(Transform, Transform);
impl_from!(ViewBox, ViewBox);

// TODO: bad, hidden allocation
impl<'a> From<&'a str> for AttributeValue {
    fn from(value: &str) -> AttributeValue {
        AttributeValue::String(value.to_owned())
    }
}

impl From<i32> for AttributeValue {
    fn from(value: i32) -> AttributeValue {
        AttributeValue::Number(f64::from(value))
    }
}

impl From<(i32, LengthUnit)> for AttributeValue {
    fn from(value: (i32, LengthUnit)) -> AttributeValue {
        AttributeValue::Length(Length::new(f64::from(value.0), value.1))
    }
}

impl From<(f64, LengthUnit)> for AttributeValue {
    fn from(value: (f64, LengthUnit)) -> AttributeValue {
        AttributeValue::Length(Length::new(value.0, value.1))
    }
}

// TODO: fix docs
macro_rules! impl_is_type {
    ($name:ident, $t:ident) => (
        #[allow(missing_docs)]
        pub fn $name(&self) -> bool {
            match *self {
                AttributeValue::$t(..) => true,
                _ => false,
            }
        }
    )
}

macro_rules! impl_is_type_without_value {
    ($name:ident, $t:ident) => (
        #[allow(missing_docs)]
        pub fn $name(&self) -> bool {
            match *self {
                AttributeValue::$t => true,
                _ => false,
            }
        }
    )
}

impl AttributeValue {
    impl_is_type_without_value!(is_none, None);
    impl_is_type_without_value!(is_inherit, Inherit);
    impl_is_type_without_value!(is_current_color, CurrentColor);
    impl_is_type!(is_aspect_ratio, AspectRatio);
    impl_is_type!(is_color, Color);
    impl_is_type!(is_length, Length);
    impl_is_type!(is_length_list, LengthList);
    impl_is_type!(is_link, Link);
    impl_is_type!(is_func_link, FuncLink);
    impl_is_type!(is_paint, Paint);
    impl_is_type!(is_number, Number);
    impl_is_type!(is_number_list, NumberList);
    impl_is_type!(is_path, Path);
    impl_is_type!(is_points, Points);
    impl_is_type!(is_string, String);
    impl_is_type!(is_transform, Transform);
    impl_is_type!(is_viewbox, ViewBox);

    /// Constructs a new attribute value with a default value, if it's known.
    pub fn default_value(id: AttributeId) -> Option<AttributeValue> {
        macro_rules! some {
            ($expr:expr) => (Some(AttributeValue::from($expr)))
        }

        match id {
              AttributeId::AlignmentBaseline
            | AttributeId::Clip
            | AttributeId::ColorProfile
            | AttributeId::ColorRendering
            | AttributeId::Cursor
            | AttributeId::DominantBaseline
            | AttributeId::GlyphOrientationVertical
            | AttributeId::ImageRendering
            | AttributeId::Kerning
            | AttributeId::ShapeRendering
            | AttributeId::TextRendering => some!("auto"),

              AttributeId::ClipPath
            | AttributeId::Filter
            | AttributeId::FontSizeAdjust
            | AttributeId::Marker
            | AttributeId::MarkerEnd
            | AttributeId::MarkerMid
            | AttributeId::MarkerStart
            | AttributeId::Mask
            | AttributeId::Stroke
            | AttributeId::StrokeDasharray
            | AttributeId::TextDecoration => Some(AttributeValue::None),

              AttributeId::FontStretch
            | AttributeId::FontStyle
            | AttributeId::FontVariant
            | AttributeId::FontWeight
            | AttributeId::LetterSpacing
            | AttributeId::UnicodeBidi
            | AttributeId::WordSpacing => some!("normal"),

              AttributeId::Fill
            | AttributeId::FloodColor
            | AttributeId::StopColor => some!(Color::new(0, 0, 0)),

              AttributeId::FillOpacity
            | AttributeId::FloodOpacity
            | AttributeId::Opacity
            | AttributeId::StopOpacity
            | AttributeId::StrokeOpacity => some!(1.0),

              AttributeId::ClipRule
            | AttributeId::FillRule => some!("nonzero"),

            AttributeId::BaselineShift =>               some!("baseline"),
            AttributeId::ColorInterpolation =>          some!("sRGB"),
            AttributeId::ColorInterpolationFilters =>   some!("linearRGB"),
            AttributeId::Direction =>                   some!("ltr"),
            AttributeId::Display =>                     some!("inline"),
            AttributeId::EnableBackground =>            some!("accumulate"),
            AttributeId::FontSize =>                    some!("medium"),
            AttributeId::GlyphOrientationHorizontal =>  some!("0deg"),
            AttributeId::LightingColor =>               some!(Color::new(255, 255, 255)),
            AttributeId::StrokeDashoffset =>            some!((0.0, LengthUnit::None)),
            AttributeId::StrokeLinecap =>               some!("butt"),
            AttributeId::StrokeLinejoin =>              some!("miter"),
            AttributeId::StrokeMiterlimit =>            some!((4.0, LengthUnit::None)),
            AttributeId::StrokeWidth =>                 some!((1.0, LengthUnit::None)),
            AttributeId::TextAnchor =>                  some!("start"),
            AttributeId::Visibility =>                  some!("visible"),
            AttributeId::WritingMode =>                 some!("lr-tb"),
            _ => None,
        }
    }
}

impl WriteBuffer for AttributeValue {
    fn write_buf_opt(&self, opt: &WriteOptions, buf: &mut Vec<u8>) {
        match *self {
            AttributeValue::None => {
                buf.extend_from_slice(b"none");
            }
            AttributeValue::Inherit => {
                buf.extend_from_slice(b"inherit");
            }
            AttributeValue::CurrentColor => {
                buf.extend_from_slice(b"currentColor");
            }
            AttributeValue::String(ref s) => {
                for c in s.as_bytes() {
                    match *c {
                        b'"' if !opt.use_single_quote => buf.extend_from_slice(b"""),
                        b'\'' if opt.use_single_quote => buf.extend_from_slice(b"'"),
                        _ => buf.push(*c),
                    }
                }
            }
            AttributeValue::Number(ref n) => {
                n.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::NumberList(ref list) => {
                list.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Length(ref l) => {
                l.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::LengthList(ref list) => {
                list.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Transform(ref t) => {
                t.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Path(ref p) => {
                p.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Points(ref p) => {
                p.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::Link(ref n) => {
                buf.push(b'#');
                buf.extend_from_slice(n.id().as_bytes());
            }
            AttributeValue::FuncLink(ref n) => {
                buf.extend_from_slice(b"url(#");
                buf.extend_from_slice(n.id().as_bytes());
                buf.push(b')');
            }
            AttributeValue::Paint(ref n, ref fallback) => {
                buf.extend_from_slice(b"url(#");
                buf.extend_from_slice(n.id().as_bytes());
                buf.push(b')');

                if let Some(fallback) = *fallback {
                    buf.push(b' ');
                    match fallback {
                        PaintFallback::None => buf.extend_from_slice(b"none"),
                        PaintFallback::CurrentColor => buf.extend_from_slice(b"currentColor"),
                        PaintFallback::Color(ref c) => c.write_buf_opt(&opt.values, buf),
                    }
                }
            }
            AttributeValue::Color(ref c) => {
                c.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::ViewBox(vb) => {
                vb.write_buf_opt(&opt.values, buf);
            }
            AttributeValue::AspectRatio(ratio) => {
                ratio.write_buf_opt(&opt.values, buf);
            }
        }
    }
}

impl fmt::Display for AttributeValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.with_write_opt(&WriteOptions::default()))
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use base::{
    AbstractCFTypeRef,
    CFAllocatorRef,
    CFIndex,
    CFTypeID,
    CFTypeRef,
    CFWrapper,
    kCFAllocatorDefault,
};
use std::cast;
use std::libc::c_void;
use std::ptr;
use std::vec;
use std::iterator::Enumerate;

pub type CFArrayRetainCallBack = *u8;
pub type CFArrayReleaseCallBack = *u8;
pub type CFArrayCopyDescriptionCallBack = *u8;
pub type CFArrayEqualCallBack = *u8;

pub struct CFArrayCallBacks {
    version: CFIndex,
    retain: CFArrayRetainCallBack,
    release: CFArrayReleaseCallBack,
    copyDescription: CFArrayCopyDescriptionCallBack,
    equal: CFArrayEqualCallBack,
}

struct __CFArray { private: () }
pub type CFArrayRef = *__CFArray;

impl AbstractCFTypeRef for CFArrayRef {
    fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef }
    fn type_id() -> CFTypeID { unsafe { CFArrayGetTypeID() } }
}

// FIXME: Should be a newtype struct, but that fails due to a Rust compiler bug.
pub struct CFArray<ElemRefType> {
    contents: CFWrapper<CFArrayRef, ElemRefType, ()>
}

pub struct CFArrayIterator<'self, ElemRefType> {
    priv array: &'self CFArray<ElemRefType>,
    priv index: uint,
}

impl<'self, ElemRefType: AbstractCFTypeRef> Iterator<ElemRefType> for CFArrayIterator<'self, ElemRefType> {
    fn next(&mut self) -> Option<ElemRefType> {
        if self.index >= self.array.len() {
            None
        } else {
            let v = self.array[self.index];
            self.index += 1;
            Some(v)
        }
    }
}

impl<ElemRefType:AbstractCFTypeRef> CFArray<ElemRefType> {
    pub fn wrap_shared(array: CFArrayRef) -> CFArray<ElemRefType> {
        CFArray {
            contents: CFWrapper::wrap_shared(array)
        }
    }

    pub fn wrap_owned(array: CFArrayRef) -> CFArray<ElemRefType> {
        CFArray {
            contents: CFWrapper::wrap_owned(array)
        }
    }

    pub fn new(elems: &[ElemRefType]) -> CFArray<ElemRefType> {
        let array_ref: CFArrayRef;
        let elems_refs = do elems.map |e: &ElemRefType| { e.as_type_ref() };

        unsafe {
            array_ref = CFArrayCreate(kCFAllocatorDefault,
                                      cast::transmute::<*CFTypeRef, **c_void>(vec::raw::to_ptr(elems_refs)),
                                      elems.len() as CFIndex,
                                      ptr::to_unsafe_ptr(&kCFTypeArrayCallBacks));
        }

        CFArray {
            contents: CFWrapper::wrap_owned(array_ref)
        }
    }

    // Careful; the loop body must wrap the reference properly.
    // Generally, when array elements are Core Foundation objects (not
    // always true), they need to be wrapped with CFWrapper::wrap_shared.
    pub fn each<'t>(&'t self) -> CFArrayIterator<'t, ElemRefType> {
        CFArrayIterator {
            array: self,
            index: 0
        }
    }

    // Careful; the loop body must wrap the reference properly.
    // Generally, when array elements are Core Foundation objects (not
    // always true), they need to be wrapped with CFWrapper::wrap_shared.
    pub fn eachi<'t>(&'t self) -> Enumerate<CFArrayIterator<'t, ElemRefType>> {
        self.each().enumerate()
    }

    pub fn len(&self) -> uint {
        unsafe {
            return CFArrayGetCount(*self.contents.borrow_ref()) as uint;
        }
    }
}

impl<ElemRefType:AbstractCFTypeRef> Index<uint,ElemRefType> for CFArray<ElemRefType> {
    // Careful; the caller must wrap any returned reference properly.
    // Generally, when array elements are Core Foundation objects (not
    // always true), they need to be wrapped with CFWrapper::wrap_shared.
    fn index(&self, idx: &uint) -> ElemRefType {
        assert!(*idx < self.len());
        unsafe {
            let elem = CFArrayGetValueAtIndex(*self.contents.borrow_ref(), *idx as CFIndex);
            // Don't return a wrapped thing, since we don't know whether
            // it needs base::wrap_shared() or base::wrap_owned()
            cast::transmute::<*c_void,ElemRefType>(elem)
        }
    }
}

#[link_args="-framework CoreFoundation"]
#[nolink]
extern {
    /*
     * CFArray.h
     */
    static kCFTypeArrayCallBacks: CFArrayCallBacks;

    fn CFArrayCreate(allocator: CFAllocatorRef, values: **c_void,
                     numValues: CFIndex, callBacks: *CFArrayCallBacks) -> CFArrayRef;
    // CFArrayCreateCopy
    // CFArrayBSearchValues
    // CFArrayContainsValue
    fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex;
    // CFArrayGetCountOfValue
    // CFArrayGetFirstIndexOfValue
    // CFArrayGetLastIndexOfValue
    // CFArrayGetValues
    fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *c_void;
    // CFArrayApplyFunction
    fn CFArrayGetTypeID() -> CFTypeID;
}

#[test]
fn should_box_and_unbox() {
    use number::{CFNumber, CFNumberRef};

    let one = CFNumber::new(1 as i32);
    let two = CFNumber::new(2 as i32);
    let thr = CFNumber::new(3 as i32);
    let fou = CFNumber::new(4 as i32);
    let fiv = CFNumber::new(5 as i32);

    let arr = CFArray::new([
        *one.contents.borrow_ref(),
        *two.contents.borrow_ref(),
        *thr.contents.borrow_ref(),
        *fou.contents.borrow_ref(),
        *fiv.contents.borrow_ref()
    ]);

    let mut sum = 0i32;

    for elem in arr.iter() {
        sum += CFNumber::wrap_shared(*elem).to_i32();
    }

    assert!(sum == 15);

    for elem in arr.iter() {
        sum += CFNumber::wrap_shared(*elem).to_i32();
    }

    assert!(sum == 30);
}
<commit_msg>Fix test failures.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use base::{
    AbstractCFTypeRef,
    CFAllocatorRef,
    CFIndex,
    CFTypeID,
    CFTypeRef,
    CFWrapper,
    kCFAllocatorDefault,
};
use std::cast;
use std::libc::c_void;
use std::ptr;
use std::vec;
use std::iterator::Enumerate;

pub type CFArrayRetainCallBack = *u8;
pub type CFArrayReleaseCallBack = *u8;
pub type CFArrayCopyDescriptionCallBack = *u8;
pub type CFArrayEqualCallBack = *u8;

pub struct CFArrayCallBacks {
    version: CFIndex,
    retain: CFArrayRetainCallBack,
    release: CFArrayReleaseCallBack,
    copyDescription: CFArrayCopyDescriptionCallBack,
    equal: CFArrayEqualCallBack,
}

struct __CFArray { private: () }
pub type CFArrayRef = *__CFArray;

impl AbstractCFTypeRef for CFArrayRef {
    fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef }
    fn type_id() -> CFTypeID { unsafe { CFArrayGetTypeID() } }
}

// FIXME: Should be a newtype struct, but that fails due to a Rust compiler bug.
pub struct CFArray<ElemRefType> {
    contents: CFWrapper<CFArrayRef, ElemRefType, ()>
}

pub struct CFArrayIterator<'self, ElemRefType> {
    priv array: &'self CFArray<ElemRefType>,
    priv index: uint,
}

impl<'self, ElemRefType: AbstractCFTypeRef> Iterator<ElemRefType> for CFArrayIterator<'self, ElemRefType> {
    fn next(&mut self) -> Option<ElemRefType> {
        if self.index >= self.array.len() {
            None
        } else {
            let v = self.array[self.index];
            self.index += 1;
            Some(v)
        }
    }
}

impl<ElemRefType:AbstractCFTypeRef> CFArray<ElemRefType> {
    pub fn wrap_shared(array: CFArrayRef) -> CFArray<ElemRefType> {
        CFArray {
            contents: CFWrapper::wrap_shared(array)
        }
    }

    pub fn wrap_owned(array: CFArrayRef) -> CFArray<ElemRefType> {
        CFArray {
            contents: CFWrapper::wrap_owned(array)
        }
    }

    pub fn new(elems: &[ElemRefType]) -> CFArray<ElemRefType> {
        let array_ref: CFArrayRef;
        let elems_refs = do elems.map |e: &ElemRefType| { e.as_type_ref() };

        unsafe {
            array_ref = CFArrayCreate(kCFAllocatorDefault,
                                      cast::transmute::<*CFTypeRef, **c_void>(vec::raw::to_ptr(elems_refs)),
                                      elems.len() as CFIndex,
                                      ptr::to_unsafe_ptr(&kCFTypeArrayCallBacks));
        }

        CFArray {
            contents: CFWrapper::wrap_owned(array_ref)
        }
    }

    // Careful; the loop body must wrap the reference properly.
    // Generally, when array elements are Core Foundation objects (not
    // always true), they need to be wrapped with CFWrapper::wrap_shared.
    pub fn each<'t>(&'t self) -> CFArrayIterator<'t, ElemRefType> {
        CFArrayIterator {
            array: self,
            index: 0
        }
    }

    // Careful; the loop body must wrap the reference properly.
    // Generally, when array elements are Core Foundation objects (not
    // always true), they need to be wrapped with CFWrapper::wrap_shared.
    pub fn eachi<'t>(&'t self) -> Enumerate<CFArrayIterator<'t, ElemRefType>> {
        self.each().enumerate()
    }

    pub fn len(&self) -> uint {
        unsafe {
            return CFArrayGetCount(*self.contents.borrow_ref()) as uint;
        }
    }
}

impl<ElemRefType:AbstractCFTypeRef> Index<uint,ElemRefType> for CFArray<ElemRefType> {
    // Careful; the caller must wrap any returned reference properly.
    // Generally, when array elements are Core Foundation objects (not
    // always true), they need to be wrapped with CFWrapper::wrap_shared.
    fn index(&self, idx: &uint) -> ElemRefType {
        assert!(*idx < self.len());
        unsafe {
            let elem = CFArrayGetValueAtIndex(*self.contents.borrow_ref(), *idx as CFIndex);
            // Don't return a wrapped thing, since we don't know whether
            // it needs base::wrap_shared() or base::wrap_owned()
            cast::transmute::<*c_void,ElemRefType>(elem)
        }
    }
}

#[link_args="-framework CoreFoundation"]
#[nolink]
extern {
    /*
     * CFArray.h
     */
    static kCFTypeArrayCallBacks: CFArrayCallBacks;

    fn CFArrayCreate(allocator: CFAllocatorRef, values: **c_void,
                     numValues: CFIndex, callBacks: *CFArrayCallBacks) -> CFArrayRef;
    // CFArrayCreateCopy
    // CFArrayBSearchValues
    // CFArrayContainsValue
    fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex;
    // CFArrayGetCountOfValue
    // CFArrayGetFirstIndexOfValue
    // CFArrayGetLastIndexOfValue
    // CFArrayGetValues
    fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *c_void;
    // CFArrayApplyFunction
    fn CFArrayGetTypeID() -> CFTypeID;
}

#[test]
fn should_box_and_unbox() {
    use number::{CFNumber, CFNumberRef};

    let one = CFNumber::new(1 as i32);
    let two = CFNumber::new(2 as i32);
    let thr = CFNumber::new(3 as i32);
    let fou = CFNumber::new(4 as i32);
    let fiv = CFNumber::new(5 as i32);

    let arr = CFArray::new([
        *one.contents.borrow_ref(),
        *two.contents.borrow_ref(),
        *thr.contents.borrow_ref(),
        *fou.contents.borrow_ref(),
        *fiv.contents.borrow_ref()
    ]);

    let mut sum = 0i32;

    for elem in arr.iter() {
        sum += CFNumber::wrap_shared(elem).to_i32();
    }

    assert!(sum == 15);

    for elem in arr.iter() {
        sum += CFNumber::wrap_shared(elem).to_i32();
    }

    assert!(sum == 30);
}
<|endoftext|>


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

fn main() {
    let args: Vec<String> = env::args().collect();

    let config = parse_config(&args);

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    let mut f = File::open(config.filename).expect("file not found");

    let mut contents = String::new();
    f.read_to_string(&mut contents).expect("something went wrong while reading the file");

    println!("With text:\n{}", contents);
}

struct Config {
    query: String,
    filename: String,
}

fn parse_config(args: &[String]) -> Config {
    let query = args[1].clone();
    let filename = args[2].clone();

    Config { query, filename }
}
<commit_msg>create constructor for config greprs<commit_after>use std::env;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    let args: Vec<String> = env::args().collect();

    let config = Config::new(&args);

    println!("Searching for {}", config.query);
    println!("In file {}", config.filename);

    let mut f = File::open(config.filename).expect("file not found");

    let mut contents = String::new();
    f.read_to_string(&mut contents).expect("something went wrong while reading the file");

    println!("With text:\n{}", contents);
}

struct Config {
    query: String,
    filename: String,
}

impl Config {
    fn new(args: &[String]) -> Config {
        let query = args[1].clone();
        let filename = args[2].clone();

        Config { query, filename }
    }
}
<|endoftext|>


<commit_before>extern crate glib_sys;
extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate libc;

use self::glib::translate::*;

use color::*;
use error::*;
use opacity::*;
use node::RsvgNode;
use node::NodeType;
use path_builder::RsvgPathBuilder;
use state::RsvgState;

pub enum RsvgDrawingCtx {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi (draw_ctx: *const RsvgDrawingCtx,
                                 out_dpi_x: *mut f64,
                                 out_dpi_y: *mut f64);

    fn rsvg_drawing_ctx_get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size (draw_ctx: *const RsvgDrawingCtx,
                                           out_x: *mut f64,
                                           out_y: *mut f64);

    fn rsvg_drawing_ctx_push_view_box (draw_ctx: *const RsvgDrawingCtx,
                                       width:     f64,
                                       height:    f64);

    fn rsvg_drawing_ctx_pop_view_box (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node (draw_ctx: *const RsvgDrawingCtx,
                                      url:      *const libc::c_char) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                                              url:       *const libc::c_char,
                                              node_type: NodeType) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node (draw_ctx: *const RsvgDrawingCtx,
                                      node:     *mut RsvgNode);

    fn rsvg_drawing_ctx_get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix;

    fn rsvg_drawing_ctx_set_current_state_affine (draw_ctx: *const RsvgDrawingCtx,
                                                  affine:   *const cairo::Matrix);

    fn rsvg_drawing_ctx_add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                                           x: f64,
                                           y: f64,
                                           w: f64,
                                           h: f64);

    fn rsvg_drawing_ctx_draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                                              node:     *const RsvgNode,
                                              dominate: i32);

    fn rsvg_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_state_new () -> *mut RsvgState;
    fn rsvg_state_reinit (state: *mut RsvgState);
    fn rsvg_state_reconstruct (state: *mut RsvgState, node: *const RsvgNode);
    fn rsvg_state_is_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_has_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_cond_true (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_stop_color (state: *const RsvgState) -> *const ColorSpec;
    fn rsvg_state_get_stop_opacity (state: *const RsvgState) -> *const OpacitySpec;
    fn rsvg_state_get_current_color (state: *const RsvgState) -> u32;

    fn rsvg_state_push (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_state_pop (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                                 state: *mut RsvgState,
                                 dominate: libc::c_int);

    fn rsvg_push_discrete_layer (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                                 builder: *const RsvgPathBuilder);

    fn rsvg_cairo_get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_dpi (draw_ctx, &mut dpi_x, &mut dpi_y); }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size (draw_ctx) }
}

pub fn get_view_box_size (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_view_box_size (draw_ctx, &mut w, &mut h); }

    (w, h)
}

pub fn push_view_box (draw_ctx: *const RsvgDrawingCtx,
                      width:     f64,
                      height:    f64)
{
    unsafe { rsvg_drawing_ctx_push_view_box (draw_ctx, width, height); }
}

pub fn pop_view_box (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_drawing_ctx_pop_view_box (draw_ctx); }
}

pub fn acquire_node (draw_ctx: *const RsvgDrawingCtx,
                     url:      &str) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node (draw_ctx, str::to_glib_none (url).0) }
}

pub fn acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                             url:       &str,
                             node_type: NodeType) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node_of_type (draw_ctx, str::to_glib_none (url).0, node_type) }
}

pub fn release_node (draw_ctx: *const RsvgDrawingCtx,
                     node:     *mut RsvgNode) {
    unsafe { rsvg_drawing_ctx_release_node (draw_ctx, node); }
}

pub fn state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                            state: *mut RsvgState,
                            dominate: i32) {
    unsafe { rsvg_state_reinherit_top (draw_ctx, state, dominate); }
}

pub fn push_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_push_discrete_layer (draw_ctx); }
}

pub fn pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_pop_discrete_layer (draw_ctx); }
}

pub fn render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                            builder: &RsvgPathBuilder) {
    unsafe { rsvg_render_path_builder (draw_ctx, builder); }
}

pub fn get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context (draw_ctx);

        let cr = cairo::Context::from_glib_none (raw_cr);

        cr
    }
}

pub fn set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none ().0;

        rsvg_cairo_set_cairo_context (draw_ctx, raw_cr);
    }
}

pub fn get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix {
    unsafe {
        rsvg_drawing_ctx_get_current_state_affine (draw_ctx)
    }
}

pub fn set_current_state_affine (draw_ctx: *const RsvgDrawingCtx, affine: cairo::Matrix) {
    unsafe {
        rsvg_drawing_ctx_set_current_state_affine (draw_ctx, &affine);
    }
}

pub fn add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                          x: f64,
                          y: f64,
                          w: f64,
                          h: f64) {
    unsafe { rsvg_drawing_ctx_add_clipping_rect (draw_ctx, x, y, w, h); }
}

pub fn draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                             node:     *const RsvgNode,
                             dominate: i32) {
    unsafe { rsvg_drawing_ctx_draw_node_from_stack (draw_ctx, node, dominate); }
}

pub fn get_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_current_state (draw_ctx) }
}

pub fn state_new () -> *mut RsvgState {
    unsafe { rsvg_state_new () }
}

pub fn state_reinit (state: *mut RsvgState) {
    unsafe { rsvg_state_reinit (state); }
}

pub fn state_reconstruct (state: *mut RsvgState, node: *const RsvgNode) {
    unsafe { rsvg_state_reconstruct (state, node); }
}

pub fn state_is_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_is_overflow (state)) }
}

pub fn state_has_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_has_overflow (state)) }
}

pub fn state_get_cond_true (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_get_cond_true (state)) }
}

pub fn state_push (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_push (draw_ctx);
    }
}

pub fn state_pop (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_pop (draw_ctx);
    }
}

pub fn state_get_stop_color (state: *const RsvgState) -> Result<Option<Color>, AttributeError> {
    unsafe {
        let spec_ptr = rsvg_state_get_stop_color (state);

        if spec_ptr.is_null () {
            Ok (None)
        } else {
            Color::from_color_spec (&*spec_ptr).map (|color| Some (color))
        }
    }
}

pub fn state_get_stop_opacity (state: *const RsvgState) -> Result<Option<Opacity>, AttributeError> {
    unsafe {
        let opacity_ptr = rsvg_state_get_stop_opacity (state);

        if opacity_ptr.is_null () {
            Ok (None)
        } else {
            Opacity::from_opacity_spec (&*opacity_ptr).map (|opacity| Some (opacity))
        }
    }
}

pub fn state_get_current_color (state: *const RsvgState) -> u32 {
    unsafe {
        rsvg_state_get_current_color (state)
    }
}
<commit_msg>drawing_ctx::state_free() - Bind rsvg_state_free() for Rust<commit_after>extern crate glib_sys;
extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate libc;

use self::glib::translate::*;

use color::*;
use error::*;
use opacity::*;
use node::RsvgNode;
use node::NodeType;
use path_builder::RsvgPathBuilder;
use state::RsvgState;

pub enum RsvgDrawingCtx {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi (draw_ctx: *const RsvgDrawingCtx,
                                 out_dpi_x: *mut f64,
                                 out_dpi_y: *mut f64);

    fn rsvg_drawing_ctx_get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size (draw_ctx: *const RsvgDrawingCtx,
                                           out_x: *mut f64,
                                           out_y: *mut f64);

    fn rsvg_drawing_ctx_push_view_box (draw_ctx: *const RsvgDrawingCtx,
                                       width:     f64,
                                       height:    f64);

    fn rsvg_drawing_ctx_pop_view_box (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node (draw_ctx: *const RsvgDrawingCtx,
                                      url:      *const libc::c_char) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                                              url:       *const libc::c_char,
                                              node_type: NodeType) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node (draw_ctx: *const RsvgDrawingCtx,
                                      node:     *mut RsvgNode);

    fn rsvg_drawing_ctx_get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix;

    fn rsvg_drawing_ctx_set_current_state_affine (draw_ctx: *const RsvgDrawingCtx,
                                                  affine:   *const cairo::Matrix);

    fn rsvg_drawing_ctx_add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                                           x: f64,
                                           y: f64,
                                           w: f64,
                                           h: f64);

    fn rsvg_drawing_ctx_draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                                              node:     *const RsvgNode,
                                              dominate: i32);

    fn rsvg_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_state_new () -> *mut RsvgState;
    fn rsvg_state_free (state: *mut RsvgState);
    fn rsvg_state_reinit (state: *mut RsvgState);
    fn rsvg_state_reconstruct (state: *mut RsvgState, node: *const RsvgNode);
    fn rsvg_state_is_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_has_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_cond_true (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_stop_color (state: *const RsvgState) -> *const ColorSpec;
    fn rsvg_state_get_stop_opacity (state: *const RsvgState) -> *const OpacitySpec;
    fn rsvg_state_get_current_color (state: *const RsvgState) -> u32;

    fn rsvg_state_push (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_state_pop (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                                 state: *mut RsvgState,
                                 dominate: libc::c_int);

    fn rsvg_push_discrete_layer (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                                 builder: *const RsvgPathBuilder);

    fn rsvg_cairo_get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_dpi (draw_ctx, &mut dpi_x, &mut dpi_y); }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size (draw_ctx) }
}

pub fn get_view_box_size (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_view_box_size (draw_ctx, &mut w, &mut h); }

    (w, h)
}

pub fn push_view_box (draw_ctx: *const RsvgDrawingCtx,
                      width:     f64,
                      height:    f64)
{
    unsafe { rsvg_drawing_ctx_push_view_box (draw_ctx, width, height); }
}

pub fn pop_view_box (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_drawing_ctx_pop_view_box (draw_ctx); }
}

pub fn acquire_node (draw_ctx: *const RsvgDrawingCtx,
                     url:      &str) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node (draw_ctx, str::to_glib_none (url).0) }
}

pub fn acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                             url:       &str,
                             node_type: NodeType) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node_of_type (draw_ctx, str::to_glib_none (url).0, node_type) }
}

pub fn release_node (draw_ctx: *const RsvgDrawingCtx,
                     node:     *mut RsvgNode) {
    unsafe { rsvg_drawing_ctx_release_node (draw_ctx, node); }
}

pub fn state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                            state: *mut RsvgState,
                            dominate: i32) {
    unsafe { rsvg_state_reinherit_top (draw_ctx, state, dominate); }
}

pub fn push_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_push_discrete_layer (draw_ctx); }
}

pub fn pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_pop_discrete_layer (draw_ctx); }
}

pub fn render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                            builder: &RsvgPathBuilder) {
    unsafe { rsvg_render_path_builder (draw_ctx, builder); }
}

pub fn get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context (draw_ctx);

        let cr = cairo::Context::from_glib_none (raw_cr);

        cr
    }
}

pub fn set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none ().0;

        rsvg_cairo_set_cairo_context (draw_ctx, raw_cr);
    }
}

pub fn get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix {
    unsafe {
        rsvg_drawing_ctx_get_current_state_affine (draw_ctx)
    }
}

pub fn set_current_state_affine (draw_ctx: *const RsvgDrawingCtx, affine: cairo::Matrix) {
    unsafe {
        rsvg_drawing_ctx_set_current_state_affine (draw_ctx, &affine);
    }
}

pub fn add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                          x: f64,
                          y: f64,
                          w: f64,
                          h: f64) {
    unsafe { rsvg_drawing_ctx_add_clipping_rect (draw_ctx, x, y, w, h); }
}

pub fn draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                             node:     *const RsvgNode,
                             dominate: i32) {
    unsafe { rsvg_drawing_ctx_draw_node_from_stack (draw_ctx, node, dominate); }
}

pub fn get_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_current_state (draw_ctx) }
}

pub fn state_new () -> *mut RsvgState {
    unsafe { rsvg_state_new () }
}

pub fn state_free (state: *mut RsvgState) {
    unsafe { rsvg_state_free (state); }
}

pub fn state_reinit (state: *mut RsvgState) {
    unsafe { rsvg_state_reinit (state); }
}

pub fn state_reconstruct (state: *mut RsvgState, node: *const RsvgNode) {
    unsafe { rsvg_state_reconstruct (state, node); }
}

pub fn state_is_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_is_overflow (state)) }
}

pub fn state_has_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_has_overflow (state)) }
}

pub fn state_get_cond_true (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_get_cond_true (state)) }
}

pub fn state_push (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_push (draw_ctx);
    }
}

pub fn state_pop (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_pop (draw_ctx);
    }
}

pub fn state_get_stop_color (state: *const RsvgState) -> Result<Option<Color>, AttributeError> {
    unsafe {
        let spec_ptr = rsvg_state_get_stop_color (state);

        if spec_ptr.is_null () {
            Ok (None)
        } else {
            Color::from_color_spec (&*spec_ptr).map (|color| Some (color))
        }
    }
}

pub fn state_get_stop_opacity (state: *const RsvgState) -> Result<Option<Opacity>, AttributeError> {
    unsafe {
        let opacity_ptr = rsvg_state_get_stop_opacity (state);

        if opacity_ptr.is_null () {
            Ok (None)
        } else {
            Opacity::from_opacity_spec (&*opacity_ptr).map (|opacity| Some (opacity))
        }
    }
}

pub fn state_get_current_color (state: *const RsvgState) -> u32 {
    unsafe {
        rsvg_state_get_current_color (state)
    }
}
<|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.

use core::finally::{try_finally, Finally};
use std::task::failing;

#[test]
fn test_success() {
    let mut i = 0i;
    try_finally(
        &mut i, (),
        |i, ()| {
            *i = 10;
        },
        |i| {
            assert!(!failing());
            assert_eq!(*i, 10);
            *i = 20;
        });
    assert_eq!(i, 20);
}

#[test]
#[should_fail]
fn test_fail() {
    let mut i = 0i;
    try_finally(
        &mut i, (),
        |i, ()| {
            *i = 10;
            panic!();
        },
        |i| {
            assert!(failing());
            assert_eq!(*i, 10);
        })
}

#[test]
fn test_retval() {
    let mut closure: || -> int = || 10;
    let i = closure.finally(|| { });
    assert_eq!(i, 10);
}

#[test]
fn test_compact() {
    fn do_some_fallible_work() {}
    fn but_always_run_this_function() { }
    let mut f = do_some_fallible_work;
    f.finally(but_always_run_this_function);
}
<commit_msg>libcoretest: fix fallout<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.

use core::finally::{try_finally, Finally};
use std::task::failing;

#[test]
fn test_success() {
    let mut i = 0i;
    try_finally(
        &mut i, (),
        |i, ()| {
            *i = 10;
        },
        |i| {
            assert!(!failing());
            assert_eq!(*i, 10);
            *i = 20;
        });
    assert_eq!(i, 20);
}

#[test]
#[should_fail]
fn test_fail() {
    let mut i = 0i;
    try_finally(
        &mut i, (),
        |i, ()| {
            *i = 10;
            panic!();
        },
        |i| {
            assert!(failing());
            assert_eq!(*i, 10);
        })
}

#[test]
fn test_retval() {
    let mut closure = |&mut:| 10i;
    let i = closure.finally(|| { });
    assert_eq!(i, 10);
}

#[test]
fn test_compact() {
    fn do_some_fallible_work() {}
    fn but_always_run_this_function() { }
    let mut f = do_some_fallible_work;
    f.finally(but_always_run_this_function);
}
<|endoftext|>