use url::Url;
use crate::{
date::Date, namespace::FileNamespaceUrl, AgendaItemId, DateTime, FileId, Keyword, MeetingId,
Name, PaperId, Sha1Sum, Sha512Sum,
};
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct File {
pub id: FileId,
#[serde(rename = "type")]
pub namespace: FileNamespaceUrl,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mime_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub date: Option<Date>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub size: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sha1_checksum: Option<Sha1Sum>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sha512_checksum: Option<Sha512Sum>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
pub access_url: Url,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub download_url: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub external_service_url: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub master_file: Option<FileId>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub derivative_file: Vec<FileId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_license: Option<Url>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub meeting: Vec<MeetingId>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub agenda_item: Vec<AgendaItemId>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub paper: Vec<PaperId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license: Option<Url>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub keyword: Vec<Keyword>,
pub created: DateTime,
pub modified: DateTime,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub web: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub deleted: Option<bool>,
}
#[cfg(test)]
mod serde_tests {
use super::File;
use crate::{namespace::FileNamespaceUrl, Sha1Sum};
use pretty_assertions::assert_eq;
use serde_json::json;
use time::macros::{date, datetime};
fn example_file() -> File {
File {
id: "https://oparl.example.org/files/57737"
.parse()
.expect("value must be parseable as id"),
namespace: FileNamespaceUrl::Identifier,
file_name: Some("anlage_1_zur_anfrage.pdf".into()),
name: Some("Anlage 1 zur Anfrage".into()),
mime_type: Some("application/pdf".into()),
date: Some(date!(2013 - 01 - 04).into()),
size: Some(82930),
sha1_checksum: Some(Sha1Sum::from([
0xd7, 0x49, 0x75, 0x1a, 0xf4, 0x4a, 0x32, 0xc8, 0x18, 0xb9, 0xb1, 0xe1, 0x51, 0x52,
0x51, 0xc6, 0x77, 0x34, 0xf5, 0xd2,
])),
sha512_checksum: None,
text: None,
access_url: "https://oparl.example.org/files/57737.pdf"
.parse()
.expect("value must be parseable as url"),
download_url: Some(
"https://oparl.example.org/files/download/57737.pdf"
.parse()
.expect("value must be parseable as url"),
),
external_service_url: None,
master_file: None,
derivative_file: vec!["https://oparl.example.org/files/57739"
.parse()
.expect("value must be parseable as url")],
file_license: Some(
"http://www.opendefinition.org/licenses/cc-by"
.parse()
.expect("value must be parseable as url"),
),
meeting: vec![],
agenda_item: vec![],
paper: vec![],
license: None,
keyword: vec![],
created: datetime!(2013-01-04 07:54:13 +01:00).into(),
modified: datetime!(2013-01-04 07:54:13 +01:00).into(),
web: None,
deleted: None,
}
}
fn example_file_json() -> serde_json::Value {
json!({
"id": "https://oparl.example.org/files/57737",
"type": "https://schema.oparl.org/1.1/File",
"name": "Anlage 1 zur Anfrage",
"fileName": "anlage_1_zur_anfrage.pdf",
"mimeType": "application/pdf",
"date": "2013-01-04",
"size": 82930,
"sha1Checksum": "d749751af44a32c818b9b1e1515251c67734f5d2",
"accessUrl": "https://oparl.example.org/files/57737.pdf",
"downloadUrl": "https://oparl.example.org/files/download/57737.pdf",
"derivativeFile": [
"https://oparl.example.org/files/57739"
],
"fileLicense": "http://www.opendefinition.org/licenses/cc-by",
"created": "2013-01-04T07:54:13+01:00",
"modified": "2013-01-04T07:54:13+01:00"
})
}
#[test]
fn serialize() {
assert_eq!(json!(example_file()), example_file_json());
}
#[test]
fn deserialize_good() {
let deserialized: File = serde_json::from_value(example_file_json())
.expect("value must be deserializable as File");
assert_eq!(deserialized, example_file());
}
#[test]
fn deserialize_bad() {
assert!(serde_json::from_value::<File>(json!("xyzabcd")).is_err());
assert!(serde_json::from_value::<File>(json!(true)).is_err());
assert!(serde_json::from_value::<File>(json!(123)).is_err());
}
}