harmont_cli/orchestrator/
archive.rs1use std::collections::HashMap;
11use std::sync::Mutex;
12
13use hm_plugin_protocol::ArchiveId;
14use uuid::Uuid;
15
16#[derive(Debug, Default)]
17pub struct ArchiveStore {
18 archives: Mutex<HashMap<ArchiveId, Vec<u8>>>,
19}
20
21impl ArchiveStore {
22 #[must_use]
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn register(&self, bytes: Vec<u8>) -> ArchiveId {
29 let id = ArchiveId::from(Uuid::new_v4());
30 let _ = self.archives.lock().map(|mut m| m.insert(id, bytes));
31 id
32 }
33
34 #[must_use]
37 pub fn total_size(&self, id: ArchiveId) -> u64 {
38 self.archives
39 .lock()
40 .ok()
41 .and_then(|m| m.get(&id).map(|b| b.len() as u64))
42 .unwrap_or(0)
43 }
44
45 #[must_use]
47 pub fn get_bytes(&self, id: ArchiveId) -> Option<Vec<u8>> {
48 self.archives.lock().ok()?.get(&id).cloned()
49 }
50
51 #[must_use]
54 pub fn read(&self, id: ArchiveId, offset: u64, max: u64) -> Vec<u8> {
55 let Ok(g) = self.archives.lock() else {
59 return Vec::new();
60 };
61 let Some(bytes) = g.get(&id) else {
62 return Vec::new();
63 };
64 #[allow(
68 clippy::cast_possible_truncation,
69 reason = "archive sizes fit in usize on supported 64-bit hosts"
70 )]
71 let start = (offset as usize).min(bytes.len());
72 #[allow(
73 clippy::cast_possible_truncation,
74 reason = "archive sizes fit in usize on supported 64-bit hosts"
75 )]
76 let max_us = max as usize;
77 let end = start.saturating_add(max_us).min(bytes.len());
78 bytes[start..end].to_vec()
79 }
80}
81
82#[cfg(test)]
83#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn register_then_read_round_trip() {
89 let s = ArchiveStore::new();
90 let id = s.register(b"hello world".to_vec());
91 assert_eq!(s.total_size(id), 11);
92 assert_eq!(s.read(id, 0, 5), b"hello");
93 assert_eq!(s.read(id, 6, 5), b"world");
94 assert_eq!(s.read(id, 100, 5), Vec::<u8>::new());
95 }
96
97 #[test]
98 fn unknown_id_returns_empty() {
99 let s = ArchiveStore::new();
100 let bogus = ArchiveId(Uuid::new_v4());
101 assert_eq!(s.total_size(bogus), 0);
102 assert_eq!(s.read(bogus, 0, 100), Vec::<u8>::new());
103 }
104}