isr_dl_linux/ubuntu/
parse.rs1#[derive(Debug, Default, Clone, PartialEq, Eq)]
5pub struct UbuntuRepositoryEntry {
6 pub package: Option<String>,
8
9 pub version: Option<String>,
11
12 pub filename: Option<String>,
14
15 pub size: Option<usize>,
17
18 pub installed_size: Option<usize>,
20
21 pub depends: Option<String>,
23
24 pub section: Option<String>,
26
27 pub source: Option<String>,
29
30 pub md5sum: Option<String>,
32
33 pub sha1: Option<String>,
35
36 pub sha256: Option<String>,
38
39 pub sha512: Option<String>,
41}
42
43pub fn parse_packages(text: &str) -> Vec<UbuntuRepositoryEntry> {
45 let mut result = Vec::new();
46 let mut entry = UbuntuRepositoryEntry::default();
47
48 for line in text.lines() {
49 if line.is_empty() {
50 result.push(entry);
51 entry = UbuntuRepositoryEntry::default();
52 continue;
53 }
54
55 if line.starts_with(' ') {
56 continue;
57 }
58
59 let (key, value) = match line.split_once(": ") {
60 Some(kv) => kv,
61 None => continue,
62 };
63
64 match key {
65 "Package" => entry.package = Some(value.into()),
66 "Version" => entry.version = Some(value.into()),
67 "Filename" => entry.filename = Some(value.into()),
68 "Size" => entry.size = value.parse().ok(),
69 "Installed-Size" => entry.installed_size = value.parse().ok(),
70 "Depends" => entry.depends = Some(value.into()),
71 "Section" => entry.section = Some(value.into()),
72 "Source" => entry.source = Some(value.into()),
73 "MD5sum" => entry.md5sum = Some(value.into()),
74 "SHA1" => entry.sha1 = Some(value.into()),
75 "SHA256" => entry.sha256 = Some(value.into()),
76 "SHA512" => entry.sha512 = Some(value.into()),
77 _ => (),
78 }
79 }
80
81 if entry.package.is_some() || entry.filename.is_some() {
82 result.push(entry);
83 }
84
85 result
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn parses_two_entries_with_blank_separator() {
94 let input = "\
95Package: linux-image-6.8.0-40-generic
96Version: 6.8.0-40.40
97Filename: pool/main/l/linux/linux-image-6.8.0-40-generic_6.8.0-40.40_amd64.deb
98Size: 12345
99
100Package: linux-modules-6.8.0-40-generic
101Version: 6.8.0-40.40
102Filename: pool/main/l/linux/linux-modules-6.8.0-40-generic_6.8.0-40.40_amd64.deb
103Size: 67890
104";
105 let entries = parse_packages(input);
106 assert_eq!(entries.len(), 2);
107 assert_eq!(
108 entries[0].package.as_deref(),
109 Some("linux-image-6.8.0-40-generic")
110 );
111 assert_eq!(entries[0].size, Some(12345));
112 assert_eq!(
113 entries[1].package.as_deref(),
114 Some("linux-modules-6.8.0-40-generic")
115 );
116 }
117
118 #[test]
119 fn ignores_continuation_lines() {
120 let input = "\
121Package: foo
122Description: a package
123 with a wrapped description
124 across multiple lines
125Version: 1.0
126";
127 let entries = parse_packages(input);
128 assert_eq!(entries.len(), 1);
129 assert_eq!(entries[0].version.as_deref(), Some("1.0"));
130 }
131
132 #[test]
133 fn skips_lines_without_separator() {
134 let input = "Package: foo\nNotAField\nVersion: 1.0\n";
135 let entries = parse_packages(input);
136 assert_eq!(entries.len(), 1);
137 assert_eq!(entries[0].version.as_deref(), Some("1.0"));
138 }
139
140 #[test]
141 fn empty_input_produces_no_entries() {
142 assert_eq!(parse_packages("").len(), 0);
143 }
144}