Skip to main content

memlink_runtime/resolver/
local.rs

1//! Local file resolver for shared libraries.
2
3use std::fs::File;
4use std::io::Read;
5use std::path::Path;
6
7use crate::error::{Error, Result};
8use crate::resolver::{ArtifactHandle, ModuleRef, ModuleResolver};
9
10pub struct LocalResolver;
11
12impl LocalResolver {
13    pub fn new() -> Self {
14        LocalResolver
15    }
16}
17
18impl Default for LocalResolver {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl ModuleResolver for LocalResolver {
25    fn resolve(&self, reference: ModuleRef) -> Result<ArtifactHandle> {
26        let ModuleRef::LocalPath(path) = reference;
27
28        if !path.exists() {
29            return Err(Error::FileNotFound(path));
30        }
31
32        validate_extension(&path)?;
33        validate_shared_library(&path)?;
34
35        Ok(ArtifactHandle::Local(path))
36    }
37}
38
39fn validate_extension(path: &Path) -> Result<()> {
40    let extension = path
41        .extension()
42        .and_then(|ext| ext.to_str())
43        .unwrap_or("");
44
45    match extension.to_lowercase().as_str() {
46        "so" | "dll" | "dylib" => Ok(()),
47        _ => Err(Error::InvalidModuleFormat(format!(
48            "Invalid extension '.{}': expected .so, .dll, or .dylib",
49            extension
50        ))),
51    }
52}
53
54pub fn validate_shared_library(path: &Path) -> Result<()> {
55    let mut file = File::open(path).map_err(|e| {
56        Error::InvalidModuleFormat(format!("Failed to open file: {}", e))
57    })?;
58
59    let mut buffer = [0u8; 16];
60    file.read_exact(&mut buffer).map_err(|e| {
61        Error::InvalidModuleFormat(format!("Failed to read file header: {}", e))
62    })?;
63
64    if buffer[0..4] == [0x7f, 0x45, 0x4c, 0x46] {
65        return Ok(());
66    }
67
68    if buffer[0..4] == [0xce, 0xfa, 0xed, 0xfe]
69        || buffer[0..4] == [0xfe, 0xed, 0xfa, 0xce]
70        || buffer[0..4] == [0xcf, 0xfa, 0xed, 0xfe]
71        || buffer[0..4] == [0xfe, 0xed, 0xfa, 0xcf]
72    {
73        return Ok(());
74    }
75
76    if buffer[0..2] == [0x4d, 0x5a] {
77        return Ok(());
78    }
79
80    Err(Error::InvalidModuleFormat(format!(
81        "File '{}' does not have valid shared library magic bytes. Found: {:02x?}",
82        path.display(),
83        &buffer[0..4]
84    )))
85}