1use fallow_config::WorkspaceInfo;
4
5use fallow_types::discover::{DiscoveredFile, FileId};
6
7pub struct ProjectState {
11 files: Vec<DiscoveredFile>,
12 workspaces: Vec<WorkspaceInfo>,
13}
14
15impl ProjectState {
16 #[must_use]
18 pub fn new(files: Vec<DiscoveredFile>, workspaces: Vec<WorkspaceInfo>) -> Self {
19 debug_assert!(
20 files.iter().enumerate().all(|(i, f)| f.id.0 as usize == i),
21 "FileIds must be densely packed starting at 0"
22 );
23 Self { files, workspaces }
24 }
25
26 #[must_use]
28 pub fn files(&self) -> &[DiscoveredFile] {
29 &self.files
30 }
31
32 #[must_use]
34 pub fn workspaces(&self) -> &[WorkspaceInfo] {
35 &self.workspaces
36 }
37
38 #[must_use]
40 pub fn file_by_id(&self, id: FileId) -> Option<&DiscoveredFile> {
41 self.files.get(id.0 as usize)
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use std::path::PathBuf;
48
49 use super::*;
50
51 fn make_file(id: u32, path: &str) -> DiscoveredFile {
52 DiscoveredFile {
53 id: FileId(id),
54 path: PathBuf::from(path),
55 size_bytes: 100,
56 }
57 }
58
59 fn make_workspace(name: &str, root: &str) -> WorkspaceInfo {
60 WorkspaceInfo {
61 root: PathBuf::from(root),
62 name: name.to_string(),
63 is_internal_dependency: false,
64 }
65 }
66
67 #[test]
68 fn file_by_id_valid() {
69 let files = vec![
70 make_file(0, "/project/src/a.ts"),
71 make_file(1, "/project/src/b.ts"),
72 ];
73 let state = ProjectState::new(files, vec![]);
74 let file = state.file_by_id(FileId(0)).unwrap();
75 assert_eq!(file.path, PathBuf::from("/project/src/a.ts"));
76 assert_eq!(file.id, FileId(0));
77 }
78
79 #[test]
80 fn file_by_id_out_of_bounds() {
81 let files = vec![make_file(0, "/project/src/a.ts")];
82 let state = ProjectState::new(files, vec![]);
83 assert!(state.file_by_id(FileId(999)).is_none());
84 }
85
86 #[test]
87 fn empty_state() {
88 let state = ProjectState::new(vec![], vec![]);
89 assert!(state.files().is_empty());
90 assert!(state.workspaces().is_empty());
91 assert!(state.file_by_id(FileId(0)).is_none());
92 }
93
94 #[test]
95 fn files_returns_all_files() {
96 let files = vec![
97 make_file(0, "/project/src/a.ts"),
98 make_file(1, "/project/src/b.ts"),
99 ];
100 let state = ProjectState::new(files, vec![]);
101 assert_eq!(state.files().len(), 2);
102 assert_eq!(state.files()[0].id, FileId(0));
103 assert_eq!(state.files()[1].id, FileId(1));
104 }
105
106 #[test]
107 fn workspaces_returns_all_workspaces() {
108 let workspaces = vec![
109 make_workspace("a", "/project/packages/a"),
110 make_workspace("b", "/project/packages/b"),
111 ];
112 let state = ProjectState::new(vec![], workspaces);
113 assert_eq!(state.workspaces().len(), 2);
114 }
115}