<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Functions to throw JavaScript exceptions from Rust.

#![deny(missing_docs)]

use jsapi::{JSContext, JSErrorFormatString, JSExnType, JS_ReportErrorNumber};
use libc;
use std::ffi::CString;
use std::{mem, os, ptr};

/// Format string used to throw javascript errors.
static ERROR_FORMAT_STRING_STRING: [libc::c_char; 4] = [
    '{' as libc::c_char,
    '0' as libc::c_char,
    '}' as libc::c_char,
    0 as libc::c_char,
];

/// Format string struct used to throw `TypeError`s.
static mut TYPE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
    name: b"TYPE_ERROR" as *const _ as *const libc::c_char,
    format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
    argCount: 1,
    exnType: JSExnType::JSEXN_TYPEERR as i16,
};

/// Format string struct used to throw `RangeError`s.
static mut RANGE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
    name: b"RANGE_ERROR" as *const _ as *const libc::c_char,
    format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
    argCount: 1,
    exnType: JSExnType::JSEXN_RANGEERR as i16,
};

/// Callback used to throw javascript errors.
/// See throw_js_error for info about error_number.
unsafe extern "C" fn get_error_message(_user_ref: *mut os::raw::c_void,
                                       error_number: libc::c_uint)
                                       -> *const JSErrorFormatString {
    let num: JSExnType = mem::transmute(error_number);
    match num {
        JSExnType::JSEXN_TYPEERR => &TYPE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
        JSExnType::JSEXN_RANGEERR => &RANGE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
        _ => panic!("Bad js error number given to get_error_message: {}",
                    error_number),
    }
}

/// Helper fn to throw a javascript error with the given message and number.
/// Reuse the jsapi error codes to distinguish the error_number
/// passed back to the get_error_message callback.
/// c_uint is u32, so this cast is safe, as is casting to/from i32 from there.
unsafe fn throw_js_error(cx: *mut JSContext, error: &str, error_number: u32) {
    let error = CString::new(error).unwrap();
    JS_ReportErrorNumber(cx,
                         Some(get_error_message),
                         ptr::null_mut(),
                         error_number,
                         error.as_ptr());
}

/// Throw a `TypeError` with the given message.
pub unsafe fn throw_type_error(cx: *mut JSContext, error: &str) {
    throw_js_error(cx, error, JSExnType::JSEXN_TYPEERR as u32);
}

/// Throw a `RangeError` with the given message.
pub unsafe fn throw_range_error(cx: *mut JSContext, error: &str) {
    throw_js_error(cx, error, JSExnType::JSEXN_RANGEERR as u32);
}
<commit_msg>Improve the names of JSErrorFormatStrings.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Functions to throw JavaScript exceptions from Rust.

#![deny(missing_docs)]

use jsapi::{JSContext, JSErrorFormatString, JSExnType, JS_ReportErrorNumber};
use libc;
use std::ffi::CString;
use std::{mem, os, ptr};

/// Format string used to throw javascript errors.
static ERROR_FORMAT_STRING_STRING: [libc::c_char; 4] = [
    '{' as libc::c_char,
    '0' as libc::c_char,
    '}' as libc::c_char,
    0 as libc::c_char,
];

/// Format string struct used to throw `TypeError`s.
static mut TYPE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
    name: b"RUSTMSG_TYPE_ERROR\0" as *const _ as *const libc::c_char,
    format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
    argCount: 1,
    exnType: JSExnType::JSEXN_TYPEERR as i16,
};

/// Format string struct used to throw `RangeError`s.
static mut RANGE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
    name: b"RUSTMSG_RANGE_ERROR\0" as *const _ as *const libc::c_char,
    format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
    argCount: 1,
    exnType: JSExnType::JSEXN_RANGEERR as i16,
};

/// Callback used to throw javascript errors.
/// See throw_js_error for info about error_number.
unsafe extern "C" fn get_error_message(_user_ref: *mut os::raw::c_void,
                                       error_number: libc::c_uint)
                                       -> *const JSErrorFormatString {
    let num: JSExnType = mem::transmute(error_number);
    match num {
        JSExnType::JSEXN_TYPEERR => &TYPE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
        JSExnType::JSEXN_RANGEERR => &RANGE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
        _ => panic!("Bad js error number given to get_error_message: {}",
                    error_number),
    }
}

/// Helper fn to throw a javascript error with the given message and number.
/// Reuse the jsapi error codes to distinguish the error_number
/// passed back to the get_error_message callback.
/// c_uint is u32, so this cast is safe, as is casting to/from i32 from there.
unsafe fn throw_js_error(cx: *mut JSContext, error: &str, error_number: u32) {
    let error = CString::new(error).unwrap();
    JS_ReportErrorNumber(cx,
                         Some(get_error_message),
                         ptr::null_mut(),
                         error_number,
                         error.as_ptr());
}

/// Throw a `TypeError` with the given message.
pub unsafe fn throw_type_error(cx: *mut JSContext, error: &str) {
    throw_js_error(cx, error, JSExnType::JSEXN_TYPEERR as u32);
}

/// Throw a `RangeError` with the given message.
pub unsafe fn throw_range_error(cx: *mut JSContext, error: &str) {
    throw_js_error(cx, error, JSExnType::JSEXN_RANGEERR as u32);
}
<|endoftext|>


<commit_before>use super::{Result, Response, DropboxClient, ApiError};
use std::default::Default;
use std::io;
use std::fmt;
use std::collections::BTreeMap;
use rustc_serialize::json;

use structs::{FolderList, Metadata, FileMetadata};

/// Instructs dropbox what to do when a conflict happens during upload
#[derive(Debug, PartialEq, Clone)]
pub enum WriteMode {
    Add,
    Overwrite,
    Update,
}

impl fmt::Display for WriteMode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WriteMode::Add => write!(f, "add"),
            WriteMode::Overwrite => write!(f, "overwrite"),
            WriteMode::Update => write!(f, "update"),
        }
    }
}

/// Optional arguments to the `upload` API call
#[derive(Debug, PartialEq, Clone)]
pub struct UploadOptions {
    pub mode: WriteMode,
    pub autorename: bool,
    pub client_modified: Option<String>,
    pub mute: bool,
}

