2020-07-16 19:32:30 +00:00
use std ::default ::Default ;
use builder ::Builder ;
2021-01-15 03:36:34 +00:00
use item ::Item ;
2020-07-16 19:32:30 +00:00
const VERSION_1 : & 'static str = " https://jsonfeed.org/version/1 " ;
/// Represents a single feed
///
/// # Examples
///
/// ```rust
/// // Serialize a feed object to a JSON string
///
/// # extern crate jsonfeed;
/// # use std::default::Default;
/// # use jsonfeed::Feed;
/// # fn main() {
/// let feed: Feed = Feed::default();
/// assert_eq!(
/// jsonfeed::to_string(&feed).unwrap(),
/// "{\"version\":\"https://jsonfeed.org/version/1\",\"title\":\"\",\"items\":[]}"
/// );
/// # }
/// ```
///
/// ```rust
/// // Deserialize a feed objects from a JSON String
///
/// # extern crate jsonfeed;
/// # use jsonfeed::Feed;
/// # fn main() {
/// let json = "{\"version\":\"https://jsonfeed.org/version/1\",\"title\":\"\",\"items\":[]}";
/// let feed: Feed = jsonfeed::from_str(&json).unwrap();
/// assert_eq!(
/// feed,
/// Feed::default()
/// );
/// # }
/// ```
#[ derive(Debug, Clone, PartialEq, Deserialize, Serialize) ]
pub struct Feed {
pub version : String ,
pub title : String ,
pub items : Vec < Item > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub home_page_url : Option < String > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub feed_url : Option < String > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub description : Option < String > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub user_comment : Option < String > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub next_url : Option < String > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub icon : Option < String > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub favicon : Option < String > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub author : Option < Author > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub expired : Option < bool > ,
#[ serde(skip_serializing_if = " Option::is_none " ) ]
pub hubs : Option < Vec < Hub > > ,
}
impl Feed {
/// Used to construct a Feed object
pub fn builder ( ) -> Builder {
Builder ::new ( )
}
}
impl Default for Feed {
fn default ( ) -> Feed {
Feed {
version : VERSION_1 . to_string ( ) ,
title : " " . to_string ( ) ,
items : vec ! [ ] ,
home_page_url : None ,
feed_url : None ,
description : None ,
user_comment : None ,
next_url : None ,
icon : None ,
favicon : None ,
author : None ,
expired : None ,
hubs : None ,
}
}
}
/// Represents an `attachment` for an item
#[ derive(Debug, Clone, PartialEq, Deserialize, Serialize) ]
pub struct Attachment {
url : String ,
mime_type : String ,
title : Option < String > ,
size_in_bytes : Option < u64 > ,
duration_in_seconds : Option < u64 > ,
}
/// Represents an `author` in both a feed and a feed item
#[ derive(Debug, Clone, PartialEq, Deserialize, Serialize) ]
pub struct Author {
name : Option < String > ,
url : Option < String > ,
avatar : Option < String > ,
}
impl Author {
pub fn new ( ) -> Author {
Author {
name : None ,
url : None ,
avatar : None ,
}
}
pub fn name < I : Into < String > > ( mut self , name : I ) -> Self {
self . name = Some ( name . into ( ) ) ;
self
}
pub fn url < I : Into < String > > ( mut self , url : I ) -> Self {
self . url = Some ( url . into ( ) ) ;
self
}
pub fn avatar < I : Into < String > > ( mut self , avatar : I ) -> Self {
self . avatar = Some ( avatar . into ( ) ) ;
self
}
}
/// Represents a `hub` for a feed
#[ derive(Debug, Clone, PartialEq, Deserialize, Serialize) ]
pub struct Hub {
#[ serde(rename = " type " ) ]
type_ : String ,
url : String ,
}
#[ cfg(test) ]
mod tests {
2021-01-15 03:36:34 +00:00
use super ::* ;
2020-07-16 19:32:30 +00:00
use serde_json ;
use std ::default ::Default ;
#[ test ]
fn serialize_feed ( ) {
let feed = Feed {
version : " https://jsonfeed.org/version/1 " . to_string ( ) ,
title : " some title " . to_string ( ) ,
items : vec ! [ ] ,
home_page_url : None ,
description : None ,
expired : Some ( true ) ,
.. Default ::default ( )
} ;
assert_eq! (
serde_json ::to_string ( & feed ) . unwrap ( ) ,
r # "{"version":"https://jsonfeed.org/version/1","title":"some title","items":[],"expired":true}"#
) ;
}
#[ test ]
fn deserialize_feed ( ) {
2021-01-15 03:36:34 +00:00
let json =
r # "{"version":"https://jsonfeed.org/version/1","title":"some title","items":[]}"# ;
2020-07-16 19:32:30 +00:00
let feed : Feed = serde_json ::from_str ( & json ) . unwrap ( ) ;
let expected = Feed {
version : " https://jsonfeed.org/version/1 " . to_string ( ) ,
2021-01-15 03:36:34 +00:00
title : " some title " . to_string ( ) ,
items : vec ! [ ] ,
.. Default ::default ( )
2020-07-16 19:32:30 +00:00
} ;
2021-01-15 03:36:34 +00:00
assert_eq! ( feed , expected ) ;
2020-07-16 19:32:30 +00:00
}
#[ test ]
fn serialize_attachment ( ) {
let attachment = Attachment {
url : " http://example.com " . to_string ( ) ,
mime_type : " application/json " . to_string ( ) ,
title : Some ( " some title " . to_string ( ) ) ,
size_in_bytes : Some ( 1 ) ,
duration_in_seconds : Some ( 1 ) ,
} ;
assert_eq! (
serde_json ::to_string ( & attachment ) . unwrap ( ) ,
r # "{"url":"http://example.com","mime_type":"application/json","title":"some title","size_in_bytes":1,"duration_in_seconds":1}"#
) ;
}
#[ test ]
fn deserialize_attachment ( ) {
let json = r # "{"url":"http://example.com","mime_type":"application/json","title":"some title","size_in_bytes":1,"duration_in_seconds":1}"# ;
let attachment : Attachment = serde_json ::from_str ( & json ) . unwrap ( ) ;
let expected = Attachment {
url : " http://example.com " . to_string ( ) ,
mime_type : " application/json " . to_string ( ) ,
title : Some ( " some title " . to_string ( ) ) ,
size_in_bytes : Some ( 1 ) ,
duration_in_seconds : Some ( 1 ) ,
} ;
2021-01-15 03:36:34 +00:00
assert_eq! ( attachment , expected ) ;
2020-07-16 19:32:30 +00:00
}
#[ test ]
fn serialize_author ( ) {
let author = Author {
name : Some ( " bob jones " . to_string ( ) ) ,
url : Some ( " http://example.com " . to_string ( ) ) ,
avatar : Some ( " http://img.com/blah " . to_string ( ) ) ,
} ;
assert_eq! (
serde_json ::to_string ( & author ) . unwrap ( ) ,
r # "{"name":"bob jones","url":"http://example.com","avatar":"http://img.com/blah"}"#
) ;
}
#[ test ]
fn deserialize_author ( ) {
2021-01-15 03:36:34 +00:00
let json =
r # "{"name":"bob jones","url":"http://example.com","avatar":"http://img.com/blah"}"# ;
2020-07-16 19:32:30 +00:00
let author : Author = serde_json ::from_str ( & json ) . unwrap ( ) ;
let expected = Author {
name : Some ( " bob jones " . to_string ( ) ) ,
url : Some ( " http://example.com " . to_string ( ) ) ,
avatar : Some ( " http://img.com/blah " . to_string ( ) ) ,
} ;
2021-01-15 03:36:34 +00:00
assert_eq! ( author , expected ) ;
2020-07-16 19:32:30 +00:00
}
#[ test ]
fn serialize_hub ( ) {
let hub = Hub {
type_ : " some-type " . to_string ( ) ,
url : " http://example.com " . to_string ( ) ,
} ;
assert_eq! (
serde_json ::to_string ( & hub ) . unwrap ( ) ,
r # "{"type":"some-type","url":"http://example.com"}"#
)
}
#[ test ]
fn deserialize_hub ( ) {
let json = r # "{"type":"some-type","url":"http://example.com"}"# ;
let hub : Hub = serde_json ::from_str ( & json ) . unwrap ( ) ;
let expected = Hub {
type_ : " some-type " . to_string ( ) ,
url : " http://example.com " . to_string ( ) ,
} ;
2021-01-15 03:36:34 +00:00
assert_eq! ( hub , expected ) ;
2020-07-16 19:32:30 +00:00
}
#[ test ]
fn deser_podcast ( ) {
let json = r #" {
" version " : " https://jsonfeed.org/version/1 " ,
" title " : " Timetable " ,
" home_page_url " : " http://timetable.manton.org/ " ,
" items " : [
{
" id " : " http://timetable.manton.org/2017/04/episode-45-launch-week/ " ,
" url " : " http://timetable.manton.org/2017/04/episode-45-launch-week/ " ,
" title " : " Episode 45: Launch week " ,
" content_html " : " I’ m rolling out early access to Micro.blog this week. I talk about how the first 2 days have gone, mistakes with TestFlight, and what to do next. " ,
" date_published " : " 2017-04-26T01:09:45+00:00 " ,
" attachments " : [
{
" url " : " http://timetable.manton.org/podcast-download/139/episode-45-launch-week.mp3 " ,
" mime_type " : " audio/mpeg " ,
" size_in_bytes " : 5236920
}
]
}
]
} " #;
serde_json ::from_str ::< Feed > ( & json ) . expect ( " Failed to deserialize podcast feed " ) ;
}
}