Skip to content

Commit a086bc5

Browse files
committed
feat: add update information parser
Supports: - zsync|<url> - generic zsync URL - gh-releases-zsync|<user>|<repo>|<tag>|<filename> - GitHub releases
1 parent 08bc111 commit a086bc5

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

src/update_info/generic.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#[derive(Debug, Clone)]
2+
pub struct GenericUpdateInfo {
3+
pub url: String,
4+
}
5+
6+
impl GenericUpdateInfo {
7+
pub fn zsync_url(&self) -> &str {
8+
&self.url
9+
}
10+
}

src/update_info/github.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::cell::OnceCell;
2+
3+
use crate::error::Result;
4+
5+
#[derive(Debug, Clone)]
6+
pub struct GitHubUpdateInfo {
7+
pub username: String,
8+
pub repo: String,
9+
pub tag: String,
10+
pub filename: String,
11+
resolved_url: OnceCell<String>,
12+
}
13+
14+
impl GitHubUpdateInfo {
15+
pub fn new(username: String, repo: String, tag: String, filename: String) -> Self {
16+
Self {
17+
username,
18+
repo,
19+
tag,
20+
filename,
21+
resolved_url: OnceCell::new(),
22+
}
23+
}
24+
25+
pub fn zsync_url(&self) -> Result<&str> {
26+
if self.resolved_url.get().is_none() {
27+
let url = self.resolve_url()?;
28+
let _ = self.resolved_url.set(url);
29+
}
30+
Ok(self.resolved_url.get().unwrap())
31+
}
32+
33+
fn resolve_url(&self) -> Result<String> {
34+
todo!("Implement GitHub API call to resolve zsync URL")
35+
}
36+
}

src/update_info/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
mod generic;
2+
mod github;
3+
mod parser;
4+
5+
pub use generic::GenericUpdateInfo;
6+
pub use github::GitHubUpdateInfo;
7+
8+
use crate::error::Result;
9+
10+
#[derive(Debug, Clone)]
11+
pub enum UpdateInfo {
12+
Generic(GenericUpdateInfo),
13+
GitHub(GitHubUpdateInfo),
14+
}
15+
16+
impl UpdateInfo {
17+
pub fn parse(s: &str) -> Result<Self> {
18+
parser::parse(s)
19+
}
20+
}

src/update_info/parser.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use crate::error::{Error, Result};
2+
3+
use super::{GenericUpdateInfo, GitHubUpdateInfo, UpdateInfo};
4+
5+
pub fn parse(s: &str) -> Result<UpdateInfo> {
6+
let parts: Vec<&str> = s.split('|').collect();
7+
8+
if parts.is_empty() {
9+
return Err(Error::InvalidUpdateInfo("Empty update information".into()));
10+
}
11+
12+
match parts[0] {
13+
"zsync" => {
14+
if parts.len() != 2 {
15+
return Err(Error::InvalidUpdateInfo(
16+
"zsync format requires exactly 1 parameter: zsync|<url>".into(),
17+
));
18+
}
19+
Ok(UpdateInfo::Generic(GenericUpdateInfo {
20+
url: parts[1].into(),
21+
}))
22+
}
23+
"gh-releases-zsync" => {
24+
if parts.len() != 5 {
25+
return Err(Error::InvalidUpdateInfo(
26+
"gh-releases-zsync format requires 4 parameters: gh-releases-zsync|<username>|<repo>|<tag>|<filename>".into(),
27+
));
28+
}
29+
Ok(UpdateInfo::GitHub(GitHubUpdateInfo::new(
30+
parts[1].into(),
31+
parts[2].into(),
32+
parts[3].into(),
33+
parts[4].into(),
34+
)))
35+
}
36+
_ => Err(Error::InvalidUpdateInfo(format!(
37+
"Unknown update information type: {}",
38+
parts[0]
39+
))),
40+
}
41+
}
42+
43+
#[cfg(test)]
44+
mod tests {
45+
use super::*;
46+
47+
#[test]
48+
fn parse_generic_zsync() {
49+
let info = parse("zsync|https://example.com/app.AppImage.zsync").unwrap();
50+
match info {
51+
UpdateInfo::Generic(g) => {
52+
assert_eq!(g.url, "https://example.com/app.AppImage.zsync");
53+
}
54+
_ => panic!("Expected Generic variant"),
55+
}
56+
}
57+
58+
#[test]
59+
fn parse_github_releases() {
60+
let info = parse("gh-releases-zsync|user|repo|latest|app-*.AppImage").unwrap();
61+
match info {
62+
UpdateInfo::GitHub(g) => {
63+
assert_eq!(g.username, "user");
64+
assert_eq!(g.repo, "repo");
65+
assert_eq!(g.tag, "latest");
66+
assert_eq!(g.filename, "app-*.AppImage");
67+
}
68+
_ => panic!("Expected GitHub variant"),
69+
}
70+
}
71+
72+
#[test]
73+
fn parse_invalid_type() {
74+
assert!(parse("invalid|params").is_err());
75+
}
76+
77+
#[test]
78+
fn parse_missing_params() {
79+
assert!(parse("zsync").is_err());
80+
assert!(parse("gh-releases-zsync|user|repo").is_err());
81+
}
82+
}

0 commit comments

Comments
 (0)