impl Default for UploadOptions {
    fn default() -> UploadOptions {
        UploadOptions {
            mode: WriteMode::Add,
            autorename: false,
            client_modified: None,
            mute: false,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub enum ThumbnailFormat {
    Jpeg,
    Png,
    Gif,
}

#[derive(Debug, PartialEq, Clone)]
pub enum ThumbnailSize {
    W16H16,
    W32H32,
    W64H64,
    Other(usize, usize),
}

#[derive(Debug, PartialEq, Clone)]
pub struct ThumbnailOptions {
    format: ThumbnailFormat,
    size: ThumbnailSize,
}

impl Default for ThumbnailOptions {
    fn default() -> ThumbnailOptions {
        ThumbnailOptions {
            format: ThumbnailFormat::Jpeg,
            size: ThumbnailSize::W64H64,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct GetCursorOptions {
    recursive: bool,
    include_media_info: bool,
    include_deleted: bool,
}

impl Default for GetCursorOptions {
    fn default() -> GetCursorOptions {
        GetCursorOptions {
            recursive: false,
            include_media_info: false,
            include_deleted: false,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct FolderListLongpoll {
    changes: bool,
    backoff: Option<bool>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct ListRevisions {
    is_deleted: bool,
    entries: Vec<Metadata>,
}

#[derive(Debug, PartialEq, Clone)]
pub enum SearchMode {
    Filename,
    FilenameAndContent,
    DeletedFilename,
}

#[derive(Debug, PartialEq, Clone)]
pub struct SearchOptions {
    start: usize,
    max_results: usize,
    mode: SearchMode,
}

impl Default for SearchOptions {
    fn default() -> SearchOptions {
        SearchOptions {
            start: 0,
            max_results: 100,
            mode: SearchMode::Filename,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub enum SearchMatchType {
    Filename(String),
    Content(String),
    Both(String),
}

#[derive(Debug, PartialEq, Clone)]
pub struct SearchMatch {
    match_type: SearchMatchType,
    metadata: Metadata,
}

#[derive(Debug, PartialEq, Clone)]
pub struct Search {
    matches: Vec<SearchMatch>,
    more: bool,
    start: usize,
}

#[derive(Debug, PartialEq, Clone)]
pub struct CommitInfo {
    path: String,
    mode: WriteMode,
    autorename: bool,
    client_modified: String,
    mute: bool,
}

#[derive(Debug, PartialEq, Clone)]
pub struct UploadSessionCursor {
    session_id: String,
    offset: usize,
}

// Functions

/// Copy a file
///
/// # Example
///
/// ```ignore
/// use std::env;
/// use dbox::client::Client;
/// use dbox::files;
///
/// let client = Client::new(env::var("DROPBOX_TOKEN"));
/// let metadata = try!(files::copy_(&client, "/Path/to/existing/file", "/Path/to/new/file"));
/// ```
pub fn copy_<T>(client: &T, from: &str, to: &str) -> Result<Metadata>
                where T: DropboxClient
{
    let mut map = BTreeMap::new();
    map.insert("from_path".to_string(), json::Json::String(from.to_string()));
    map.insert("to_path".to_string(), json::Json::String(to.to_string()));
    let mut headers = BTreeMap::new();
    headers.insert("Content-Type".to_string(), "application/json".to_string());
    let resp = try!(client.api("files/copy", &mut headers, Some(&map)));
    json::decode(&resp.body).map_err(|e| ApiError::from(e))
}

/// Create a folder
///
/// # Example
///
/// ```ignore
/// use std::env;
/// use dbox::client::Client;
/// use dbox::files;
///
/// let client = Client::new(env::var("DROPBOX_TOKEN"));
/// let metadata = try!(files::create_folder(&client, "/Path/to/new/folder"));
/// ```
pub fn create_folder<T>(client: &T, path: &str) -> Result<Metadata>
                where T: DropboxClient
{
    let mut map = BTreeMap::new();
    map.insert("path".to_string(), json::Json::String(path.to_string()));
    let mut headers = BTreeMap::new();
    headers.insert("Content-Type".to_string(), "application/json".to_string());
    let resp = try!(client.api("files/create_folder", &mut headers, Some(map)));
    json::decode(&resp.body).map_err(|e| ApiError::from(e))
}

/// TODO implement
pub fn delete<T: DropboxClient>(client: &T, path: &str) -> Result<Metadata> {
    Ok(Default::default())
}

/// Download a file
///
/// # Example
///
/// ```ignore
/// use std::env;
/// use dbox::client::Client;
/// use dbox::files;
///
/// let token = env::var("DROPBOX_TOKEN");
/// let client = Client::new(token);
/// let (metadata, response) = try!(files::download(&client, "/Path/to/file"));
/// ```
pub fn download<T: DropboxClient>(client: &T, path: &str) -> Result<(FileMetadata, Response)> {
    let mut map = BTreeMap::new();
    map.insert("path".to_string(), json::Json::String(path.to_string()));
    let mut headers = BTreeMap::new();
    headers.insert("Dropbox-API-Arg".to_string(), json::encode(&map).unwrap());
    let resp = try!(client.content("files/download", &mut headers, None::<&str>));
    let metadata: FileMetadata = match resp.api_result {
        Some(ref data) => {
            try!(json::decode(data))
        },
        None => return Err(ApiError::ClientError)
    };
    Ok((
        metadata,
        resp,
    ))
}

/// TODO implement
pub fn download_to_file<T>(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

/// TODO implement
pub fn get_metadata<T>(client: &T, path: &str, include_media_info: bool) -> Result<Metadata>
                where T: DropboxClient
{
    Ok(Default::default())
}

/// TODO implement
pub fn get_preview<T>(client: &T, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

/// TODO implement
pub fn get_preview_to_file<T>(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

pub fn get_thumbnail<T>(client: &T, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    get_thumbnail_with_options(client, path, Default::default())
}

/// TODO implement
pub fn get_thumbnail_with_options<T>(client: &T, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

pub fn get_thumbnail_to_file<T>(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    get_thumbnail_to_file_with_options(client, dest_path, path, Default::default())
}

/// TODO implement
pub fn get_thumbnail_to_file_with_options<T>(client: &T, dest_path: &str, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

/// TODO implement, need FolderList deser
pub fn list_folder<T: DropboxClient>(client: &T, path: &str) -> Result<FolderList> {
    let mut map = BTreeMap::new();
    map.insert("path".to_string(), json::Json::String("/OpenBudget".to_string()));
    map.insert("recursive".to_string(), json::Json::Boolean(false));
    map.insert("include_media_info".to_string(), json::Json::Boolean(false));
    map.insert("include_deleted".to_string(), json::Json::Boolean(false));
    let mut headers = BTreeMap::new();
    headers.insert("Content-Type".to_string(), "application/json".to_string());
    match client.api("files/list_folder", &mut headers, Some(&map)) {
        Ok(_) => Ok(Default::default()),
        Err(e) => Err(ApiError::ClientError),
    }
}

/// TODO implement
pub fn list_folder_continue<T>(client: &T, cursor: &str) -> Result<FolderList>
                where T: DropboxClient
{
    Ok(Default::default())
}

pub fn list_folder_get_latest_cursor<T>(client: &T, path: &str) -> Result<String>
                where T: DropboxClient
{
    list_folder_get_latest_cursor_with_options(client, path, Default::default())
}

/// TODO implement
pub fn list_folder_get_latest_cursor_with_options<T>(client: &T, path: &str, options: GetCursorOptions) -> Result<String>
                where T: DropboxClient
{
    Ok("".to_string())
}

/// TODO implement
pub fn list_folder_longpoll<T>(client: &T, cursor: &str, timeout: usize) -> Result<FolderListLongpoll>
                where T: DropboxClient
{
    Ok(FolderListLongpoll {
        changes: false,
        backoff: None,
    })
}

/// TODO implement
pub fn list_revisions<T>(client: &T, path: &str, limit: usize) -> Result<ListRevisions>
                where T: DropboxClient
{
    Ok(ListRevisions {
        is_deleted: false,
        entries: vec![],
    })
}

/// TODO implement
pub fn move_<T>(client: &T, from: &str, to: &str) -> Result<Metadata>
                where T: DropboxClient
{
    Ok(Default::default())
}

/// TODO implement
pub fn permanently_delete<T>(client: &T, path: &str) -> Result<()>
                where T: DropboxClient
{
    Ok(())
}

/// TODO implement
pub fn restore<T>(client: &T, path: &str, rev: &str) -> Result<Metadata>
                where T: DropboxClient
{
    Ok(Default::default())
}

pub fn search<T>(client: &T, path: &str, query: &str) -> Result<Search>
                where T: DropboxClient
{
    search_with_options(client, path, query, Default::default())
}

/// TODO implement
pub fn search_with_options<T>(client: &T, path: &str, query: &str, options: SearchOptions) -> Result<Search>
                where T: DropboxClient
{
    Ok(Search {
        matches: vec![],
        more: false,
        start: 0,
    })
}

pub fn upload<T>(client: &T, contents: &str, path: &str) -> Result<Metadata>
                where T: DropboxClient
{
    upload_with_options(client, contents, path, Default::default())
}

/// TODO implement
pub fn upload_with_options<T>(client: &T, contents: &str, path: &str, options: UploadOptions) -> Result<Metadata>
                where T: DropboxClient
{
    let mut map = BTreeMap::new();
    map.insert("path", json::Json::String(path.to_string()));
    map.insert("mode", json::Json::String(format!("{}", options.mode)));
    map.insert("autorename", json::Json::Boolean(options.autorename));
    map.insert("mute", json::Json::Boolean(options.mute));
    let mut headers = BTreeMap::new();
    headers.insert("Dropbox-API-Arg".to_string(), json::encode(&map).unwrap());
    headers.insert("Content-Type".to_string(), "application/octet-stream".to_string());
    let resp = client.content("files/upload", &mut headers, Some(contents.to_owned()));
    Ok(Default::default())
}

/// TODO implement
pub fn upload_session_append<T, U>(client: &T, f: U, session_id: &str, offset: usize) -> Result<()>
                where T: DropboxClient, U: io::Read
{
    Ok(())
}

/// TODO implement
pub fn upload_session_finish<T, U>(client: &T, f: U, cursor: &UploadSessionCursor, commit: &CommitInfo) -> Result<Metadata>
                where T: DropboxClient,
                      U: io::Read
{
    Ok(Default::default())
}

/// TODO implement
pub fn upload_session_start<T, U>(client: &T, f: U) -> Result<String>
                where T: DropboxClient,
                      U: io::Read
{
    Ok("".to_string())
}
<commit_msg>implement the files/delete api call<commit_after>use super::{Result, Response, DropboxClient, ApiError};
use std::default::Default;
use std::io;
use std::fmt;
use std::collections::BTreeMap;
use rustc_serialize::json;

use structs::{FolderList, Metadata, FileMetadata};

/// Instructs dropbox what to do when a conflict happens during upload
#[derive(Debug, PartialEq, Clone)]
pub enum WriteMode {
    Add,
    Overwrite,
    Update,
}

impl fmt::Display for WriteMode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            WriteMode::Add => write!(f, "add"),
            WriteMode::Overwrite => write!(f, "overwrite"),
            WriteMode::Update => write!(f, "update"),
        }
    }
}

/// Optional arguments to the `upload` API call
#[derive(Debug, PartialEq, Clone)]
pub struct UploadOptions {
    pub mode: WriteMode,
    pub autorename: bool,
    pub client_modified: Option<String>,
    pub mute: bool,
}

impl Default for UploadOptions {
    fn default() -> UploadOptions {
        UploadOptions {
            mode: WriteMode::Add,
            autorename: false,
            client_modified: None,
            mute: false,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub enum ThumbnailFormat {
    Jpeg,
    Png,
    Gif,
}

#[derive(Debug, PartialEq, Clone)]
pub enum ThumbnailSize {
    W16H16,
    W32H32,
    W64H64,
    Other(usize, usize),
}

#[derive(Debug, PartialEq, Clone)]
pub struct ThumbnailOptions {
    format: ThumbnailFormat,
    size: ThumbnailSize,
}

impl Default for ThumbnailOptions {
    fn default() -> ThumbnailOptions {
        ThumbnailOptions {
            format: ThumbnailFormat::Jpeg,
            size: ThumbnailSize::W64H64,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct GetCursorOptions {
    recursive: bool,
    include_media_info: bool,
    include_deleted: bool,
}

impl Default for GetCursorOptions {
    fn default() -> GetCursorOptions {
        GetCursorOptions {
            recursive: false,
            include_media_info: false,
            include_deleted: false,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct FolderListLongpoll {
    changes: bool,
    backoff: Option<bool>,
}

#[derive(Debug, PartialEq, Clone)]
pub struct ListRevisions {
    is_deleted: bool,
    entries: Vec<Metadata>,
}

#[derive(Debug, PartialEq, Clone)]
pub enum SearchMode {
    Filename,
    FilenameAndContent,
    DeletedFilename,
}

#[derive(Debug, PartialEq, Clone)]
pub struct SearchOptions {
    start: usize,
    max_results: usize,
    mode: SearchMode,
}

impl Default for SearchOptions {
    fn default() -> SearchOptions {
        SearchOptions {
            start: 0,
            max_results: 100,
            mode: SearchMode::Filename,
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub enum SearchMatchType {
    Filename(String),
    Content(String),
    Both(String),
}

#[derive(Debug, PartialEq, Clone)]
pub struct SearchMatch {
    match_type: SearchMatchType,
    metadata: Metadata,
}

#[derive(Debug, PartialEq, Clone)]
pub struct Search {
    matches: Vec<SearchMatch>,
    more: bool,
    start: usize,
}

#[derive(Debug, PartialEq, Clone)]
pub struct CommitInfo {
    path: String,
    mode: WriteMode,
    autorename: bool,
    client_modified: String,
    mute: bool,
}

#[derive(Debug, PartialEq, Clone)]
pub struct UploadSessionCursor {
    session_id: String,
    offset: usize,
}

// Functions

/// Copy a file
///
/// # Example
///
/// ```ignore
/// use std::env;
/// use dbox::client::Client;
/// use dbox::files;
///
/// let client = Client::new(env::var("DROPBOX_TOKEN"));
/// let metadata = try!(files::copy_(&client, "/Path/to/existing/file", "/Path/to/new/file"));
/// ```
pub fn copy_<T>(client: &T, from: &str, to: &str) -> Result<Metadata>
                where T: DropboxClient
{
    let mut map = BTreeMap::new();
    map.insert("from_path".to_string(), json::Json::String(from.to_string()));
    map.insert("to_path".to_string(), json::Json::String(to.to_string()));
    let mut headers = BTreeMap::new();
    headers.insert("Content-Type".to_string(), "application/json".to_string());
    let resp = try!(client.api("files/copy", &mut headers, Some(&map)));
    json::decode(&resp.body).map_err(|e| ApiError::from(e))
}

/// Create a folder
///
/// # Example
///
/// ```ignore
/// use std::env;
/// use dbox::client::Client;
/// use dbox::files;
///
/// let client = Client::new(env::var("DROPBOX_TOKEN"));
/// let metadata = try!(files::create_folder(&client, "/Path/to/new/folder"));
/// ```
pub fn create_folder<T>(client: &T, path: &str) -> Result<Metadata>
                where T: DropboxClient
{
    let mut map = BTreeMap::new();
    map.insert("path".to_string(), json::Json::String(path.to_string()));
    let mut headers = BTreeMap::new();
    headers.insert("Content-Type".to_string(), "application/json".to_string());
    let resp = try!(client.api("files/create_folder", &mut headers, Some(map)));
    {
        println!("create folder: {:?}", &resp.body);
    }
    json::decode(&resp.body).map_err(|e| ApiError::from(e))
}

/// TODO implement
pub fn delete<T: DropboxClient>(client: &T, path: &str) -> Result<Metadata> {
    let mut map = BTreeMap::new();
    map.insert("path".to_string(), json::Json::String(path.to_string()));
    let mut headers = BTreeMap::new();
    headers.insert("Content-Type".to_string(), "application/json".to_string());
    let resp = try!(client.api("files/delete", &mut headers, Some(map)));
    json::decode(&resp.body).map_err(|e| ApiError::from(e))
}

/// Download a file
///
/// # Example
///
/// ```ignore
/// use std::env;
/// use dbox::client::Client;
/// use dbox::files;
///
/// let token = env::var("DROPBOX_TOKEN");
/// let client = Client::new(token);
/// let (metadata, response) = try!(files::download(&client, "/Path/to/file"));
/// ```
pub fn download<T: DropboxClient>(client: &T, path: &str) -> Result<(FileMetadata, Response)> {
    let mut map = BTreeMap::new();
    map.insert("path".to_string(), json::Json::String(path.to_string()));
    let mut headers = BTreeMap::new();
    headers.insert("Dropbox-API-Arg".to_string(), json::encode(&map).unwrap());
    let resp = try!(client.content("files/download", &mut headers, None::<&str>));
    let metadata: FileMetadata = match resp.api_result {
        Some(ref data) => {
            try!(json::decode(data))
        },
        None => return Err(ApiError::ClientError)
    };
    Ok((
        metadata,
        resp,
    ))
}

/// TODO implement
pub fn download_to_file<T>(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

/// TODO implement
pub fn get_metadata<T>(client: &T, path: &str, include_media_info: bool) -> Result<Metadata>
                where T: DropboxClient
{
    Ok(Default::default())
}

/// TODO implement
pub fn get_preview<T>(client: &T, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

/// TODO implement
pub fn get_preview_to_file<T>(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

pub fn get_thumbnail<T>(client: &T, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    get_thumbnail_with_options(client, path, Default::default())
}

/// TODO implement
pub fn get_thumbnail_with_options<T>(client: &T, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

pub fn get_thumbnail_to_file<T>(client: &T, dest_path: &str, path: &str) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    get_thumbnail_to_file_with_options(client, dest_path, path, Default::default())
}

/// TODO implement
pub fn get_thumbnail_to_file_with_options<T>(client: &T, dest_path: &str, path: &str, options: ThumbnailOptions) -> Result<(Metadata, Response)>
                where T: DropboxClient
{
    Ok((
        Default::default(),
        Response {
            status: 200,
            api_result: None,
            body: "".to_string(),
        },
    ))
}

/// TODO implement, need FolderList deser
pub fn list_folder<T: DropboxClient>(client: &T, path: &str) -> Result<FolderList> {
    let mut map = BTreeMap::new();
    map.insert("path".to_string(), json::Json::String("/OpenBudget".to_string()));
    map.insert("recursive".to_string(), json::Json::Boolean(false));
    map.insert("include_media_info".to_string(), json::Json::Boolean(false));
    map.insert("include_deleted".to_string(), json::Json::Boolean(false));
    let mut headers = BTreeMap::new();
    headers.insert("Content-Type".to_string(), "application/json".to_string());
    match client.api("files/list_folder", &mut headers, Some(&map)) {
        Ok(_) => Ok(Default::default()),
        Err(e) => Err(ApiError::ClientError),
    }
}

/// TODO implement
pub fn list_folder_continue<T>(client: &T, cursor: &str) -> Result<FolderList>
                where T: DropboxClient
{
    Ok(Default::default())
}

pub fn list_folder_get_latest_cursor<T>(client: &T, path: &str) -> Result<String>
                where T: DropboxClient
{
    list_folder_get_latest_cursor_with_options(client, path, Default::default())
}

/// TODO implement
pub fn list_folder_get_latest_cursor_with_options<T>(client: &T, path: &str, options: GetCursorOptions) -> Result<String>
                where T: DropboxClient
{
    Ok("".to_string())
}

/// TODO implement
pub fn list_folder_longpoll<T>(client: &T, cursor: &str, timeout: usize) -> Result<FolderListLongpoll>
                where T: DropboxClient
{
    Ok(FolderListLongpoll {
        changes: false,
        backoff: None,
    })
}

/// TODO implement
pub fn list_revisions<T>(client: &T, path: &str, limit: usize) -> Result<ListRevisions>
                where T: DropboxClient
{
    Ok(ListRevisions {
        is_deleted: false,
        entries: vec![],
    })
}

/// TODO implement
pub fn move_<T>(client: &T, from: &str, to: &str) -> Result<Metadata>
                where T: DropboxClient
{
    Ok(Default::default())
}

/// TODO implement
pub fn permanently_delete<T>(client: &T, path: &str) -> Result<()>
                where T: DropboxClient
{
    Ok(())
}

/// TODO implement
pub fn restore<T>(client: &T, path: &str, rev: &str) -> Result<Metadata>
                where T: DropboxClient
{
    Ok(Default::default())
}

pub fn search<T>(client: &T, path: &str, query: &str) -> Result<Search>
                where T: DropboxClient
{
    search_with_options(client, path, query, Default::default())
}

/// TODO implement
pub fn search_with_options<T>(client: &T, path: &str, query: &str, options: SearchOptions) -> Result<Search>
                where T: DropboxClient
{
    Ok(Search {
        matches: vec![],
        more: false,
        start: 0,
    })
}

pub fn upload<T>(client: &T, contents: &str, path: &str) -> Result<Metadata>
                where T: DropboxClient
{
    upload_with_options(client, contents, path, Default::default())
}

/// TODO implement
pub fn upload_with_options<T>(client: &T, contents: &str, path: &str, options: UploadOptions) -> Result<Metadata>
                where T: DropboxClient
{
    let mut map = BTreeMap::new();
    map.insert("path", json::Json::String(path.to_string()));
    map.insert("mode", json::Json::String(format!("{}", options.mode)));
    map.insert("autorename", json::Json::Boolean(options.autorename));
    map.insert("mute", json::Json::Boolean(options.mute));
    let mut headers = BTreeMap::new();
    headers.insert("Dropbox-API-Arg".to_string(), json::encode(&map).unwrap());
    headers.insert("Content-Type".to_string(), "application/octet-stream".to_string());
    let resp = client.content("files/upload", &mut headers, Some(contents.to_owned()));
    Ok(Default::default())
}

/// TODO implement
pub fn upload_session_append<T, U>(client: &T, f: U, session_id: &str, offset: usize) -> Result<()>
                where T: DropboxClient, U: io::Read
{
    Ok(())
}

/// TODO implement
pub fn upload_session_finish<T, U>(client: &T, f: U, cursor: &UploadSessionCursor, commit: &CommitInfo) -> Result<Metadata>
                where T: DropboxClient,
                      U: io::Read
{
    Ok(Default::default())
}

/// TODO implement
pub fn upload_session_start<T, U>(client: &T, f: U) -> Result<String>
                where T: DropboxClient,
                      U: io::Read
{
    Ok("".to_string())
}
<|endoftext|>


<commit_before>use std::ptr::null_mut;
use {
    ffi,
    BBox,
    BitmapGlyph,
    FtResult,
    Matrix,
    RenderMode,
    Vector
};

pub struct Glyph {
    library_raw: ffi::FT_Library,
    raw: ffi::FT_Glyph
}

impl Glyph {
    pub fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Glyph) -> Self {
        unsafe {
            ffi::FT_Reference_Library(library_raw);
        }
        Glyph {
            library_raw: library_raw,
            raw: raw
        }
    }

    pub fn transform(&self, mut matrix: Option<Matrix>, mut delta: Option<Vector>)
                     -> FtResult<()> {
        let mut p_matrix = null_mut();
        let mut p_delta = null_mut();

        if let Some(ref mut m) = matrix {
            p_matrix = m as *mut Matrix;
        }
        if let Some(ref mut d) = delta {
            p_delta = d as *mut Vector;
        }
        let err = unsafe {
            ffi::FT_Glyph_Transform(self.raw, p_matrix, p_delta)
        };
        if err == ffi::FT_Err_Ok {
            Ok(())
        } else {
            Err(err.into())
        }
    }

    pub fn get_cbox(&self, bbox_mode: ffi::FT_Glyph_BBox_Mode) -> BBox {
        let mut acbox = ffi::FT_BBox {
            xMin: 0,
            yMin: 0,
            xMax: 0,
            yMax: 0
        };
        unsafe {
            ffi::FT_Glyph_Get_CBox(self.raw, bbox_mode, &mut acbox)
        };
        acbox
    }

    pub fn to_bitmap(&self, render_mode: RenderMode, mut origin: Option<Vector>) -> FtResult<BitmapGlyph> {
        let mut the_glyph = self.raw;
        let mut p_origin = null_mut();

        if let Some(ref mut o) = origin {
            p_origin = o as *mut Vector;
        }
        let err = unsafe {
            ffi::FT_Glyph_To_Bitmap(&mut the_glyph, render_mode as u32, p_origin, 0)
        };
        if err == ffi::FT_Err_Ok {
            Ok(BitmapGlyph::from_raw(the_glyph as ffi::FT_BitmapGlyph))
        } else {
            Err(err.into())
        }
    }

    pub fn advance_x(&self) -> isize {
        unsafe {
            (*self.raw).advance.x as isize
        }
    }

    pub fn advance_y(&self) -> isize {
        unsafe {
            (*self.raw).advance.y as isize
        }
    }

    /// DEPRECATED: use advance_x and advance_y instead
    pub fn advance(&self) -> ffi::FT_Vector {
        unsafe {
            (*self.raw).advance
        }
    }

    #[inline(always)]
    pub fn format(&self) -> ffi::FT_Glyph_Format {
        unsafe {
            (*self.raw).format
        }
    }

    #[inline(always)]
    pub fn raw(&self) -> &ffi::FT_GlyphRec {
        unsafe {
            &*self.raw
        }
    }
}

impl Clone for Glyph {
    fn clone(&self) -> Self {
        let mut target = null_mut();

        let err = unsafe {
            ffi::FT_Glyph_Copy(self.raw, &mut target)
        };
        if err == ffi::FT_Err_Ok {
            Glyph::from_raw(self.library_raw, target)
        } else {
            panic!("Failed to copy glyph")
        }
    }
}

impl Drop for Glyph {
    fn drop(&mut self) {
        let err = unsafe {
            ffi::FT_Done_Glyph(self.raw);
            ffi::FT_Done_Library(self.library_raw)
        };
        if err != ffi::FT_Err_Ok {
            panic!("Failed to drop library")
        }
    }
}
<commit_msg>Remove deprecated 'Glyph::advance'.<commit_after>use std::ptr::null_mut;
use {
    ffi,
    BBox,
    BitmapGlyph,
    FtResult,
    Matrix,
    RenderMode,
    Vector
};

pub struct Glyph {
    library_raw: ffi::FT_Library,
    raw: ffi::FT_Glyph
}

impl Glyph {
    pub fn from_raw(library_raw: ffi::FT_Library, raw: ffi::FT_Glyph) -> Self {
        unsafe {
            ffi::FT_Reference_Library(library_raw);
        }
        Glyph {
            library_raw: library_raw,
            raw: raw
        }
    }

    pub fn transform(&self, mut matrix: Option<Matrix>, mut delta: Option<Vector>)
                     -> FtResult<()> {
        let mut p_matrix = null_mut();
        let mut p_delta = null_mut();

        if let Some(ref mut m) = matrix {
            p_matrix = m as *mut Matrix;
        }
        if let Some(ref mut d) = delta {
            p_delta = d as *mut Vector;
        }
        let err = unsafe {
            ffi::FT_Glyph_Transform(self.raw, p_matrix, p_delta)
        };
        if err == ffi::FT_Err_Ok {
            Ok(())
        } else {
            Err(err.into())
        }
    }

    pub fn get_cbox(&self, bbox_mode: ffi::FT_Glyph_BBox_Mode) -> BBox {
        let mut acbox = ffi::FT_BBox {
            xMin: 0,
            yMin: 0,
            xMax: 0,
            yMax: 0
        };
        unsafe {
            ffi::FT_Glyph_Get_CBox(self.raw, bbox_mode, &mut acbox)
        };
        acbox
    }

    pub fn to_bitmap(&self, render_mode: RenderMode, mut origin: Option<Vector>) -> FtResult<BitmapGlyph> {
        let mut the_glyph = self.raw;
        let mut p_origin = null_mut();

        if let Some(ref mut o) = origin {
            p_origin = o as *mut Vector;
        }
        let err = unsafe {
            ffi::FT_Glyph_To_Bitmap(&mut the_glyph, render_mode as u32, p_origin, 0)
        };
        if err == ffi::FT_Err_Ok {
            Ok(BitmapGlyph::from_raw(the_glyph as ffi::FT_BitmapGlyph))
        } else {
            Err(err.into())
        }
    }

    pub fn advance_x(&self) -> isize {
        unsafe {
            (*self.raw).advance.x as isize
        }
    }

    pub fn advance_y(&self) -> isize {
        unsafe {
            (*self.raw).advance.y as isize
        }
    }

    #[inline(always)]
    pub fn format(&self) -> ffi::FT_Glyph_Format {
        unsafe {
            (*self.raw).format
        }
    }

    #[inline(always)]
    pub fn raw(&self) -> &ffi::FT_GlyphRec {
        unsafe {
            &*self.raw
        }
    }
}

impl Clone for Glyph {
    fn clone(&self) -> Self {
        let mut target = null_mut();

        let err = unsafe {
            ffi::FT_Glyph_Copy(self.raw, &mut target)
        };
        if err == ffi::FT_Err_Ok {
            Glyph::from_raw(self.library_raw, target)
        } else {
            panic!("Failed to copy glyph")
        }
    }
}

impl Drop for Glyph {
    fn drop(&mut self) {
        let err = unsafe {
            ffi::FT_Done_Glyph(self.raw);
            ffi::FT_Done_Library(self.library_raw)
        };
        if err != ffi::FT_Err_Ok {
            panic!("Failed to drop library")
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(target_os = "linux")]
use secret_service::SsError;
use std::error;
use std::fmt;
use std::string::FromUtf8Error;

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

#[derive(Debug)]
pub enum KeyringError {
    #[cfg(target_os = "macos")]
    MacOsKeychainError,
    #[cfg(target_os = "linux")]
    SecretServiceError(SsError),
    #[cfg(target_os = "windows")]
    WindowsVaultError,
    NoBackendFound,
    NoPasswordFound,
    Parse(FromUtf8Error),
}

impl fmt::Display for KeyringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError => write!(f, "Mac Os Keychain Error"),
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => write!(f, "Secret Service Error: {}", err),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => write!(f, "Windows Vault Error"),
            KeyringError::NoBackendFound => write!(f, "Keyring error: No Backend Found"),
            KeyringError::NoPasswordFound => write!(f, "Keyring Error: No Password Found"),
            KeyringError::Parse(ref err) => write!(f, "Keyring Parse Error: {}", err),
        }
    }
}

impl error::Error for KeyringError {
    fn description(&self) -> &str {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError => "Mac Os Keychain Error",
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => err.description(),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => "Windows Vault Error",
            KeyringError::NoBackendFound => "No Backend Found",
            KeyringError::NoPasswordFound => "No Password Found",
            KeyringError::Parse(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => Some(err),
            _ => None,
        }
    }
}

#[cfg(target_os = "linux")]
impl From<SsError> for KeyringError {
    fn from(err: SsError) -> KeyringError {
        KeyringError::SecretServiceError(err)
    }
}

impl From<FromUtf8Error> for KeyringError {
    fn from(err: FromUtf8Error) -> KeyringError {
        KeyringError::Parse(err)
    }
}
<commit_msg>Add From<SfError> impl for Mac security-framework errors<commit_after>#[cfg(target_os = "linux")]
use secret_service::SsError;
#[cfg(target_os = "macos")]
use security_framework::base::Error as SfError;
use std::error;
use std::fmt;
use std::string::FromUtf8Error;

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

#[derive(Debug)]
pub enum KeyringError {
    #[cfg(target_os = "macos")]
    MacOsKeychainError,
    #[cfg(target_os = "linux")]
    SecretServiceError(SsError),
    #[cfg(target_os = "windows")]
    WindowsVaultError,
    NoBackendFound,
    NoPasswordFound,
    Parse(FromUtf8Error),
}

impl fmt::Display for KeyringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError => write!(f, "Mac Os Keychain Error"),
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => write!(f, "Secret Service Error: {}", err),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => write!(f, "Windows Vault Error"),
            KeyringError::NoBackendFound => write!(f, "Keyring error: No Backend Found"),
            KeyringError::NoPasswordFound => write!(f, "Keyring Error: No Password Found"),
            KeyringError::Parse(ref err) => write!(f, "Keyring Parse Error: {}", err),
        }
    }
}

impl error::Error for KeyringError {
    fn description(&self) -> &str {
        match *self {
            #[cfg(target_os = "macos")]
            KeyringError::MacOsKeychainError => "Mac Os Keychain Error",
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => err.description(),
            #[cfg(target_os = "windows")]
            KeyringError::WindowsVaultError => "Windows Vault Error",
            KeyringError::NoBackendFound => "No Backend Found",
            KeyringError::NoPasswordFound => "No Password Found",
            KeyringError::Parse(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            #[cfg(target_os = "linux")]
            KeyringError::SecretServiceError(ref err) => Some(err),
            _ => None,
        }
    }
}

#[cfg(target_os = "linux")]
impl From<SsError> for KeyringError {
    fn from(err: SsError) -> KeyringError {
        KeyringError::SecretServiceError(err)
    }
}

#[cfg(target_os = "macos")]
impl From<SfError> for KeyringError {
    fn from(err: SfError) -> KeyringError {
        KeyringError::MacOsKeychainError(err)
    }
}

impl From<FromUtf8Error> for KeyringError {
    fn from(err: FromUtf8Error) -> KeyringError {
        KeyringError::Parse(err)
    }
}
<|endoftext|>


<commit_before>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
bitflags! {
    pub flags CGEventFlags: u64 {
        const CGEventFlagNull = 0,

        // Device-independent modifier key bits.
        const CGEventFlagAlphaShift = 0x00010000,
        const CGEventFlagShift = 0x00020000,
        const CGEventFlagControl = 0x00040000,
        const CGEventFlagAlternate = 0x00080000,
        const CGEventFlagCommand = 0x00100000,

        // Special key identifiers.
        const CGEventFlagHelp = 0x00400000,
        const CGEventFlagSecondaryFn = 0x00800000,

        // Identifies key events from numeric keypad area on extended keyboards.
        const CGEventFlagNumericPad = 0x00200000,

        // Indicates if mouse/pen movement events are not being coalesced
        const CGEventFlagNonCoalesced = 0x00000100,
    }
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 0,

    // Mouse events.
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    RightMouseDown = 3,
    RightMouseUp = 4,
    MouseMoved = 5,
    LeftMouseDragged = 6,
    RightMouseDragged = 7,

    // Keyboard events.
    KeyDown = 10,
    KeyUp = 11,
    FlagsChanged = 12,

    // Specialized control devices.
    ScrollWheel = 22,
    TabletPointer = 23,
    TabletProximity = 24,
    OtherMouseDown = 25,
    OtherMouseUp = 26,
    OtherMouseDragged = 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }

    pub fn set_type(&self, event_type: CGEventType) {
        unsafe {
            CGEventSetType(self.as_concrete_TypeRef(), event_type);
        }
    }

    pub fn get_type(&self) -> CGEventType {
        unsafe {
            CGEventGetType(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;

    /// Set the event type of an event.
    fn CGEventSetType(event: CGEventRef, eventType: CGEventType);

    /// Return the event type of an event (left mouse down, for example).
    fn CGEventGetType(event: CGEventRef) -> CGEventType;
}
<commit_msg>Auto merge of #73 - msanders:ms/set-string, r=jdm<commit_after>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
bitflags! {
    pub flags CGEventFlags: u64 {
        const CGEventFlagNull = 0,

        // Device-independent modifier key bits.
        const CGEventFlagAlphaShift = 0x00010000,
        const CGEventFlagShift = 0x00020000,
        const CGEventFlagControl = 0x00040000,
        const CGEventFlagAlternate = 0x00080000,
        const CGEventFlagCommand = 0x00100000,

        // Special key identifiers.
        const CGEventFlagHelp = 0x00400000,
        const CGEventFlagSecondaryFn = 0x00800000,

        // Identifies key events from numeric keypad area on extended keyboards.
        const CGEventFlagNumericPad = 0x00200000,

        // Indicates if mouse/pen movement events are not being coalesced
        const CGEventFlagNonCoalesced = 0x00000100,
    }
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 0,

    // Mouse events.
    LeftMouseDown = 1,
    LeftMouseUp = 2,
    RightMouseDown = 3,
    RightMouseUp = 4,
    MouseMoved = 5,
    LeftMouseDragged = 6,
    RightMouseDragged = 7,

    // Keyboard events.
    KeyDown = 10,
    KeyUp = 11,
    FlagsChanged = 12,

    // Specialized control devices.
    ScrollWheel = 22,
    TabletPointer = 23,
    TabletProximity = 24,
    OtherMouseDown = 25,
    OtherMouseUp = 26,
    OtherMouseDragged = 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HID,
    Session,
    AnnotatedSession,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreate(source.as_concrete_TypeRef());
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_keyboard_event(
        source: CGEventSource,
        keycode: CGKeyCode,
        keydown: bool
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn new_mouse_event(
        source: CGEventSource,
        mouse_type: CGEventType,
        mouse_cursor_position: CGPoint,
        mouse_button: CGMouseButton
    ) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateMouseEvent(source.as_concrete_TypeRef(), mouse_type,
                mouse_cursor_position, mouse_button);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tap_location: CGEventTapLocation) {
        unsafe {
            CGEventPost(tap_location, self.as_concrete_TypeRef());
        }
    }

    pub fn location(&self) -> CGPoint {
        unsafe {
            CGEventGetLocation(self.as_concrete_TypeRef())
        }
    }

    #[cfg(feature = "elcapitan")]
    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }

    pub fn set_type(&self, event_type: CGEventType) {
        unsafe {
            CGEventSetType(self.as_concrete_TypeRef(), event_type);
        }
    }

    pub fn get_type(&self) -> CGEventType {
        unsafe {
            CGEventGetType(self.as_concrete_TypeRef())
        }
    }

    pub fn set_string_from_utf16_unchecked(&self, buf: &[u16]) {
        let buflen = buf.len() as libc::c_ulong;
        unsafe {
            CGEventKeyboardSetUnicodeString(self.as_concrete_TypeRef(), buflen, buf.as_ptr());
        }
    }

    pub fn set_string(&self, string: &str) {
        let buf: Vec<u16> = string.encode_utf16().collect();
        self.set_string_from_utf16_unchecked(&buf);
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new event using the event source `source'. If `source' is NULL,
    /// the default source is used.
    fn CGEventCreate(source: CGEventSourceRef) -> CGEventRef;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    #[cfg(feature = "elcapitan")]
    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;

    /// Return the location of an event in global display coordinates.
    /// CGPointZero is returned if event is not a valid CGEventRef.
    fn CGEventGetLocation(event: CGEventRef) -> CGPoint;

    /// Set the event type of an event.
    fn CGEventSetType(event: CGEventRef, eventType: CGEventType);

    /// Return the event type of an event (left mouse down, for example).
    fn CGEventGetType(event: CGEventRef) -> CGEventType;

    /// Set the Unicode string associated with a keyboard event.
    ///
    /// By default, the system translates the virtual key code in a keyboard
    /// event into a Unicode string based on the keyboard ID in the event
    /// source.  This function allows you to manually override this string.
    /// Note that application frameworks may ignore the Unicode string in a
    /// keyboard event and do their own translation based on the virtual
    /// keycode and perceived event state.
    fn CGEventKeyboardSetUnicodeString(event: CGEventRef,
                                       length: libc::c_ulong,
                                       string: *const u16);
}
<|endoftext|>


<commit_before>use std::error::FromError;
use std::mem;
use std::io;
use std::slice;

use color;
use color::ColorType;
use buffer::{ImageBuffer, Pixel};
use traits::Primitive;

use animation::{Frame, Frames};
use dynimage::decoder_to_image;

/// An enumeration of Image Errors
#[deriving(Show, PartialEq, Eq)]
pub enum ImageError {
    /// The Image is not formatted properly
    FormatError(String),

    /// The Image's dimensions are either too small or too large
    DimensionError,

    /// The Decoder does not support this image format
    UnsupportedError(String),

    /// The Decoder does not support this color type
    UnsupportedColor(ColorType),

    /// Not enough data was provided to the Decoder
    /// to decode the image
    NotEnoughData,

    /// An I/O Error occurred while decoding the image
    IoError(io::IoError),

    /// The end of the image has been reached
    ImageEnd
}

impl FromError<io::IoError> for ImageError {
    fn from_error(err: io::IoError) -> ImageError {
        ImageError::IoError(err)
    }
}

/// Result of an image decoding/encoding process
pub type ImageResult<T> = Result<T, ImageError>;

/// Result of a decoding process
pub enum DecodingResult {
    /// A vector of unsigned bytes
    U8(Vec<u8>),
    /// A vector of unsigned words
    U16(Vec<u16>)
}

// A buffer for image decoding
pub enum DecodingBuffer<'a> {
    /// A slice of unsigned bytes
    U8(&'a mut [u8]),
    /// A slice of unsigned words
    U16(&'a mut [u16])
}

/// An enumeration of supported image formats.
/// Not all formats support both encoding and decoding.
#[deriving(Copy, PartialEq, Eq, Show)]
pub enum ImageFormat {
    /// An Image in PNG Format
    PNG,

    /// An Image in JPEG Format
    JPEG,

    /// An Image in GIF Format
    GIF,

    /// An Image in WEBP Format
    WEBP,

    /// An Image in PPM Format
    PPM,

    /// An Image in TIFF Format
    TIFF,

    /// An Image in TGA Format
    TGA
}

/// The trait that all decoders implement
pub trait ImageDecoder {
    /// Returns a tuple containing the width and height of the image
    fn dimensions(&mut self) -> ImageResult<(u32, u32)>;

    /// Returns the color type of the image e.g RGB(8) (8bit RGB)
    fn colortype(&mut self) -> ImageResult<ColorType>;

    /// Returns the length in bytes of one decoded row of the image
    fn row_len(&mut self) -> ImageResult<uint>;

    /// Returns true if the image is animated
    fn is_animated(&mut self) -> bool {
        // since most image formats do not support animation
        // just return false by default
        return false
    }

    /// Returns the frames of the image
    /// If the image is not animated it returns a single frame
    fn into_frames(self) -> ImageResult<Frames> {
        Ok(Frames::new(vec![
            Frame::new(try!(decoder_to_image(self)).to_rgba())
        ]))
    }

    /// Reads one row from the image into buf and returns the row index
    fn read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>;

    /// Decodes the entire image and return it as a Vector
    fn read_image(&mut self) -> ImageResult<DecodingResult>;

    /// Decodes a specific region of the image, represented by the rectangle
    /// starting from ```x``` and ```y``` and having ```length``` and ```width```
    fn load_rect(&mut self, x: u32, y: u32, length: u32, width: u32) -> ImageResult<Vec<u8>> {
        let (w, h) = try!(self.dimensions());

        if length > h || width > w || x > w || y > h {
            return Err(ImageError::DimensionError)
        }

        let c = try!(self.colortype());

        let bpp = color::bits_per_pixel(c) / 8;

        let rowlen  = try!(self.row_len());

        let mut buf = Vec::from_elem(length as uint * width as uint * bpp, 0u8);
        let mut tmp = Vec::from_elem(rowlen, 0u8);

        loop {
            let row = try!(self.read_scanline(tmp.as_mut_slice()));

            if row - 1 == y {
                break
            }
        }

        for i in range(0, length as uint) {
            {
                let from = tmp.slice_from(x as uint * bpp)
                              .slice_to(width as uint * bpp);

                let to   = buf.slice_from_mut(i * width as uint * bpp)
                              .slice_to_mut(width as uint * bpp);

                slice::bytes::copy_memory(to, from);
            }

            let _ = try!(self.read_scanline(tmp.as_mut_slice()));
        }

        Ok(buf)
    }
}

/// Immutable pixel iterator
pub struct Pixels<'a, I:'a> {
    image:  &'a I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> Iterator<(u32, u32, P)> for Pixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let pixel = self.image.get_pixel(self.x, self.y);
            let p = (self.x, self.y, pixel);

            self.x += 1;

            Some(p)
        }
    }
}

/// Mutable pixel iterator
#[deprecated = "It is currently not possible to create a safe iterator for this in Rust. You have to use an iterator over the image buffer instead."]
pub struct MutPixels<'a, I:'a> {
    image:  &'a mut I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> Iterator<(u32, u32, &'a mut P)> for MutPixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, &'a mut P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let tmp = self.image.get_pixel_mut(self.x, self.y);

            // NOTE: This is potentially dangerous. It would require the signature fn next(&'a mut self) to be safe.
            // error: lifetime of `self` is too short to guarantee its contents can be safely reborrowed...
            let ptr = unsafe {
                mem::transmute(tmp)
            };

            let p = (self.x, self.y, ptr);

            self.x += 1;

            Some(p)
        }
    }
}

/// A trait for manipulating images.
pub trait GenericImage<P> {
    /// The width and height of this image.
    fn dimensions(&self) -> (u32, u32);

    /// The bounding rectangle of this image.
    fn bounds(&self) -> (u32, u32, u32, u32);

    /// Returns the pixel located at (x, y)
    ///
    /// # Panics
    ///
    /// Panics if `(x, y)` is out of bounds.
    /// TODO: change this signature to &P
    fn get_pixel(&self, x: u32, y: u32) -> P;

    /// Puts a pixel at location (x, y)
    ///
    /// # Panics
    ///
    /// Panics if `(x, y)` is out of bounds.
    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P;

    /// Put a pixel at location (x, y)
    ///
    /// # Panics
    ///
    /// Panics if `(x, y)` is out of bounds.
    fn put_pixel(&mut self, x: u32, y: u32, pixel: P);

    /// Put a pixel at location (x, y), taking into account alpha channels
    #[deprecated = "This method will be removed. Blend the pixel directly instead."]
    fn blend_pixel(&mut self, x: u32, y: u32, pixel: P);

    /// Returns an Iterator over the pixels of this image.
    /// The iterator yields the coordinates of each pixel
    /// along with their value
    fn pixels(&self) -> Pixels<Self> {
        let (width, height) = self.dimensions();

        Pixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }

    /// Returns an Iterator over mutable pixels of this image.
    /// The iterator yields the coordinates of each pixel
    /// along with a mutable reference to them.
    #[allow(deprecated)]
    #[deprecated = "This cannot be implemented safely Rust. Please use the image buffer directly."]
    fn pixels_mut(&mut self) -> MutPixels<Self> {
        let (width, height) = self.dimensions();

        MutPixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }
}

/// A View into another image
pub struct SubImage <'a, I:'a> {
    image:   &'a mut I,
    xoffset: u32,
    yoffset: u32,
    xstride: u32,
    ystride: u32,
}

impl<'a, T: Primitive + 'static, P: Pixel<T> + 'static, I: GenericImage<P>> SubImage<'a, I> {
    /// Construct a new subimage
    pub fn new(image: &mut I, x: u32, y: u32, width: u32, height: u32) -> SubImage<I> {
        SubImage {
            image:   image,
            xoffset: x,
            yoffset: y,
            xstride: width,
            ystride: height,
        }
    }

    /// Returns a mutable reference to the wrapped image.
    pub fn inner_mut(&mut self) -> &mut I {
        &mut (*self.image)
    }

    /// Change the coordinates of this subimage.
    pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) {
        self.xoffset = x;
        self.yoffset = y;
        self.xstride = width;
        self.ystride = height;
    }

    /// Convert this subimage to an ImageBuffer
    pub fn to_image(&self) -> ImageBuffer<Vec<T>, T, P> {
        let mut out = ImageBuffer::new(self.xstride, self.ystride);

        for y in range(0, self.ystride) {
            for x in range(0, self.xstride) {
                let p = self.get_pixel(x, y);
                out.put_pixel(x, y, p);
            }
        }

        out
    }
}

#[allow(deprecated)]
impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> GenericImage<P> for SubImage<'a, I> {
    fn dimensions(&self) -> (u32, u32) {
        (self.xstride, self.ystride)
    }

    fn bounds(&self) -> (u32, u32, u32, u32) {
        (self.xoffset, self.yoffset, self.xstride, self.ystride)
    }

    fn get_pixel(&self, x: u32, y: u32) -> P {
        self.image.get_pixel(x + self.xoffset, y + self.yoffset)
    }

    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
        self.image.put_pixel(x + self.xoffset, y + self.yoffset, pixel)
    }

    #[deprecated = "This method will be removed. Blend the pixel directly instead."]
    fn blend_pixel(&mut self, x: u32, y: u32, pixel: P) {
        self.image.blend_pixel(x + self.xoffset, y + self.yoffset, pixel)
    }

    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
        self.image.get_pixel_mut(x + self.xoffset, y + self.yoffset)
    }
}

#[cfg(test)]
mod tests {

    use super::GenericImage;
    use buffer::ImageBuffer;
    use color::{Rgba};

    #[test]
    /// Test that alpha blending works as expected
    #[allow(deprecated)]
    fn test_image_alpha_blending() {
        let mut target = ImageBuffer::new(1, 1);
        target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
        assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255]));
        target.blend_pixel(0, 0, Rgba([0, 255, 0, 255]));
        assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255]));

        // Blending an alpha channel onto a solid background
        target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
        assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255]));

        // Blending two alpha channels
        target.put_pixel(0, 0, Rgba([0, 255, 0, 127]));
        target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
        assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190]));
    }
}
<commit_msg>to result…<commit_after>use std::error::FromError;
use std::mem;
use std::io;
use std::slice;

use color;
use color::ColorType;
use buffer::{ImageBuffer, Pixel};
use traits::Primitive;

use animation::{Frame, Frames};
use dynimage::decoder_to_image;

/// An enumeration of Image Errors
#[deriving(Show, PartialEq, Eq)]
pub enum ImageError {
    /// The Image is not formatted properly
    FormatError(String),

    /// The Image's dimensions are either too small or too large
    DimensionError,

    /// The Decoder does not support this image format
    UnsupportedError(String),

    /// The Decoder does not support this color type
    UnsupportedColor(ColorType),

    /// Not enough data was provided to the Decoder
    /// to decode the image
    NotEnoughData,

    /// An I/O Error occurred while decoding the image
    IoError(io::IoError),

    /// The end of the image has been reached
    ImageEnd
}

impl FromError<io::IoError> for ImageError {
    fn from_error(err: io::IoError) -> ImageError {
        ImageError::IoError(err)
    }
}

/// Result of an image decoding/encoding process
pub type ImageResult<T> = Result<T, ImageError>;

/// Result of a decoding process
pub enum DecodingResult {
    /// A vector of unsigned bytes
    U8(Vec<u8>),
    /// A vector of unsigned words
    U16(Vec<u16>)
}

// A buffer for image decoding
pub enum DecodingBuffer<'a> {
    /// A slice of unsigned bytes
    U8(&'a mut [u8]),
    /// A slice of unsigned words
    U16(&'a mut [u16])
}

/// An enumeration of supported image formats.
/// Not all formats support both encoding and decoding.
#[deriving(Copy, PartialEq, Eq, Show)]
pub enum ImageFormat {
    /// An Image in PNG Format
    PNG,

    /// An Image in JPEG Format
    JPEG,

    /// An Image in GIF Format
    GIF,

    /// An Image in WEBP Format
    WEBP,

    /// An Image in PPM Format
    PPM,

    /// An Image in TIFF Format
    TIFF,

    /// An Image in TGA Format
    TGA
}

/// The trait that all decoders implement
pub trait ImageDecoder {
    /// Returns a tuple containing the width and height of the image
    fn dimensions(&mut self) -> ImageResult<(u32, u32)>;

    /// Returns the color type of the image e.g RGB(8) (8bit RGB)
    fn colortype(&mut self) -> ImageResult<ColorType>;

    /// Returns the length in bytes of one decoded row of the image
    fn row_len(&mut self) -> ImageResult<uint>;

    /// Returns true if the image is animated
    fn is_animated(&mut self) -> ImageResult<bool> {
        // since most image formats do not support animation
        // just return false by default
        return Ok(false)
    }

    /// Returns the frames of the image
    /// If the image is not animated it returns a single frame
    fn into_frames(self) -> ImageResult<Frames> {
        Ok(Frames::new(vec![
            Frame::new(try!(decoder_to_image(self)).to_rgba())
        ]))
    }

    /// Reads one row from the image into buf and returns the row index
    fn read_scanline(&mut self, buf: &mut [u8]) -> ImageResult<u32>;

    /// Decodes the entire image and return it as a Vector
    fn read_image(&mut self) -> ImageResult<DecodingResult>;

    /// Decodes a specific region of the image, represented by the rectangle
    /// starting from ```x``` and ```y``` and having ```length``` and ```width```
    fn load_rect(&mut self, x: u32, y: u32, length: u32, width: u32) -> ImageResult<Vec<u8>> {
        let (w, h) = try!(self.dimensions());

        if length > h || width > w || x > w || y > h {
            return Err(ImageError::DimensionError)
        }

        let c = try!(self.colortype());

        let bpp = color::bits_per_pixel(c) / 8;

        let rowlen  = try!(self.row_len());

        let mut buf = Vec::from_elem(length as uint * width as uint * bpp, 0u8);
        let mut tmp = Vec::from_elem(rowlen, 0u8);

        loop {
            let row = try!(self.read_scanline(tmp.as_mut_slice()));

            if row - 1 == y {
                break
            }
        }

        for i in range(0, length as uint) {
            {
                let from = tmp.slice_from(x as uint * bpp)
                              .slice_to(width as uint * bpp);

                let to   = buf.slice_from_mut(i * width as uint * bpp)
                              .slice_to_mut(width as uint * bpp);

                slice::bytes::copy_memory(to, from);
            }

            let _ = try!(self.read_scanline(tmp.as_mut_slice()));
        }

        Ok(buf)
    }
}

/// Immutable pixel iterator
pub struct Pixels<'a, I:'a> {
    image:  &'a I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> Iterator<(u32, u32, P)> for Pixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let pixel = self.image.get_pixel(self.x, self.y);
            let p = (self.x, self.y, pixel);

            self.x += 1;

            Some(p)
        }
    }
}

/// Mutable pixel iterator
#[deprecated = "It is currently not possible to create a safe iterator for this in Rust. You have to use an iterator over the image buffer instead."]
pub struct MutPixels<'a, I:'a> {
    image:  &'a mut I,
    x:      u32,
    y:      u32,
    width:  u32,
    height: u32
}

impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> Iterator<(u32, u32, &'a mut P)> for MutPixels<'a, I> {
    fn next(&mut self) -> Option<(u32, u32, &'a mut P)> {
        if self.x >= self.width {
            self.x =  0;
            self.y += 1;
        }

        if self.y >= self.height {
            None
        } else {
            let tmp = self.image.get_pixel_mut(self.x, self.y);

            // NOTE: This is potentially dangerous. It would require the signature fn next(&'a mut self) to be safe.
            // error: lifetime of `self` is too short to guarantee its contents can be safely reborrowed...
            let ptr = unsafe {
                mem::transmute(tmp)
            };

            let p = (self.x, self.y, ptr);

            self.x += 1;

            Some(p)
        }
    }
}

/// A trait for manipulating images.
pub trait GenericImage<P> {
    /// The width and height of this image.
    fn dimensions(&self) -> (u32, u32);

    /// The bounding rectangle of this image.
    fn bounds(&self) -> (u32, u32, u32, u32);

    /// Returns the pixel located at (x, y)
    ///
    /// # Panics
    ///
    /// Panics if `(x, y)` is out of bounds.
    /// TODO: change this signature to &P
    fn get_pixel(&self, x: u32, y: u32) -> P;

    /// Puts a pixel at location (x, y)
    ///
    /// # Panics
    ///
    /// Panics if `(x, y)` is out of bounds.
    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P;

    /// Put a pixel at location (x, y)
    ///
    /// # Panics
    ///
    /// Panics if `(x, y)` is out of bounds.
    fn put_pixel(&mut self, x: u32, y: u32, pixel: P);

    /// Put a pixel at location (x, y), taking into account alpha channels
    #[deprecated = "This method will be removed. Blend the pixel directly instead."]
    fn blend_pixel(&mut self, x: u32, y: u32, pixel: P);

    /// Returns an Iterator over the pixels of this image.
    /// The iterator yields the coordinates of each pixel
    /// along with their value
    fn pixels(&self) -> Pixels<Self> {
        let (width, height) = self.dimensions();

        Pixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }

    /// Returns an Iterator over mutable pixels of this image.
    /// The iterator yields the coordinates of each pixel
    /// along with a mutable reference to them.
    #[allow(deprecated)]
    #[deprecated = "This cannot be implemented safely Rust. Please use the image buffer directly."]
    fn pixels_mut(&mut self) -> MutPixels<Self> {
        let (width, height) = self.dimensions();

        MutPixels {
            image:  self,
            x:      0,
            y:      0,
            width:  width,
            height: height,
        }
    }
}

/// A View into another image
pub struct SubImage <'a, I:'a> {
    image:   &'a mut I,
    xoffset: u32,
    yoffset: u32,
    xstride: u32,
    ystride: u32,
}

impl<'a, T: Primitive + 'static, P: Pixel<T> + 'static, I: GenericImage<P>> SubImage<'a, I> {
    /// Construct a new subimage
    pub fn new(image: &mut I, x: u32, y: u32, width: u32, height: u32) -> SubImage<I> {
        SubImage {
            image:   image,
            xoffset: x,
            yoffset: y,
            xstride: width,
            ystride: height,
        }
    }

    /// Returns a mutable reference to the wrapped image.
    pub fn inner_mut(&mut self) -> &mut I {
        &mut (*self.image)
    }

    /// Change the coordinates of this subimage.
    pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) {
        self.xoffset = x;
        self.yoffset = y;
        self.xstride = width;
        self.ystride = height;
    }

    /// Convert this subimage to an ImageBuffer
    pub fn to_image(&self) -> ImageBuffer<Vec<T>, T, P> {
        let mut out = ImageBuffer::new(self.xstride, self.ystride);

        for y in range(0, self.ystride) {
            for x in range(0, self.xstride) {
                let p = self.get_pixel(x, y);
                out.put_pixel(x, y, p);
            }
        }

        out
    }
}

#[allow(deprecated)]
impl<'a, T: Primitive, P: Pixel<T>, I: GenericImage<P>> GenericImage<P> for SubImage<'a, I> {
    fn dimensions(&self) -> (u32, u32) {
        (self.xstride, self.ystride)
    }

    fn bounds(&self) -> (u32, u32, u32, u32) {
        (self.xoffset, self.yoffset, self.xstride, self.ystride)
    }

    fn get_pixel(&self, x: u32, y: u32) -> P {
        self.image.get_pixel(x + self.xoffset, y + self.yoffset)
    }

    fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
        self.image.put_pixel(x + self.xoffset, y + self.yoffset, pixel)
    }

    #[deprecated = "This method will be removed. Blend the pixel directly instead."]
    fn blend_pixel(&mut self, x: u32, y: u32, pixel: P) {
        self.image.blend_pixel(x + self.xoffset, y + self.yoffset, pixel)
    }

    fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
        self.image.get_pixel_mut(x + self.xoffset, y + self.yoffset)
    }
}

#[cfg(test)]
mod tests {

    use super::GenericImage;
    use buffer::ImageBuffer;
    use color::{Rgba};

    #[test]
    /// Test that alpha blending works as expected
    #[allow(deprecated)]
    fn test_image_alpha_blending() {
        let mut target = ImageBuffer::new(1, 1);
        target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
        assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255]));
        target.blend_pixel(0, 0, Rgba([0, 255, 0, 255]));
        assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255]));

