use crate::error::{Error, Result};
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Compression {
None,
Gzip,
Bgzip,
Zstd,
}
impl Compression {
pub fn from_path<P: AsRef<Path>>(path: P) -> Self {
let path = path.as_ref();
if let Some(ext) = path.extension() {
match ext.to_str() {
Some("gz") => Compression::Gzip,
Some("bgz") | Some("bgzf") => Compression::Bgzip,
Some("zst") => Compression::Zstd,
_ => Compression::None,
}
} else {
Compression::None
}
}
}
#[derive(Debug, Clone)]
pub enum FileLocation {
Local(String),
S3(String),
Gcs(String),
Azure(String),
Http(String),
}
impl FileLocation {
pub fn parse(s: &str) -> Self {
if s.starts_with("s3://") {
FileLocation::S3(s.to_string())
} else if s.starts_with("gs://") {
FileLocation::Gcs(s.to_string())
} else if s.starts_with("http://") || s.starts_with("https://") {
FileLocation::Http(s.to_string())
} else if s.starts_with("az://") || s.starts_with("azure://") {
FileLocation::Azure(s.to_string())
} else {
FileLocation::Local(s.to_string())
}
}
pub fn is_local(&self) -> bool {
matches!(self, FileLocation::Local(_))
}
pub fn is_remote(&self) -> bool {
!self.is_local()
}
}
pub struct CloudReader;
impl CloudReader {
pub fn open(_location: FileLocation) -> Result<Self> {
Err(Error::NotImplemented(
"Cloud storage support will be implemented in Phase 1b".to_string(),
))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_compression_detection() {
assert_eq!(
Compression::from_path("file.vcf.gz"),
Compression::Gzip
);
assert_eq!(
Compression::from_path("file.vcf.bgz"),
Compression::Bgzip
);
assert_eq!(
Compression::from_path("file.vcf"),
Compression::None
);
}
#[test]
fn test_file_location_parsing() {
assert!(matches!(
FileLocation::parse("/local/path/file.vcf"),
FileLocation::Local(_)
));
assert!(matches!(
FileLocation::parse("s3://bucket/file.vcf"),
FileLocation::S3(_)
));
assert!(matches!(
FileLocation::parse("gs://bucket/file.vcf"),
FileLocation::Gcs(_)
));
}
}