use std::path::PathBuf;
pub fn enumerate() -> std::io::Result<Vec<PathBuf>> {
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::FileTypeExt;
let serial_ports = std::fs::read_dir("/dev")?
.filter_map(|entry| {
let entry = entry.ok()?;
let kind = entry.metadata().ok()?.file_type();
if kind.is_char_device() && is_tty_name(entry.file_name().as_bytes()) {
Some(entry.path())
} else {
None
}
})
.collect();
Ok(serial_ports)
}
fn is_tty_name(name: &[u8]) -> bool {
#[cfg(target_os = "dragonfly")]
const PREFIXES: [&[u8]; 4] = [b"ttyd", b"cuaa", b"ttyU", b"cuaU"];
#[cfg(target_os = "freebsd")]
const PREFIXES: [&[u8]; 5] = [b"ttyu", b"cuau", b"cuad", b"ttyU", b"cuaU"];
#[cfg(target_os = "netbsd")]
const PREFIXES: [&[u8]; 4] = [b"tty", b"dty", b"ttyU", b"dtyU"];
#[cfg(target_os = "openbsd")]
const PREFIXES: [&[u8]; 4] = [b"tty", b"cua", b"ttyU", b"cuaU"];
for prefix in PREFIXES {
if let Some(suffix) = name.strip_prefix(prefix) {
if !suffix.is_empty() && suffix.iter().all(|c| c.is_ascii_digit()) {
return true;
}
}
}
false
}