        // Blending an alpha channel onto a solid background
        target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
        assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255]));

        // Blending two alpha channels
        target.put_pixel(0, 0, Rgba([0, 255, 0, 127]));
        target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
        assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190]));
    }
}
<|endoftext|>


<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// 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; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 gtype::GType;
use types::guint;

use std::error::Error as ErrorTrait;
use std::fmt;

pub trait IntrospectedFlags {
    fn from_uint(v: guint) -> Result<Self, UnknownFlags>;
    fn to_uint(&self) -> guint;
}

pub trait FlagsType : IntrospectedFlags {
    fn get_type() -> GType;
}

#[derive(Copy)]
pub struct UnknownFlags {
    actual: guint,
    known_mask: guint
}

impl UnknownFlags {
    pub fn new(flags: guint, known_mask: guint) -> UnknownFlags {
        UnknownFlags { actual: flags, known_mask: known_mask }
    }

    pub fn actual(&self) -> guint { self.actual }
    pub fn unknown(&self) -> guint { self.actual & !self.known_mask }
    pub fn known(&self) -> guint { self.actual & self.known_mask }
}

impl ErrorTrait for UnknownFlags {
    fn description(&self) -> &str {
        "unknown bit flags encountered"
    }
}

impl fmt::Display for UnknownFlags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "unsupported bit flag value 0b{:b} (unknown flags: 0b{:b})",
               self.actual(), self.unknown())
    }
}

