dicom_finder/
lib.rs

1use rust_search_fork::{FilterExt, SearchBuilder};
2
3use std::fs::File;
4use std::io::{self, Read, Seek, SeekFrom};
5use std::path::Path;
6
7pub fn find_dicom_files(
8    dir: &Path,
9    ext: &str,
10    search_input: Option<&str>,
11    depth: usize,
12    validate: bool,
13    threads: usize,
14    limit: usize,
15) -> Vec<String> {
16    let mut search_builder = SearchBuilder::default()
17        .location(dir)
18        .ext(ext)
19        .threads(threads);
20
21    if depth > 0 {
22        search_builder = search_builder.depth(depth);
23    }
24    if let Some(input) = search_input {
25        search_builder = search_builder.search_input(input);
26    }
27    if limit > 0 {
28        search_builder = search_builder.limit(limit);
29    };
30
31    if validate {
32        search_builder = search_builder
33            .dirs(false)
34            .custom_filter(|dir| is_valid_dicom(dir.path().to_str().unwrap()).unwrap_or(false));
35    }
36    search_builder.build().collect()
37}
38
39/// Function to validate if a file is a DICOM file.
40pub fn is_valid_dicom(filename: &str) -> io::Result<bool> {
41    let mut file = File::open(filename)?;
42
43    // Seek to byte offset 128
44    file.seek(SeekFrom::Start(128))?;
45
46    // Read the next 4 bytes
47    let mut buffer = [0u8; 4];
48    let n = file.read(&mut buffer)?;
49
50    // If fewer than 4 bytes were read, it's not a DICOM file
51    if n < 4 {
52        return Ok(false);
53    }
54    // Compare the buffer to "DICM"
55    Ok(&buffer == b"DICM")
56}