flickr 0.1.1

Rust binding to Flickr API
Documentation

//! Structs in this module are constructed by FlickrAPI functions.

pub mod activity;
pub mod auth;
pub mod favorites;
pub mod photos;

#[cfg(test)]
mod proc_tests;

use flickr_derive::{Builder};

use std::fmt;
use std::str;
use std::string;

use serde::de::{self, Deserialize, Deserializer, Unexpected};
use chrono::prelude::{DateTime, Utc, Local, TimeZone};

// ---- Content -----------------------------------------------------------------------------------
#[derive(Deserialize, Debug, Default)]
struct Content {
  #[serde(default, rename = "_content")]
  pub content: String,
}

impl fmt::Display for Content {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.content)?;
        Ok(())
    }
}

impl str::FromStr for Content {
    type Err = string::ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Content{ content: s.to_string() })
    }
}

// ---- deserialize functions ---------------------------------------------------------------------

/// Deserialize i32 from sub-block with `_content` field.
fn i32_from_content_block<'de, D>(deserializer: D) -> Result<i32, D::Error>
where
    D: Deserializer<'de>,
{
    match Content::deserialize(deserializer)?.content.parse() {
        Ok(i) => {
            return Ok(i);
        },
        Err(_e) => {
            return Err(de::Error::invalid_value(Unexpected::Str(&""), &"i32 as string",));
        }
    }
}

/// Deserialize string from sub-block with `_content` field.
fn string_from_content_block<'de, D>(deserializer: D) -> Result<String, D::Error>
where
    D: Deserializer<'de>,
{
    return Ok(Content::deserialize(deserializer)?.content);
}

/// Deserialize bool from int
fn bool_from_int<'de, D>(deserializer: D) -> Result<bool, D::Error>
where
    D: Deserializer<'de>,
{
    match u8::deserialize(deserializer)? {
        0 => Ok(false),
        1 => Ok(true),
        other => Err(de::Error::invalid_value(
            Unexpected::Unsigned(other as u64),
            &"zero or one",
        )),
    }
}

/// Deserialize i32 from string
fn i32_from_string<'de, D>(deserializer: D) -> Result<i32, D::Error>
where
    D: Deserializer<'de>,
{
    match String::deserialize(deserializer)?.parse() {
        Ok(i) => {
            return Ok(i);
        },
        Err(_e) => {
            return Err(de::Error::invalid_value(Unexpected::Str(&""), &"i32 as string",));
        }
    }
}

/// Deserialize date from epoch number string
fn date_from_string<'de, D>(deserializer: D) -> Result<DateTime<Local>, D::Error>
where
    D: Deserializer<'de>,
{
    match String::deserialize(deserializer)?.parse::<i64>() {
        Ok(a) => {
            let utc = Utc.timestamp(a, 0);
            let local_tz = Local::now().timezone();
            return Ok(utc.with_timezone(&local_tz));
        },
        Err(_e) => {
            return Err(de::Error::invalid_value(Unexpected::Str(&""), &"i64 as string",));
        }
    }
}

/// Deserialize date from MYSQL date formatted string
fn date_from_mysql_string<'de, D>(deserializer: D) -> Result<DateTime<Local>, D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;    
    match Utc.datetime_from_str(&s, "%Y-%m-%d %H:%M:%S") {
        Ok(utc) => {
            let local_tz = Local::now().timezone();
            return Ok(utc.with_timezone(&local_tz));
        },
        Err(_e) => {
            return Err(de::Error::invalid_value(Unexpected::Str(&s), &"mysql date string",));
        }
    }
}

/// Deserialize i32 from string or i32
fn i32_from_value<'de, D>(deserializer: D) -> Result<i32, D::Error>
where
    D: Deserializer<'de>,
{
    let value = serde_json::Value::deserialize(deserializer)?;
    let s = value.to_string(); 
    match s.replace("\"", "").parse::<i32>() {
        Ok(v) => {
            Ok(v)
        },
        Err(_e) => {
            return Err(de::Error::invalid_value(Unexpected::Str(&s), &"value",));
        }
    }
}

// ---- SimpleResult ------------------------------------------------------------------------------

/// Result from various methods returning only operation status information.
#[derive(Deserialize, Debug)]
pub struct SimpleResult {
    #[serde(default)]
    pub stat: String,

    #[serde(default)]
    pub code: i32,

    #[serde(default)]
    pub message: String,
}

// ---- Photos ------------------------------------------------------------------------------------

#[derive(Deserialize, Debug)]
pub struct Photos {
    #[serde(deserialize_with = "i32_from_value", default)]
    pub total: i32,

    #[serde(deserialize_with = "i32_from_value", default)]
    pub page: i32,

    #[serde(deserialize_with = "i32_from_value", default)]
    pub pages: i32,

    #[serde(deserialize_with = "i32_from_value", default)]
    pub perpage: i32,

    #[serde(default)]
    pub photo: Vec<Photo>,
}

#[derive(Deserialize, Debug)]
pub struct Photos2 {
    #[serde(deserialize_with = "i32_from_value", default)]
    pub total: i32,

    #[serde(deserialize_with = "i32_from_value", default)]
    pub page: i32,

    #[serde(deserialize_with = "i32_from_value", default)]
    pub pages: i32,

    #[serde(deserialize_with = "i32_from_value", default)]
    pub per_page: i32,

    #[serde(default)]
    pub photo: Vec<Photo>,
}

#[derive(Deserialize, Debug)]
pub struct Photo {
    pub id: String,
    #[serde(default)]
    pub owner: String,
    #[serde(default)]
    pub username: String,
    #[serde(default)]
    pub title: String,

    #[serde(deserialize_with = "bool_from_int", default)]
    pub ispublic: bool,
    #[serde(deserialize_with = "bool_from_int", default)]
    pub isfriend: bool,
    #[serde(deserialize_with = "bool_from_int", default)]
    pub isfamily: bool,

    #[serde(default)]
    pub secret: String,
    #[serde(default)]
    pub server: String,
    #[serde(deserialize_with = "i32_from_value", default)]
    pub farm: i32,
}