1use rkyv::{Archive, Deserialize, Serialize};
2
3use crate::WorkspaceIndex;
4
5pub const ARCHIVE_SCHEMA_VERSION: u32 = 1;
6
7#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
8#[rkyv(compare(PartialEq), derive(Debug))]
9pub struct ArchivedWorkspace {
10 pub schema_version: u32,
11 pub index: WorkspaceIndex,
12}
13
14#[derive(Debug, thiserror::Error)]
15pub enum ArchiveError {
16 #[error("workspace archive schema {found} is not supported; expected {expected}")]
17 UnsupportedSchema { found: u32, expected: u32 },
18}
19
20impl ArchivedWorkspace {
21 pub fn new(index: WorkspaceIndex) -> Self {
22 Self {
23 schema_version: ARCHIVE_SCHEMA_VERSION,
24 index,
25 }
26 }
27
28 pub fn validate_schema(&self) -> Result<(), ArchiveError> {
29 if self.schema_version == ARCHIVE_SCHEMA_VERSION {
30 Ok(())
31 } else {
32 Err(ArchiveError::UnsupportedSchema {
33 found: self.schema_version,
34 expected: ARCHIVE_SCHEMA_VERSION,
35 })
36 }
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::{ARCHIVE_SCHEMA_VERSION, ArchivedWorkspace};
43 use crate::WorkspaceIndex;
44
45 #[test]
46 fn rejects_stale_schema() {
47 let archive = ArchivedWorkspace {
48 schema_version: ARCHIVE_SCHEMA_VERSION + 1,
49 index: WorkspaceIndex {
50 diagnostics: Vec::new(),
51 imports: Vec::new(),
52 symbols: Vec::new(),
53 },
54 };
55
56 assert!(archive.validate_schema().is_err());
57 }
58
59 #[test]
60 fn rkyv_round_trip_workspace_archive() {
61 let archive = ArchivedWorkspace::new(WorkspaceIndex {
62 diagnostics: Vec::new(),
63 imports: Vec::new(),
64 symbols: Vec::new(),
65 });
66 let bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&archive).unwrap();
67 let archived =
68 rkyv::access::<super::ArchivedArchivedWorkspace, rkyv::rancor::Error>(&bytes).unwrap();
69 assert_eq!(archived.schema_version, ARCHIVE_SCHEMA_VERSION);
70 }
71}