impl fmt::Debug for UnknownFlags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "UnknownFlags {{ actual: 0b{:b}, known_mask: 0b{:b} }}",
               self.actual, self.known_mask)
    }
}

pub fn from_uint<F>(v: guint) -> Result<F, UnknownFlags>
    where F: IntrospectedFlags
{
    IntrospectedFlags::from_uint(v)
}

pub fn type_of<F>() -> GType where F: FlagsType {
    <F as FlagsType>::get_type()
}
<commit_msg>Added module flags::prelude<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// 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; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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 gtype::GType;
use types::guint;

use std::error::Error as ErrorTrait;
use std::fmt;

pub trait IntrospectedFlags {
    fn from_uint(v: guint) -> Result<Self, UnknownFlags>;
    fn to_uint(&self) -> guint;
}

pub trait FlagsType : IntrospectedFlags {
    fn get_type() -> GType;
}

#[derive(Copy)]
pub struct UnknownFlags {
    actual: guint,
    known_mask: guint
}

impl UnknownFlags {
    pub fn new(flags: guint, known_mask: guint) -> UnknownFlags {
        UnknownFlags { actual: flags, known_mask: known_mask }
    }

    pub fn actual(&self) -> guint { self.actual }
    pub fn unknown(&self) -> guint { self.actual & !self.known_mask }
    pub fn known(&self) -> guint { self.actual & self.known_mask }
}

