-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathrepomd.rs
118 lines (102 loc) · 3.47 KB
/
repomd.rs
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
// 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 https://mozilla.org/MPL/2.0/.
/*! `repomd.xml` file format. */
use {
crate::{
error::{Result, RpmRepositoryError},
io::ContentDigest,
},
serde::{Deserialize, Serialize},
std::io::Read,
};
/// A `repomd.xml` file.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepoMd {
/// Revision of the repository.
///
/// Often an integer-like value.
pub revision: String,
/// Describes additional primary data files constituting this repository.
pub data: Vec<RepoMdData>,
}
impl RepoMd {
/// Construct an instance by parsing XML from a reader.
pub fn from_reader(reader: impl Read) -> Result<Self> {
Ok(serde_xml_rs::from_reader(reader)?)
}
/// Construct an instance by parsing XML from a string.
pub fn from_xml(s: &str) -> Result<Self> {
Ok(serde_xml_rs::from_str(s)?)
}
}
/// A `<data>` element in a `repomd.xml` file.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RepoMdData {
/// The type of data.
#[serde(rename = "type")]
pub data_type: String,
/// Content checksum of this file.
pub checksum: Checksum,
/// Where the file is located.
pub location: Location,
/// Size in bytes of the file as stored in the repository.
pub size: Option<u64>,
/// Time file was created/modified.
pub timestamp: Option<f64>,
/// Content checksum of the decoded (often decompressed) file.
#[serde(rename = "open-checksum")]
pub open_checksum: Option<Checksum>,
/// Size in bytes of the decoded (often decompressed) file.
#[serde(rename = "open-size")]
pub open_size: Option<u64>,
/// Content checksum of header data.
#[serde(rename = "header-checksum")]
pub header_checksum: Option<Checksum>,
/// Size in bytes of the header.
#[serde(rename = "header-size")]
pub header_size: Option<u64>,
}
/// The content checksum of a `<data>` element.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Checksum {
/// The name of the content digest.
#[serde(rename = "type")]
pub name: String,
/// The hex encoded content digest.
#[serde(rename = "$value")]
pub value: String,
}
impl TryFrom<Checksum> for ContentDigest {
type Error = RpmRepositoryError;
fn try_from(v: Checksum) -> std::result::Result<Self, Self::Error> {
match v.name.as_str() {
"sha1" => ContentDigest::sha1_hex(&v.value),
"sha256" => ContentDigest::sha256_hex(&v.value),
name => Err(RpmRepositoryError::UnknownDigestFormat(name.to_string())),
}
}
}
/// The location of a `<data>` element.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Location {
pub href: String,
}
#[cfg(test)]
mod test {
use super::*;
const FEDORA_35_REPOMD_XML: &str = include_str!("../testdata/fedora-35-repodata.xml");
const WITH_FLOAT_TIMESTAMP: &str = include_str!("../testdata/with-float-timestamp.xml");
#[test]
fn fedora_35_parse() -> Result<()> {
let result = RepoMd::from_xml(FEDORA_35_REPOMD_XML)?;
assert_eq!(result.data[0].timestamp, Some(1635225121.));
Ok(())
}
#[test]
fn with_float_timestamp_parse() -> Result<()> {
let result = RepoMd::from_xml(WITH_FLOAT_TIMESTAMP)?;
assert_eq!(result.data[0].timestamp, Some(1635225121.75));
Ok(())
}
}