use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::sync::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::time::SystemTime;
pub use crate::{
ape_is_exec_format_error as is_exec_format_error,
APE_EXECVP_SHELL_FALLBACK as EXECVP_SHELL_FALLBACK, APE_LOADER_HOST as LOADER_HOST,
APE_NEEDS_LOADER as NEEDS_LOADER, APE_SHELL as SHELL, APE_SYSTEM_LOADERS as SYSTEM_LOADERS,
};
pub const LOADER_ENV: &str = "RUNNING_PROCESS_APE_LOADER";
pub const CACHE_DIR_ENV: &str = "RUNNING_PROCESS_APE_CACHE_DIR";
pub const MAGICS: [&[u8]; 3] = [b"MZqFpD='", b"jartsr='", b"APEDBG='"];
#[cfg(feature = "ape-loader")]
const PROLOGUE_SCAN_BYTES: u64 = 64 * 1024;
#[cfg(feature = "ape-loader")]
const MAX_LOADER_BYTES: u64 = 4 * 1024 * 1024;
pub fn is_ape_header(header: &[u8]) -> bool {
MAGICS.iter().any(|magic| header.starts_with(magic))
}
pub fn is_ape_file(path: &Path) -> bool {
let mut header = [0u8; 8];
File::open(path)
.and_then(|mut file| file.read_exact(&mut header))
.is_ok_and(|()| is_ape_header(&header))
}
static FORK_LOCK: RwLock<()> = RwLock::new(());
pub fn fork_guard() -> RwLockReadGuard<'static, ()> {
FORK_LOCK.read().unwrap_or_else(|error| error.into_inner())
}
pub fn exclusive_fork_guard() -> RwLockWriteGuard<'static, ()> {
FORK_LOCK.write().unwrap_or_else(|error| error.into_inner())
}
pub fn retry_while_busy<T>(mut spawn: impl FnMut() -> io::Result<T>) -> io::Result<T> {
for delay_ms in [1, 4, 16, 64, 256] {
match spawn() {
Err(error) if error.kind() == io::ErrorKind::ExecutableFileBusy => {
std::thread::sleep(std::time::Duration::from_millis(delay_ms));
}
result => return result,
}
}
spawn()
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ApeOptions {
pub path: Option<OsString>,
pub loader: Option<OsString>,
pub cache_dirs: Vec<PathBuf>,
}
impl ApeOptions {
pub fn inherited() -> Self {
Self::with_overrides(false, [])
}
pub fn with_overrides<'a>(
clear: bool,
overrides: impl IntoIterator<Item = (&'a OsStr, Option<&'a OsStr>)>,
) -> Self {
let inherited = |name: &str| {
if clear {
return None;
}
match name {
"PATH" => crate::env_vars::PATH.os(),
LOADER_ENV => crate::env_vars::APE_LOADER.os(),
_ => crate::env_vars::APE_CACHE_DIR.os(),
}
};
let mut path = inherited("PATH");
let mut loader = inherited(LOADER_ENV);
let mut cache_dir = inherited(CACHE_DIR_ENV);
for (key, value) in overrides {
let slot = match key.to_str() {
Some("PATH") => &mut path,
Some(LOADER_ENV) => &mut loader,
Some(CACHE_DIR_ENV) => &mut cache_dir,
_ => continue,
};
*slot = value.map(OsStr::to_os_string);
}
let set = |value: Option<OsString>| value.filter(|value| !value.is_empty());
let mut cache_dirs: Vec<PathBuf> = set(cache_dir).map(PathBuf::from).into_iter().collect();
cache_dirs.extend(crate::ape_default_loader_dirs());
Self {
path: set(path),
loader: set(loader),
cache_dirs,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LoaderKind {
Explicit,
Embedded,
System,
Shell,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ApeLaunch {
pub kind: LoaderKind,
pub loader: PathBuf,
pub image: PathBuf,
pub ape_path_dir: Option<PathBuf>,
}
impl ApeLaunch {
pub fn child_path(&self, inherited: Option<&OsStr>) -> Option<OsString> {
let dir = self.ape_path_dir.as_ref()?;
let rest = inherited.filter(|path| !path.is_empty());
std::env::join_paths(
std::iter::once(dir.clone()).chain(rest.into_iter().flat_map(std::env::split_paths)),
)
.ok()
}
pub fn args<I, S>(&self, args: I) -> Vec<OsString>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
std::iter::once(self.image.clone().into_os_string())
.chain(args.into_iter().map(|arg| arg.as_ref().to_os_string()))
.collect()
}
}
pub fn plan_launch(
program: &OsStr,
current_dir: Option<&Path>,
options: &ApeOptions,
) -> Option<ApeLaunch> {
if !NEEDS_LOADER {
return None;
}
let image = resolve_program(program, current_dir, options.path.as_deref())?;
if !is_ape_file(&image) {
return None;
}
let launch = |kind, loader: PathBuf| ApeLaunch {
kind,
ape_path_dir: ape_path_dir(&loader, &options.cache_dirs),
loader,
image: image.clone(),
};
if let Some(explicit) = options.loader.as_deref() {
return resolve_explicit_loader(explicit, options.path.as_deref())
.map(|loader| launch(LoaderKind::Explicit, loader));
}
if let Some(loader) = embedded_loader(&image, &options.cache_dirs) {
return Some(launch(LoaderKind::Embedded, loader));
}
if let Some(loader) = system_loader(options.path.as_deref()) {
return Some(launch(LoaderKind::System, loader));
}
shell(options.path.as_deref()).map(|loader| launch(LoaderKind::Shell, loader))
}
pub fn resolve_program(
program: &OsStr,
current_dir: Option<&Path>,
path: Option<&OsStr>,
) -> Option<PathBuf> {
let program_path = Path::new(program);
if program_path.components().count() > 1 || program_path.is_absolute() {
let resolved = match current_dir {
Some(dir) if program_path.is_relative() => dir.join(program_path),
_ => program_path.to_path_buf(),
};
return std::path::absolute(resolved).ok();
}
find_executable_on_path(program, path).and_then(|found| std::path::absolute(found).ok())
}
fn resolve_explicit_loader(explicit: &OsStr, path: Option<&OsStr>) -> Option<PathBuf> {
let explicit_path = Path::new(explicit);
if explicit_path.components().count() > 1 || explicit_path.is_absolute() {
return Some(explicit_path.to_path_buf());
}
find_executable_on_path(explicit, path)
}
fn system_loader(path: Option<&OsStr>) -> Option<PathBuf> {
find_executable_on_path(OsStr::new("ape"), path)
.or_else(|| first_executable(SYSTEM_LOADERS.iter().map(PathBuf::from)))
}
fn shell(path: Option<&OsStr>) -> Option<PathBuf> {
first_executable([PathBuf::from(SHELL)])
.or_else(|| find_executable_on_path(OsStr::new("sh"), path))
}
fn find_executable_on_path(name: &OsStr, path: Option<&OsStr>) -> Option<PathBuf> {
let dirs = std::env::split_paths(path?).filter(|dir| !dir.as_os_str().is_empty());
first_executable(dirs.map(|dir| dir.join(name)))
}
fn first_executable(candidates: impl IntoIterator<Item = PathBuf>) -> Option<PathBuf> {
candidates.into_iter().find(|candidate| {
std::fs::metadata(candidate)
.is_ok_and(|meta| meta.is_file() && crate::ape_is_executable(&meta))
})
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LoaderHost {
None,
Linux,
Macos,
}
pub type Range = (u64, u64);
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Prologue {
pub linux_loader_x86_64: Option<Range>,
pub linux_loader_aarch64: Option<Range>,
pub macos_loader_x86_64: Option<Range>,
pub macos_loader_source_aarch64: Option<Range>,
}
impl Prologue {
pub fn parse(prologue: &[u8]) -> Self {
let text = String::from_utf8_lossy(prologue);
let mut parsed = Self::default();
let mut cpu = None;
let mut lines = text.lines().map(str::trim).peekable();
while let Some(line) = lines.next() {
if line.contains("\"$m\" = x86_64") {
cpu = Some("x86_64");
} else if line.contains("\"$m\" = aarch64") {
cpu = Some("aarch64");
}
let Some(cpu) = cpu else { continue };
if !line.starts_with("dd if=\"$o\" ") {
continue;
}
if line.contains("| gzip -dc >\"$t.c.$$\"") {
if cpu == "aarch64" {
parsed.macos_loader_source_aarch64 = range(line);
}
} else if line.contains("| gzip -dc >\"$t.$$\"") {
let patched = lines
.peek()
.is_some_and(|next| next.starts_with("dd if=\"$t.$$\" of=\"$t.$$\""));
match (cpu, patched) {
("x86_64", true) => parsed.macos_loader_x86_64 = range(line),
("x86_64", false) => parsed.linux_loader_x86_64 = range(line),
("aarch64", false) => parsed.linux_loader_aarch64 = range(line),
_ => {}
}
}
}
parsed
}
pub fn linux_loader(&self, machine: &str) -> Option<Range> {
match machine {
"x86_64" => self.linux_loader_x86_64,
"aarch64" => self.linux_loader_aarch64,
_ => None,
}
}
}
fn range(line: &str) -> Option<Range> {
let field = |key: &str| {
line.split_whitespace()
.find_map(|token| token.strip_prefix(key))
.and_then(|value| value.parse::<u64>().ok())
};
Some((field("skip=")?, field("count=")?))
}
pub fn loader_blob_range(prologue: &[u8], machine: &str) -> Option<Range> {
Prologue::parse(prologue).linux_loader(machine)
}
type ImageKey = (PathBuf, u64, Option<SystemTime>, Vec<PathBuf>);
struct Memo(Mutex<Option<HashMap<ImageKey, PathBuf>>>);
impl Memo {
const fn new() -> Self {
Self(Mutex::new(None))
}
fn get(&self, key: &ImageKey) -> Option<PathBuf> {
let guard = self.0.lock().unwrap_or_else(|error| error.into_inner());
let hit = guard.as_ref()?.get(key)?.clone();
hit.exists().then_some(hit)
}
fn put(&self, key: ImageKey, path: PathBuf) {
let mut guard = self.0.lock().unwrap_or_else(|error| error.into_inner());
guard.get_or_insert_with(HashMap::new).insert(key, path);
}
}
static LOADER_MEMO: Memo = Memo::new();
fn image_key(image: &Path, cache_dirs: &[PathBuf]) -> Option<ImageKey> {
let meta = std::fs::metadata(image).ok()?;
Some((
image.to_path_buf(),
meta.len(),
meta.modified().ok(),
cache_dirs.to_vec(),
))
}
pub fn embedded_loader(image: &Path, cache_dirs: &[PathBuf]) -> Option<PathBuf> {
if LOADER_HOST == LoaderHost::None {
return None;
}
let key = image_key(image, cache_dirs)?;
if let Some(hit) = LOADER_MEMO.get(&key) {
return Some(hit);
}
let loader = install_embedded_loader(image, cache_dirs)?;
LOADER_MEMO.put(key, loader.clone());
Some(loader)
}
#[cfg(feature = "ape-loader")]
fn install_embedded_loader(image: &Path, cache_dirs: &[PathBuf]) -> Option<PathBuf> {
let machine = std::env::consts::ARCH;
match (LOADER_HOST, machine) {
(LoaderHost::Linux, _) => {
let bytes = extract_loader(image, machine)?;
let name = format!("ape-loader-linux-{machine}-{}", short_hash(&bytes));
materialize(&bytes, &name, cache_dirs)
}
(LoaderHost::Macos, "x86_64") => {
let bytes = extract_macos_x86_64_loader(image)?;
let name = format!("ape-loader-macos-{machine}-{}", short_hash(&bytes));
materialize(&bytes, &name, cache_dirs)
}
(LoaderHost::Macos, "aarch64") => compile_macos_aarch64_loader(image, cache_dirs),
_ => None,
}
}
#[cfg(not(feature = "ape-loader"))]
fn install_embedded_loader(_image: &Path, _cache_dirs: &[PathBuf]) -> Option<PathBuf> {
None
}
#[cfg(feature = "ape-loader")]
fn materialize(bytes: &[u8], name: &str, dirs: &[PathBuf]) -> Option<PathBuf> {
install(dirs, None, name, bytes).or_else(|| crate::ape_anonymous_executable(bytes, name))
}
fn short_hash(bytes: &[u8]) -> String {
let hash = bytes.iter().fold(0xcbf2_9ce4_8422_2325_u64, |hash, &byte| {
(hash ^ u64::from(byte)).wrapping_mul(0x0000_0100_0000_01b3)
});
format!("{hash:016x}")
}
pub fn install(
dirs: &[PathBuf],
subdir: Option<&str>,
name: &str,
bytes: &[u8],
) -> Option<PathBuf> {
dirs.iter().find_map(|dir| match subdir {
Some(sub) => crate::ape_private_exec_dir(dir)
.then(|| install_in(&dir.join(sub), bytes, name))
.flatten(),
None => install_in(dir, bytes, name),
})
}
pub fn install_in(dir: &Path, bytes: &[u8], name: &str) -> Option<PathBuf> {
use std::io::Write;
use std::sync::atomic::{AtomicU64, Ordering};
if !crate::ape_private_exec_dir(dir) {
return None;
}
let target = dir.join(name);
if is_installed(&target, bytes) {
return Some(target);
}
static SEQ: AtomicU64 = AtomicU64::new(0);
let staging = dir.join(format!(
".{name}.{}.{}",
std::process::id(),
SEQ.fetch_add(1, Ordering::Relaxed)
));
let written = {
let _fork = exclusive_fork_guard();
std::fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(&staging)
.and_then(|mut file| {
file.write_all(bytes)?;
file.sync_all()
})
}
.and_then(|()| crate::ape_mark_executable(&staging))
.and_then(|()| std::fs::rename(&staging, &target));
if written.is_err() {
let _ = std::fs::remove_file(&staging);
return None;
}
is_installed(&target, bytes).then_some(target)
}
fn is_installed(path: &Path, bytes: &[u8]) -> bool {
std::fs::symlink_metadata(path).is_ok_and(|meta| {
meta.file_type().is_file()
&& crate::ape_is_executable(&meta)
&& meta.len() == bytes.len() as u64
}) && std::fs::read(path).is_ok_and(|content| content == bytes)
}
fn ape_path_dir(loader: &Path, cache_dirs: &[PathBuf]) -> Option<PathBuf> {
if loader.file_name().is_some_and(|name| name == "sh") || loader.starts_with("/proc/self") {
return None;
}
if loader.file_name().is_some_and(|name| name == "ape") {
return loader.parent().map(Path::to_path_buf);
}
let bytes = std::fs::read(loader).ok()?;
if bytes.len() as u64 > MAX_PATH_LOADER_BYTES {
return None;
}
let sub = format!("bin-{}", short_hash(&bytes));
install(cache_dirs, Some(&sub), "ape", &bytes)?
.parent()
.map(Path::to_path_buf)
}
const MAX_PATH_LOADER_BYTES: u64 = 4 * 1024 * 1024;
#[cfg(feature = "ape-loader")]
struct Image {
file: File,
len: u64,
prologue: Prologue,
}
#[cfg(feature = "ape-loader")]
impl Image {
fn open(image: &Path) -> Option<Self> {
let mut file = File::open(image).ok()?;
let len = file.metadata().ok()?.len();
let mut head = Vec::new();
(&mut file)
.take(PROLOGUE_SCAN_BYTES)
.read_to_end(&mut head)
.ok()?;
if !is_ape_header(&head) {
return None;
}
Some(Self {
file,
len,
prologue: Prologue::parse(&head),
})
}
fn read(&mut self, (skip, count): Range) -> Option<Vec<u8>> {
use std::io::{Seek, SeekFrom};
let end = skip.checked_add(count)?;
if count == 0 || count > MAX_LOADER_BYTES || end > self.len {
return None;
}
self.file.seek(SeekFrom::Start(skip)).ok()?;
let mut out = Vec::with_capacity(count as usize);
(&mut self.file).take(count).read_to_end(&mut out).ok()?;
(out.len() as u64 == count).then_some(out)
}
fn inflate(&mut self, range: Range) -> Option<Vec<u8>> {
gunzip(&self.read(range)?, MAX_LOADER_BYTES as usize).ok()
}
}
#[cfg(feature = "ape-loader")]
fn elf_machine(machine: &str) -> Option<u16> {
match machine {
"x86_64" => Some(62), "aarch64" => Some(183), _ => None,
}
}
#[cfg(feature = "ape-loader")]
pub fn extract_loader(image: &Path, machine: &str) -> Option<Vec<u8>> {
let elf_machine = elf_machine(machine)?;
let mut image = Image::open(image)?;
let range = image.prologue.linux_loader(machine)?;
let elf = image.inflate(range)?;
is_static_elf_for(&elf, elf_machine).then_some(elf)
}
#[cfg(feature = "ape-loader")]
pub fn extract_macos_x86_64_loader(image: &Path) -> Option<Vec<u8>> {
let mut image = Image::open(image)?;
let range = image.prologue.macos_loader_x86_64?;
let mut bin = image.inflate(range)?;
if bin.len() < 320 + 512 {
return None;
}
bin.copy_within(320..320 + 512, 0);
is_macho_x86_64(&bin).then_some(bin)
}
#[cfg(feature = "ape-loader")]
pub fn extract_macos_aarch64_loader_source(image: &Path) -> Option<Vec<u8>> {
let mut image = Image::open(image)?;
let range = image.prologue.macos_loader_source_aarch64?;
let source = image.inflate(range)?;
(std::str::from_utf8(&source).is_ok() && source.windows(4).any(|window| window == b"main"))
.then_some(source)
}
#[cfg(feature = "ape-loader")]
fn compile_macos_aarch64_loader(image: &Path, dirs: &[PathBuf]) -> Option<PathBuf> {
let source = extract_macos_aarch64_loader_source(image)?;
let name = format!("ape-loader-macos-aarch64-{}", short_hash(&source));
let dir = dirs.iter().find(|dir| crate::ape_private_exec_dir(dir))?;
let target = dir.join(&name);
if first_executable([target.clone()]).is_some() {
return Some(target);
}
let tag = format!(
"{}.{}",
std::process::id(),
short_hash(target.as_os_str().as_encoded_bytes())
);
let source_path = dir.join(format!(".{name}.{tag}.c"));
let out_path = dir.join(format!(".{name}.{tag}"));
std::fs::write(&source_path, &source).ok()?;
let cc =
first_executable([PathBuf::from("/usr/bin/cc")]).unwrap_or_else(|| PathBuf::from("cc"));
let mut command = std::process::Command::new(&cc);
command
.args(["-w", "-O", "-o"])
.arg(&out_path)
.arg(&source_path)
.stdin(std::process::Stdio::null());
let compiled = retry_while_busy(|| {
let _fork = fork_guard();
command.output()
});
let _ = std::fs::remove_file(&source_path);
let built = compiled.is_ok_and(|output| output.status.success())
&& std::fs::rename(&out_path, &target).is_ok();
if !built {
let _ = std::fs::remove_file(&out_path);
return None;
}
Some(target)
}
#[cfg(feature = "ape-loader")]
fn is_static_elf_for(elf: &[u8], machine: u16) -> bool {
elf.len() >= 64
&& elf.len() as u64 <= MAX_LOADER_BYTES
&& elf.starts_with(b"\x7fELF")
&& elf[4] == 2 && elf[5] == 1 && matches!(u16::from_le_bytes([elf[16], elf[17]]), 2 | 3)
&& u16::from_le_bytes([elf[18], elf[19]]) == machine
}
#[cfg(feature = "ape-loader")]
fn is_macho_x86_64(bin: &[u8]) -> bool {
bin.len() >= 32 && bin.starts_with(&[0xcf, 0xfa, 0xed, 0xfe]) && bin[4..8] == [7, 0, 0, 1]
}
#[cfg(feature = "ape-loader")]
pub fn gunzip(member: &[u8], limit: usize) -> io::Result<Vec<u8>> {
const FHCRC: u8 = 0x02;
const FEXTRA: u8 = 0x04;
const FNAME: u8 = 0x08;
const FCOMMENT: u8 = 0x10;
if member.len() < 18 || member[..3] != [0x1f, 0x8b, 8] {
return Err(invalid("not a deflate gzip member"));
}
let flags = member[3];
let mut at = 10;
if flags & FEXTRA != 0 {
let extra = member
.get(at..at + 2)
.ok_or_else(|| invalid("truncated gzip"))?;
at += 2 + usize::from(u16::from_le_bytes([extra[0], extra[1]]));
}
for flag in [FNAME, FCOMMENT] {
if flags & flag != 0 {
let terminator = member
.get(at..)
.and_then(|rest| rest.iter().position(|&byte| byte == 0))
.ok_or_else(|| invalid("truncated gzip"))?;
at += terminator + 1;
}
}
if flags & FHCRC != 0 {
at += 2;
}
let trailer = member.len() - 8;
let deflate = member
.get(at..trailer)
.ok_or_else(|| invalid("truncated gzip"))?;
let output = miniz_oxide::inflate::decompress_to_vec_with_limit(deflate, limit)
.map_err(|error| invalid(&format!("corrupt gzip member: {error}")))?;
let size = u32::from_le_bytes(member[trailer + 4..].try_into().expect("four bytes"));
if output.len() as u32 != size {
return Err(invalid("gzip member size does not match its trailer"));
}
Ok(output)
}
#[cfg(feature = "ape-loader")]
fn invalid(message: &str) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, message.to_owned())
}
pub fn command(program: impl AsRef<OsStr>) -> std::process::Command {
let program = program.as_ref();
let options = ApeOptions::inherited();
match plan_launch(program, None, &options) {
Some(launch) => {
let mut command = std::process::Command::new(&launch.loader);
command.arg(&launch.image);
if let Some(path) = launch.child_path(options.path.as_deref()) {
command.env("PATH", path);
}
command
}
None => std::process::Command::new(program),
}
}
#[cfg(feature = "async-process")]
pub fn tokio_command(program: impl AsRef<OsStr>) -> tokio::process::Command {
let program = program.as_ref();
let options = ApeOptions::inherited();
match plan_launch(program, None, &options) {
Some(launch) => {
let mut command = tokio::process::Command::new(&launch.loader);
command.arg(&launch.image);
if let Some(path) = launch.child_path(options.path.as_deref()) {
command.env("PATH", path);
}
command
}
None => tokio::process::Command::new(program),
}
}
pub fn prepare_std_retry(command: &mut std::process::Command, error: &io::Error) -> bool {
if !retryable(command, error) {
return false;
}
crate::ape_route_through_execvp(command);
true
}
#[cfg(feature = "async-process")]
pub fn prepare_tokio_retry(command: &mut tokio::process::Command, error: &io::Error) -> bool {
if !retryable(command.as_std(), error) {
return false;
}
crate::ape_route_tokio_through_execvp(command);
true
}
fn retryable(command: &std::process::Command, error: &io::Error) -> bool {
if !EXECVP_SHELL_FALLBACK || !is_exec_format_error(error) {
return false;
}
let options = ApeOptions::with_overrides(false, command.get_envs());
resolve_program(
command.get_program(),
command.get_current_dir(),
options.path.as_deref(),
)
.is_some_and(|image| is_ape_file(&image))
}
pub fn spawn_std<T>(
command: &mut std::process::Command,
mut spawn: impl FnMut(&mut std::process::Command) -> io::Result<T>,
) -> io::Result<T> {
let first = retry_while_busy(|| {
let _fork = fork_guard();
spawn(command)
});
match first {
Err(error) if prepare_std_retry(command, &error) => {
let _fork = fork_guard();
spawn(command)
}
result => result,
}
}
#[cfg(feature = "async-process")]
pub fn spawn_tokio<T>(
command: &mut tokio::process::Command,
mut spawn: impl FnMut(&mut tokio::process::Command) -> io::Result<T>,
) -> io::Result<T> {
let first = retry_while_busy(|| {
let _fork = fork_guard();
spawn(command)
});
match first {
Err(error) if prepare_tokio_retry(command, &error) => {
let _fork = fork_guard();
spawn(command)
}
result => result,
}
}
#[cfg(test)]
#[path = "ape_tests.rs"]
mod tests;