pub mod prelude {
    pub use super::{IntrospectedFlags, FlagsType, UnknownFlags};
    pub use gtype::GType;
    pub use types::guint;
}

impl ErrorTrait for UnknownFlags {
    fn description(&self) -> &str {
        "unknown bit flags encountered"
    }
}

impl fmt::Display for UnknownFlags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "unsupported bit flag value 0b{:b} (unknown flags: 0b{:b})",
               self.actual(), self.unknown())
    }
}

impl fmt::Debug for UnknownFlags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "UnknownFlags {{ actual: 0b{:b}, known_mask: 0b{:b} }}",
               self.actual, self.known_mask)
    }
}

pub fn from_uint<F>(v: guint) -> Result<F, UnknownFlags>
    where F: IntrospectedFlags
{
    IntrospectedFlags::from_uint(v)
}

pub fn type_of<F>() -> GType where F: FlagsType {
    <F as FlagsType>::get_type()
}
<|endoftext|>


<commit_before>use primitive::*;

#[derive(Copy, Clone)]
pub struct Tile {
    pub wall : Option<char>,
}

impl Tile {
    pub fn new(wall : Option<char>) -> Self {
        if let Some(s) = wall {
            Self { wall: Some(s) }
        } else {
            Self { wall: None }
        }
    }
}

