use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct DiscoveredFile {
pub id: FileId,
pub path: PathBuf,
pub size_bytes: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FileId(pub u32);
const _: () = assert!(std::mem::size_of::<FileId>() == 4);
#[cfg(all(target_pointer_width = "64", unix))]
const _: () = assert!(std::mem::size_of::<DiscoveredFile>() == 40);
#[derive(Debug, Clone)]
pub struct EntryPoint {
pub path: PathBuf,
pub source: EntryPointSource,
}
impl std::fmt::Display for EntryPointSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::PackageJsonMain => f.write_str("package.json main"),
Self::PackageJsonModule => f.write_str("package.json module"),
Self::PackageJsonExports => f.write_str("package.json exports"),
Self::PackageJsonBin => f.write_str("package.json bin"),
Self::PackageJsonScript => f.write_str("package.json script"),
Self::Plugin { name } => write!(f, "{name}"),
Self::TestFile => f.write_str("test file"),
Self::DefaultIndex => f.write_str("default index"),
Self::ManualEntry => f.write_str("manual entry"),
Self::InfrastructureConfig => f.write_str("infrastructure config"),
Self::DynamicallyLoaded => f.write_str("dynamically loaded"),
}
}
}
#[derive(Debug, Clone)]
pub enum EntryPointSource {
PackageJsonMain,
PackageJsonModule,
PackageJsonExports,
PackageJsonBin,
PackageJsonScript,
Plugin {
name: String,
},
TestFile,
DefaultIndex,
ManualEntry,
InfrastructureConfig,
DynamicallyLoaded,
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
#[test]
fn file_id_equality() {
assert_eq!(FileId(0), FileId(0));
assert_eq!(FileId(42), FileId(42));
assert_ne!(FileId(0), FileId(1));
}
#[test]
fn file_id_copy_semantics() {
let a = FileId(5);
let b = a; assert_eq!(a, b);
}
#[test]
fn file_id_hash_consistent() {
let id = FileId(99);
let hash1 = {
let mut h = DefaultHasher::new();
id.hash(&mut h);
h.finish()
};
let hash2 = {
let mut h = DefaultHasher::new();
id.hash(&mut h);
h.finish()
};
assert_eq!(hash1, hash2);
}
#[test]
fn file_id_equal_values_same_hash() {
let a = FileId(7);
let b = FileId(7);
let hash_a = {
let mut h = DefaultHasher::new();
a.hash(&mut h);
h.finish()
};
let hash_b = {
let mut h = DefaultHasher::new();
b.hash(&mut h);
h.finish()
};
assert_eq!(hash_a, hash_b);
}
#[test]
fn file_id_inner_value_accessible() {
let id = FileId(123);
assert_eq!(id.0, 123);
}
#[test]
fn file_id_debug_format() {
let id = FileId(42);
let debug = format!("{id:?}");
assert!(
debug.contains("42"),
"Debug should show inner value: {debug}"
);
}
#[test]
fn discovered_file_clone() {
let original = DiscoveredFile {
id: FileId(0),
path: PathBuf::from("/project/src/index.ts"),
size_bytes: 1024,
};
let cloned = original.clone();
assert_eq!(cloned.id, original.id);
assert_eq!(cloned.path, original.path);
assert_eq!(cloned.size_bytes, original.size_bytes);
}
#[test]
fn discovered_file_zero_size() {
let file = DiscoveredFile {
id: FileId(0),
path: PathBuf::from("/empty.ts"),
size_bytes: 0,
};
assert_eq!(file.size_bytes, 0);
}
#[test]
fn discovered_file_large_size() {
let file = DiscoveredFile {
id: FileId(0),
path: PathBuf::from("/large.ts"),
size_bytes: u64::MAX,
};
assert_eq!(file.size_bytes, u64::MAX);
}
#[test]
fn entry_point_clone() {
let ep = EntryPoint {
path: PathBuf::from("/project/src/main.ts"),
source: EntryPointSource::PackageJsonMain,
};
let cloned = ep.clone();
assert_eq!(cloned.path, ep.path);
assert!(matches!(cloned.source, EntryPointSource::PackageJsonMain));
}
#[test]
fn entry_point_source_all_variants_constructible() {
let _ = EntryPointSource::PackageJsonMain;
let _ = EntryPointSource::PackageJsonModule;
let _ = EntryPointSource::PackageJsonExports;
let _ = EntryPointSource::PackageJsonBin;
let _ = EntryPointSource::PackageJsonScript;
let _ = EntryPointSource::Plugin {
name: "next".to_string(),
};
let _ = EntryPointSource::TestFile;
let _ = EntryPointSource::DefaultIndex;
let _ = EntryPointSource::ManualEntry;
let _ = EntryPointSource::InfrastructureConfig;
let _ = EntryPointSource::DynamicallyLoaded;
}
#[test]
fn entry_point_source_plugin_preserves_name() {
let source = EntryPointSource::Plugin {
name: "vitest".to_string(),
};
match source {
EntryPointSource::Plugin { name } => assert_eq!(name, "vitest"),
_ => panic!("expected Plugin variant"),
}
}
#[test]
fn entry_point_source_plugin_clone_preserves_name() {
let source = EntryPointSource::Plugin {
name: "storybook".to_string(),
};
let cloned = source.clone();
assert!(matches!(&source, EntryPointSource::Plugin { name } if name == "storybook"));
match cloned {
EntryPointSource::Plugin { name } => assert_eq!(name, "storybook"),
_ => panic!("expected Plugin variant after clone"),
}
}
#[test]
fn entry_point_source_debug_format() {
let source = EntryPointSource::PackageJsonMain;
let debug = format!("{source:?}");
assert!(
debug.contains("PackageJsonMain"),
"Debug should name the variant: {debug}"
);
let plugin = EntryPointSource::Plugin {
name: "remix".to_string(),
};
let debug = format!("{plugin:?}");
assert!(
debug.contains("remix"),
"Debug should show plugin name: {debug}"
);
}
#[test]
fn entry_point_source_display_all_variants() {
assert_eq!(
EntryPointSource::PackageJsonMain.to_string(),
"package.json main"
);
assert_eq!(
EntryPointSource::PackageJsonModule.to_string(),
"package.json module"
);
assert_eq!(
EntryPointSource::PackageJsonExports.to_string(),
"package.json exports"
);
assert_eq!(
EntryPointSource::PackageJsonBin.to_string(),
"package.json bin"
);
assert_eq!(
EntryPointSource::PackageJsonScript.to_string(),
"package.json script"
);
assert_eq!(
EntryPointSource::Plugin {
name: "vitest".to_string()
}
.to_string(),
"vitest"
);
assert_eq!(EntryPointSource::TestFile.to_string(), "test file");
assert_eq!(EntryPointSource::DefaultIndex.to_string(), "default index");
assert_eq!(EntryPointSource::ManualEntry.to_string(), "manual entry");
assert_eq!(
EntryPointSource::InfrastructureConfig.to_string(),
"infrastructure config"
);
assert_eq!(
EntryPointSource::DynamicallyLoaded.to_string(),
"dynamically loaded"
);
}
}