1use std::path::PathBuf;
4
5#[derive(Debug, Clone)]
22pub struct DiscoveredFile {
23 pub id: FileId,
25 pub path: PathBuf,
27 pub size_bytes: u64,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
49pub struct FileId(pub u32);
50
51const _: () = assert!(std::mem::size_of::<FileId>() == 4);
55#[cfg(all(target_pointer_width = "64", unix))]
56const _: () = assert!(std::mem::size_of::<DiscoveredFile>() == 40);
57
58#[derive(Debug, Clone)]
60pub struct EntryPoint {
61 pub path: PathBuf,
63 pub source: EntryPointSource,
65}
66
67#[derive(Debug, Clone)]
69pub enum EntryPointSource {
70 PackageJsonMain,
72 PackageJsonModule,
74 PackageJsonExports,
76 PackageJsonBin,
78 PackageJsonScript,
80 Plugin {
82 name: String,
84 },
85 TestFile,
87 DefaultIndex,
89 ManualEntry,
91 InfrastructureConfig,
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use std::collections::hash_map::DefaultHasher;
99 use std::hash::{Hash, Hasher};
100
101 #[test]
104 fn file_id_equality() {
105 assert_eq!(FileId(0), FileId(0));
106 assert_eq!(FileId(42), FileId(42));
107 assert_ne!(FileId(0), FileId(1));
108 }
109
110 #[test]
111 fn file_id_copy_semantics() {
112 let a = FileId(5);
113 let b = a; assert_eq!(a, b);
115 }
116
117 #[test]
118 fn file_id_hash_consistent() {
119 let id = FileId(99);
120 let hash1 = {
121 let mut h = DefaultHasher::new();
122 id.hash(&mut h);
123 h.finish()
124 };
125 let hash2 = {
126 let mut h = DefaultHasher::new();
127 id.hash(&mut h);
128 h.finish()
129 };
130 assert_eq!(hash1, hash2);
131 }
132
133 #[test]
134 fn file_id_equal_values_same_hash() {
135 let a = FileId(7);
136 let b = FileId(7);
137 let hash_a = {
138 let mut h = DefaultHasher::new();
139 a.hash(&mut h);
140 h.finish()
141 };
142 let hash_b = {
143 let mut h = DefaultHasher::new();
144 b.hash(&mut h);
145 h.finish()
146 };
147 assert_eq!(hash_a, hash_b);
148 }
149
150 #[test]
151 fn file_id_inner_value_accessible() {
152 let id = FileId(123);
153 assert_eq!(id.0, 123);
154 }
155
156 #[test]
157 fn file_id_debug_format() {
158 let id = FileId(42);
159 let debug = format!("{id:?}");
160 assert!(
161 debug.contains("42"),
162 "Debug should show inner value: {debug}"
163 );
164 }
165
166 #[test]
169 fn discovered_file_clone() {
170 let original = DiscoveredFile {
171 id: FileId(0),
172 path: PathBuf::from("/project/src/index.ts"),
173 size_bytes: 1024,
174 };
175 let cloned = original.clone();
176 assert_eq!(cloned.id, original.id);
177 assert_eq!(cloned.path, original.path);
178 assert_eq!(cloned.size_bytes, original.size_bytes);
179 }
180
181 #[test]
182 fn discovered_file_zero_size() {
183 let file = DiscoveredFile {
184 id: FileId(0),
185 path: PathBuf::from("/empty.ts"),
186 size_bytes: 0,
187 };
188 assert_eq!(file.size_bytes, 0);
189 }
190
191 #[test]
192 fn discovered_file_large_size() {
193 let file = DiscoveredFile {
194 id: FileId(0),
195 path: PathBuf::from("/large.ts"),
196 size_bytes: u64::MAX,
197 };
198 assert_eq!(file.size_bytes, u64::MAX);
199 }
200
201 #[test]
204 fn entry_point_clone() {
205 let ep = EntryPoint {
206 path: PathBuf::from("/project/src/main.ts"),
207 source: EntryPointSource::PackageJsonMain,
208 };
209 let cloned = ep.clone();
210 assert_eq!(cloned.path, ep.path);
211 assert!(matches!(cloned.source, EntryPointSource::PackageJsonMain));
212 }
213
214 #[test]
217 fn entry_point_source_all_variants_constructible() {
218 let _ = EntryPointSource::PackageJsonMain;
220 let _ = EntryPointSource::PackageJsonModule;
221 let _ = EntryPointSource::PackageJsonExports;
222 let _ = EntryPointSource::PackageJsonBin;
223 let _ = EntryPointSource::PackageJsonScript;
224 let _ = EntryPointSource::Plugin {
225 name: "next".to_string(),
226 };
227 let _ = EntryPointSource::TestFile;
228 let _ = EntryPointSource::DefaultIndex;
229 let _ = EntryPointSource::ManualEntry;
230 let _ = EntryPointSource::InfrastructureConfig;
231 }
232
233 #[test]
234 fn entry_point_source_plugin_preserves_name() {
235 let source = EntryPointSource::Plugin {
236 name: "vitest".to_string(),
237 };
238 match source {
239 EntryPointSource::Plugin { name } => assert_eq!(name, "vitest"),
240 _ => panic!("expected Plugin variant"),
241 }
242 }
243
244 #[test]
245 fn entry_point_source_plugin_clone_preserves_name() {
246 let source = EntryPointSource::Plugin {
247 name: "storybook".to_string(),
248 };
249 let cloned = source.clone();
251 assert!(matches!(&source, EntryPointSource::Plugin { name } if name == "storybook"));
253 match cloned {
255 EntryPointSource::Plugin { name } => assert_eq!(name, "storybook"),
256 _ => panic!("expected Plugin variant after clone"),
257 }
258 }
259
260 #[test]
261 fn entry_point_source_debug_format() {
262 let source = EntryPointSource::PackageJsonMain;
263 let debug = format!("{source:?}");
264 assert!(
265 debug.contains("PackageJsonMain"),
266 "Debug should name the variant: {debug}"
267 );
268
269 let plugin = EntryPointSource::Plugin {
270 name: "remix".to_string(),
271 };
272 let debug = format!("{plugin:?}");
273 assert!(
274 debug.contains("remix"),
275 "Debug should show plugin name: {debug}"
276 );
277 }
278}