pub struct Floor {
    pub rows: usize,
    pub cols: usize,
    pub tiles: Vec<Vec<Tile>>
}

impl Floor {
    pub fn new(cols : usize, rows : usize) -> Self {
        // Tiles to use
        let horizontal   = Tile::new(Some('─')); // U-2500
        let vertical     = Tile::new(Some('│')); // U-2502
        let top_left     = Tile::new(Some('┌')); // U-250c
        let top_right    = Tile::new(Some('┐')); // U-2510
        let bottom_left  = Tile::new(Some('└')); // U-2514
        let bottom_right = Tile::new(Some('┘')); // U-2518
        let blank        = Tile::new(None);

        // Create tiles 2D Vec and populate with empty rows
        let mut tiles = Vec::<Vec<Tile>>::with_capacity(rows);
        for _ in 0..rows {
            tiles.push(Vec::<Tile>::with_capacity(rows));
        }
        // First row is all wall
        tiles[0].push(top_left);
        for _ in 1..cols-1 {
            tiles[0].push(horizontal);
        }
        tiles[0].push(top_right);
        // Middle rows are vertical sides and blank middles
        for row in 1..rows-1 {
            tiles[row].push(vertical);
            for _ in 1..cols-1 {
                tiles[row].push(blank);
            }
            tiles[row].push(vertical);
        }
        // Bottom row is also all wall
        tiles[rows-1].push(bottom_left);
        for _ in 1..cols-1 {
            tiles[rows-1].push(horizontal);
        }
        tiles[rows-1].push(bottom_right);

        // Create the floor
        Self {
            rows: rows,
            cols: cols,
            tiles: tiles,
        }
    }
    pub fn get_symbol(&self, coord : &Coord) -> String {
        if let Some(wall) = self.tiles[coord.row as usize][coord.col as usize].wall {
            wall.to_string()
        } else {
            " ".to_string()
        }
    }
    pub fn is_wall(&self, coord : &Coord) -> bool {
        self.tiles[coord.row as usize][coord.col as usize].wall.is_some()
    }
}
<commit_msg>Simplify<commit_after>use ::*;

