Skip to main content

luaur_web/records/
demo_file_resolver.rs

1//! Port of `DemoFileResolver : Luau::FileResolver` (`CLI/src/Web.cpp:16-46`).
2//!
3//! The luau.org/demo file resolver. Like the project's `NullFileResolver`, it is
4//! a concrete `FileResolver` subclass: `#[repr(C)]` with `base: FileResolver`
5//! first so a `*mut FileResolver` (the vtable receiver) can be cast back to
6//! `*mut DemoFileResolver` to reach `source`. The four virtuals are wired to the
7//! free `demo_file_resolver_*` thunks; each delegates to the inherent methods in
8//! `methods/`.
9//!
10//! C++ member: `std::unordered_map<ModuleName, std::string> source;` — ported as
11//! a typed `HashMap<ModuleName, String>` (no untyped JSON).
12
13use alloc::string::String;
14use luaur_analysis::records::file_resolver::{FileResolver, FileResolverVtable};
15use luaur_analysis::records::module_info::ModuleInfo;
16use luaur_analysis::records::source_code::SourceCode;
17use luaur_analysis::records::type_check_limits::TypeCheckLimits;
18use luaur_analysis::type_aliases::module_name_file_resolver::ModuleName;
19use luaur_ast::records::ast_expr::AstExpr;
20use std::collections::HashMap;
21
22#[repr(C)]
23pub struct DemoFileResolver {
24    pub base: FileResolver,
25    pub source: HashMap<ModuleName, String>,
26}
27
28/// `std::optional<SourceCode> readSource(const ModuleName&)` thunk.
29///
30/// # Safety
31/// `this` must point at the `base` subobject of a live `DemoFileResolver`.
32pub(crate) unsafe fn demo_file_resolver_read_source_thunk(
33    this: *mut FileResolver,
34    name: &ModuleName,
35) -> Option<SourceCode> {
36    let this = this as *mut DemoFileResolver;
37    (*this).read_source(name)
38}
39
40/// `std::optional<ModuleInfo> resolveModule(const ModuleInfo*, AstExpr*, const TypeCheckLimits&)` thunk.
41///
42/// # Safety
43/// `this` must point at the `base` subobject of a live `DemoFileResolver`.
44pub(crate) unsafe fn demo_file_resolver_resolve_module_thunk(
45    this: *mut FileResolver,
46    context: *const ModuleInfo,
47    expr: *mut AstExpr,
48    limits: &TypeCheckLimits,
49) -> Option<ModuleInfo> {
50    let this = this as *const DemoFileResolver;
51    (*this).resolve_module(context, expr, limits)
52}
53
54/// `std::string getHumanReadableModuleName(const ModuleName&) const` thunk.
55///
56/// # Safety
57/// `this` must point at the `base` subobject of a live `DemoFileResolver`.
58pub(crate) unsafe fn demo_file_resolver_get_human_readable_module_name_thunk(
59    this: *const FileResolver,
60    name: &ModuleName,
61) -> String {
62    let this = this as *const DemoFileResolver;
63    (*this).get_human_readable_module_name(name)
64}
65
66/// `std::optional<std::string> getEnvironmentForModule(const ModuleName&) const` thunk.
67///
68/// # Safety
69/// `this` must point at the `base` subobject of a live `DemoFileResolver`.
70pub(crate) unsafe fn demo_file_resolver_get_environment_for_module_thunk(
71    this: *const FileResolver,
72    name: &ModuleName,
73) -> Option<String> {
74    let this = this as *const DemoFileResolver;
75    (*this).get_environment_for_module(name)
76}
77
78impl DemoFileResolver {
79    pub fn new() -> Self {
80        let vtable = FileResolverVtable {
81            read_source: demo_file_resolver_read_source_thunk,
82            resolve_module: demo_file_resolver_resolve_module_thunk,
83            get_human_readable_module_name: demo_file_resolver_get_human_readable_module_name_thunk,
84            get_environment_for_module: demo_file_resolver_get_environment_for_module_thunk,
85        };
86
87        DemoFileResolver {
88            base: FileResolver {
89                vtable,
90                require_suggester: None,
91            },
92            source: HashMap::new(),
93        }
94    }
95}
96
97impl Default for DemoFileResolver {
98    fn default() -> Self {
99        Self::new()
100    }
101}