1use std::fmt;
4use std::sync::atomic::{AtomicU64, Ordering};
5
6const PREFIX: &str = "download-";
8
9static NEXT: AtomicU64 = AtomicU64::new(1);
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
15pub struct DownloadId(u64);
16
17impl DownloadId {
18 #[must_use]
20 pub fn next() -> Self {
21 Self(NEXT.fetch_add(1, Ordering::Relaxed))
22 }
23
24 #[must_use]
26 pub fn parse(text: &str) -> Option<Self> {
27 text.strip_prefix(PREFIX)?.parse().ok().map(Self)
28 }
29}
30
31impl fmt::Display for DownloadId {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "{PREFIX}{}", self.0)
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn reads_back_the_ids_it_shows() {
43 let id = DownloadId::next();
44 assert_ne!(DownloadId::next(), id);
45 assert_eq!(DownloadId::parse(&id.to_string()), Some(id));
46 assert_eq!(DownloadId::parse("download-x"), None);
47 assert_eq!(DownloadId::parse("7"), None);
48 assert_eq!(DownloadId::parse(""), None);
49 }
50}