#[derive(Copy, Clone)]
pub struct Tile {
    pub wall : Option<char>,
}

impl Tile {
    pub fn new(wall : Option<char>) -> Self {
        if let Some(s) = wall {
            Self { wall: Some(s) }
        } else {
            Self { wall: None }
        }
    }
}

pub struct Floor {
    pub rows: usize,
    pub cols: usize,
    pub tiles: Vec<Vec<Tile>>
}

impl Floor {
    pub fn new(cols : usize, rows : usize) -> Self {
        // Tiles to use
        let horizontal   = Tile::new(Some('─')); // U-2500
        let vertical     = Tile::new(Some('│')); // U-2502
        let top_left     = Tile::new(Some('┌')); // U-250c
        let top_right    = Tile::new(Some('┐')); // U-2510
        let bottom_left  = Tile::new(Some('└')); // U-2514
        let bottom_right = Tile::new(Some('┘')); // U-2518
        let blank        = Tile::new(None);

        // Create tiles 2D Vec and populate with empty rows
        let mut tiles = Vec::<Vec<Tile>>::with_capacity(rows);
        for _ in 0..rows {
            tiles.push(Vec::<Tile>::with_capacity(rows));
        }
        // First row is all wall
        tiles[0].push(top_left);
        for _ in 1..cols-1 {
            tiles[0].push(horizontal);
        }
        tiles[0].push(top_right);
        // Middle rows are vertical sides and blank middles
        for row in 1..rows-1 {
            tiles[row].push(vertical);
            for _ in 1..cols-1 {
                tiles[row].push(blank);
            }
            tiles[row].push(vertical);
        }
        // Bottom row is also all wall
        tiles[rows-1].push(bottom_left);
        for _ in 1..cols-1 {
            tiles[rows-1].push(horizontal);
        }
        tiles[rows-1].push(bottom_right);

        // Create the floor
        Self {
            rows: rows,
            cols: cols,
            tiles: tiles,
        }
    }
    pub fn get_symbol(&self, coord : &Coord) -> String {
        if let Some(wall) = self.tiles[coord.row as usize][coord.col as usize].wall {
            wall.to_string()
        } else {
            " ".to_string()
        }
    }
    pub fn is_wall(&self, coord : &Coord) -> bool {
        self.tiles[coord.row as usize][coord.col as usize].wall.is_some()
    }
}
<|endoftext|>