1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use serde::{Deserialize, Serialize};

use crate::{
    deserializers::{
        default_false, default_sap_content_version, default_true, edm_string::to_bool,
    },
    xml::{
        default_xml_language, default_xml_namespace_app, default_xml_namespace_atom,
        default_xml_namespace_m, default_xml_namespace_sap,
    },
};

pub mod feed;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// Represents an `<atom:link>` tag
#[derive(Debug, Serialize, Deserialize)]
pub struct AtomLink {
    // Appears in the XML as the `link` attribute `xmlns:atom`
    #[serde(rename = "@atom", default = "default_xml_namespace_atom")]
    pub xml_namespace_atom: Option<String>,

    #[serde(rename = "@type")]
    pub mime_type: Option<String>,

    #[serde(rename = "@rel")]
    pub rel: String,

    #[serde(rename = "@href")]
    pub href: String,

    #[serde(rename = "@title")]
    pub title: Option<String>,
}

impl std::str::FromStr for AtomLink {
    type Err = quick_xml::DeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        quick_xml::de::from_str(s)
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// Represents an `<atom:collection>` tag
#[derive(Debug, Serialize, Deserialize)]
pub struct AtomCollection {
    #[serde(
        rename = "@creatable",
        deserialize_with = "to_bool",
        default = "default_true"
    )]
    pub is_creatable: bool,

    #[serde(
        rename = "@updatable",
        deserialize_with = "to_bool",
        default = "default_true"
    )]
    pub is_updatable: bool,

    #[serde(
        rename = "@deletable",
        deserialize_with = "to_bool",
        default = "default_true"
    )]
    pub is_deletable: bool,

    #[serde(
        rename = "@pageable",
        deserialize_with = "to_bool",
        default = "default_true"
    )]
    pub is_pageable: bool,

    #[serde(
        rename = "@searchable",
        deserialize_with = "to_bool",
        default = "default_false"
    )]
    pub is_searchable: bool,

    #[serde(rename = "@content-version", default = "default_sap_content_version")]
    pub content_version: String,
    #[serde(rename = "@href")]
    pub href: String,
    pub title: String,
    #[serde(rename = "member-title")]
    pub member_title: String,
    pub link: Option<AtomLink>,
}

impl std::str::FromStr for AtomCollection {
    type Err = quick_xml::DeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        quick_xml::de::from_str(s)
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// Represents an `<atom:workspace>` tag
#[derive(Debug, Serialize, Deserialize)]
pub struct AtomWorkspace {
    pub title: String,

    #[serde(rename = "collection")]
    pub collections: Vec<AtomCollection>,
}

impl std::str::FromStr for AtomWorkspace {
    type Err = quick_xml::DeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        quick_xml::de::from_str(s)
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/// Represents an Atom service document `<app:service>`
///
/// ***WARNING:***<br>`quick-xml` strips namespace identifiers from XML tag names, and from certain attribute names!
///
/// Tag names such as `<app:service>` and `<atom:title>` will appear simply as `<service>` and `<title>`.
///
/// Attribute names prefixed with `xml` such as `xml:lang` or `xml:base` will be modified to `lang` and `base`, but
/// `xmlns:app` or `xmlns:atom` will appear without modification
#[derive(Debug, Serialize, Deserialize)]
pub struct AtomService {
    #[serde(rename = "@xmlns:app", default = "default_xml_namespace_app")]
    pub namespace_app: String,
    #[serde(rename = "@xmlns:atom", default = "default_xml_namespace_atom")]
    pub namespace_atom: Option<String>,
    #[serde(rename = "@xmlns:m", default = "default_xml_namespace_m")]
    pub namespace_m: String,
    #[serde(rename = "@xmlns:sap", default = "default_xml_namespace_sap")]
    pub namespace_sap: String,
    #[serde(rename = "@lang", default = "default_xml_language")]
    pub language: String,
    #[serde(rename = "@base")]
    pub base_url: String,
    pub workspace: AtomWorkspace,
    #[serde(rename = "link")]
    pub links: Vec<AtomLink>,
}

impl std::str::FromStr for AtomService {
    type Err = quick_xml::DeError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        quick_xml::de::from_str(s)
    }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#[cfg(test)]
pub mod unit_tests;