From fcef25f6ef36287a4984ffdaab39df84f5aceeba Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 21 Jun 2026 15:49:24 +0900 Subject: refactor(php-shim): split lib.rs --- crates/shirabe-php-shim/src/runtime.rs | 416 +++++++++++++++++++++++++++++++++ 1 file changed, 416 insertions(+) create mode 100644 crates/shirabe-php-shim/src/runtime.rs (limited to 'crates/shirabe-php-shim/src/runtime.rs') diff --git a/crates/shirabe-php-shim/src/runtime.rs b/crates/shirabe-php-shim/src/runtime.rs new file mode 100644 index 0000000..cc63af6 --- /dev/null +++ b/crates/shirabe-php-shim/src/runtime.rs @@ -0,0 +1,416 @@ +use crate::PhpMixed; +use indexmap::IndexMap; + +pub const PHP_VERSION_ID: i64 = 80100; +pub const PHP_VERSION: &str = "8.1.0"; + +pub const PHP_MAJOR_VERSION: i64 = 8; +pub const PHP_MINOR_VERSION: i64 = 1; +pub const PHP_RELEASE_VERSION: i64 = 0; + +pub const PHP_WINDOWS_VERSION_MAJOR: i64 = 0; +pub const PHP_WINDOWS_VERSION_MINOR: i64 = 0; +pub const PHP_WINDOWS_VERSION_BUILD: i64 = 0; + +pub const PHP_INT_MAX: i64 = i64::MAX; +pub const PHP_INT_MIN: i64 = i64::MIN; +pub const PHP_INT_SIZE: i64 = 8; + +pub const HHVM_VERSION: Option<&str> = None; + +pub const E_ALL: i64 = 32767; +pub const E_WARNING: i64 = 2; +pub const E_NOTICE: i64 = 8; +pub const E_USER_WARNING: i64 = 512; +pub const E_USER_NOTICE: i64 = 1024; +pub const E_DEPRECATED: i64 = 8192; +pub const E_USER_DEPRECATED: i64 = 16384; + +pub const INFO_GENERAL: i64 = 1; +pub const PHP_BINARY: &str = ""; + +// NOTE: &str matching in const expression does not compile for now. +pub const PHP_OS: &str = match std::env::consts::OS.as_bytes() { + b"linux" => "Linux", + b"macos" => "Darwin", + b"windows" => "WINNT", + b"freebsd" => "FreeBSD", + b"openbsd" => "OpenBSD", + b"netbsd" => "NetBSD", + b"dragonfly" => "DragonFly", + b"solaris" | b"illumos" => "SunOS", + _ => std::env::consts::OS, +}; + +pub fn constant(_name: &str) -> PhpMixed { + todo!() +} + +// Models the constants defined in a standard modern PHP CLI environment on a +// non-Windows platform with the common extensions loaded (curl, openssl, json). +// Windows-only, HHVM and Composer-bootstrap constants are reported undefined. +pub fn defined(name: &str) -> bool { + matches!( + name, + "CURLMOPT_MAX_HOST_CONNECTIONS" + | "CURL_HTTP_VERSION_2_0" + | "CURL_HTTP_VERSION_3" + | "CURL_VERSION_HTTP2" + | "CURL_VERSION_HTTP3" + | "CURL_VERSION_HTTPS_PROXY" + | "CURL_VERSION_LIBZ" + | "CURL_VERSION_ZSTD" + | "GLOB_BRACE" + | "JSON_ERROR_UTF8" + | "OPENSSL_VERSION_TEXT" + | "PHP_BINARY" + | "SIGINT" + | "STDIN" + | "STDOUT" + ) +} + +pub fn method_exists(_object: &PhpMixed, _method_name: &str) -> bool { + todo!() +} + +// Models the classes available in a standard PHP CLI environment running Composer: +// the common bundled extensions (zip, Phar) plus Composer's own runtime classes. +pub fn class_exists(name: &str) -> bool { + matches!(name, "Composer\\InstalledVersions" | "Phar" | "ZipArchive") +} + +// Models the functions available in a standard modern PHP CLI environment on a +// non-Windows platform with the common extensions loaded (curl, mbstring, iconv, +// zlib, posix, pcntl). Opt-in or Windows-only functions are reported absent. +pub fn function_exists(name: &str) -> bool { + matches!( + name, + "bzcompress" + | "cli_set_process_title" + | "curl_multi_exec" + | "curl_multi_init" + | "curl_multi_setopt" + | "curl_share_init" + | "curl_strerror" + | "date_default_timezone_get" + | "date_default_timezone_set" + | "disk_free_space" + | "exec" + | "filter_var" + | "getmypid" + | "gzcompress" + | "iconv" + | "ini_set" + | "json_decode" + | "mb_check_encoding" + | "mb_convert_encoding" + | "mb_strlen" + | "pcntl_async_signals" + | "pcntl_signal" + | "php_strip_whitespace" + | "php_uname" + | "posix_geteuid" + | "posix_getpwuid" + | "posix_getuid" + | "posix_isatty" + | "proc_open" + | "putenv" + | "shell_exec" + | "stream_isatty" + | "symlink" + ) +} + +/// PHP `PHP_OS_FAMILY` constant: the family of the host OS. +/// One of "Windows", "BSD", "Darwin", "Solaris", "Linux", "Unknown". +pub fn php_os_family() -> &'static str { + match std::env::consts::OS { + "linux" | "android" => "Linux", + "macos" | "ios" => "Darwin", + "windows" => "Windows", + "freebsd" | "dragonfly" | "netbsd" | "openbsd" => "BSD", + "solaris" | "illumos" => "Solaris", + _ => "Unknown", + } +} + +// Models the extensions loaded in a standard PHP CLI environment running Composer. +// Opt-in extensions (apcu, xdebug, ionCube, uopz) are reported absent. +pub fn extension_loaded(name: &str) -> bool { + matches!( + name, + "Phar" + | "curl" + | "filter" + | "hash" + | "iconv" + | "intl" + | "mbstring" + | "openssl" + | "zip" + | "zlib" + ) +} + +// Models the configuration of a standard PHP CLI environment. Settings belonging +// to extensions that are not loaded (apcu, uopz, xdebug) are not registered, so +// PHP's ini_get returns false (None) for them. +pub fn ini_get(option: &str) -> Option { + match option { + "allow_url_fopen" => Some("1".to_string()), + "default_socket_timeout" => Some("60".to_string()), + "disable_functions" => Some(String::new()), + "mbstring.func_overload" => Some("0".to_string()), + "memory_limit" => Some("-1".to_string()), + "open_basedir" => Some(String::new()), + _ => None, + } +} + +pub fn get_loaded_extensions() -> Vec { + todo!() +} + +pub fn phpversion(_extension: &str) -> Option { + todo!() +} + +// TODO(php-runtime): the callback should be registered in PHP runtime. +pub fn set_error_handler(_callback: fn(i64, &str, &str, i64) -> bool) {} + +pub fn debug_backtrace() -> Vec> { + todo!() +} + +/// Equivalent to PHP `include $file;` +pub fn include_file(file: &str) -> PhpMixed { + let _ = file; + todo!() +} + +pub fn spl_autoload_register( + callback: Box PhpMixed + Send + Sync>, + throw: bool, + prepend: bool, +) -> bool { + let _ = (callback, throw, prepend); + todo!() +} + +pub fn spl_autoload_unregister(callback: Box PhpMixed + Send + Sync>) -> bool { + let _ = callback; + todo!() +} + +static ERROR_REPORTING_LEVEL: std::sync::atomic::AtomicI64 = + std::sync::atomic::AtomicI64::new(E_ALL); + +pub fn error_reporting(level: Option) -> i64 { + let old = ERROR_REPORTING_LEVEL.load(std::sync::atomic::Ordering::Relaxed); + if let Some(level) = level { + ERROR_REPORTING_LEVEL.store(level, std::sync::atomic::Ordering::Relaxed); + } + old +} + +pub fn spl_autoload_functions() -> Vec { + todo!() +} + +pub fn version_compare(_v1: &str, _v2: &str, _op: &str) -> bool { + todo!() +} + +pub fn version_compare_2(_v1: &str, _v2: &str) -> i64 { + todo!() +} + +// TODO(php-runtime): the previous handler should be restored in the PHP runtime. +// Paired with set_error_handler, which is a no-op in this shim. +pub fn restore_error_handler() {} + +pub fn spl_object_hash(_object: &T) -> String { + todo!() +} + +pub fn spl_object_hash_process(_object: &T) -> String { + todo!() +} + +pub fn php_uname(mode: &str) -> String { + match mode { + // sysname, as reported by uname(2). On Windows PHP returns "Windows NT", + // which differs from PHP_OS. + "s" => match std::env::consts::OS { + "linux" => "Linux", + "macos" => "Darwin", + "windows" => "Windows NT", + "freebsd" => "FreeBSD", + "netbsd" => "NetBSD", + "openbsd" => "OpenBSD", + "dragonfly" => "DragonFly", + "solaris" => "SunOS", + other => other, + } + .to_string(), + // TODO(phase-c): use libc? + // release, as reported by uname(2). On Linux this matches the contents + // of /proc/sys/kernel/osrelease. + "r" => std::fs::read_to_string("/proc/sys/kernel/osrelease") + .map(|s| s.trim_end().to_string()) + .unwrap_or_default(), + _ => todo!(), + } +} + +pub fn trigger_error(_message: &str, _error_level: i64) { + todo!() +} + +pub fn trigger_deprecation(_package: &str, _version: &str, _message: &str, _arg: &str) { + todo!() +} + +pub fn usleep(_microseconds: u64) { + std::thread::sleep(std::time::Duration::from_micros(_microseconds)); +} + +/// Equivalent to PHP's __DIR__ magic constant +pub fn php_dir() -> String { + todo!() +} + +pub fn dir() -> String { + todo!() +} + +/// Equivalent to PHP's `require ` returning the file's return value +pub fn require_php_file(_filename: &str) -> PhpMixed { + todo!() +} + +pub fn php_require(_file: &str) -> PhpMixed { + todo!() +} + +pub fn r#eval(_code: &str) -> PhpMixed { + todo!() +} + +pub fn memory_get_usage() -> i64 { + todo!() +} + +pub fn memory_get_peak_usage(_real_usage: bool) -> i64 { + todo!() +} + +pub fn call_user_func(_callback: &str, _args: &[PhpMixed]) -> T +where + T: From, +{ + todo!() +} + +pub fn call_user_func_array(_callback: &str, _args: &PhpMixed) -> PhpMixed { + todo!() +} + +pub fn call_php_callable(_callback: &PhpMixed, _args: &[PhpMixed]) -> PhpMixed { + todo!() +} + +// The shim does not raise PHP-level errors, so there is never a last error. +pub fn error_get_last() -> Option> { + None +} + +pub fn globals_get(_name: &str) -> PhpMixed { + todo!() +} + +pub fn globals_set(_name: &str, _value: PhpMixed) { + todo!() +} + +pub fn clone(_value: T) -> T { + todo!() +} + +pub fn ini_set(_varname: &str, _value: &str) -> Option { + todo!() +} + +thread_local! { + static SHUTDOWN_FUNCTIONS: std::cell::RefCell>> = + const { std::cell::RefCell::new(Vec::new()) }; +} + +pub fn register_shutdown_function(callback: Box) { + SHUTDOWN_FUNCTIONS.with(|f| f.borrow_mut().push(callback)); +} + +// Runs the registered shutdown functions in registration order, mirroring PHP +// executing them at the end of the request. Must be invoked at every process exit. +pub fn run_shutdown_functions() { + let functions = SHUTDOWN_FUNCTIONS.with(|f| std::mem::take(&mut *f.borrow_mut())); + for callback in &functions { + callback(); + } +} + +pub fn composer_dev_warning_time() -> i64 { + todo!() +} + +pub fn gc_collect_cycles() -> i64 { + // Rust has no cycle collector; nothing is collected. + 0 +} + +pub fn gc_disable() { + // Rust has no cycle collector to disable. +} + +pub fn gc_enable() { + // Rust has no cycle collector to enable. +} + +pub fn react_promise_resolve(_value: PhpMixed) -> PhpMixed { + todo!() +} + +pub fn ioncube_loader_iversion() -> i64 { + todo!() +} + +pub fn ioncube_loader_version() -> String { + todo!() +} + +pub fn phpinfo(_what: i64) { + todo!() +} + +pub fn exit(status: i64) -> ! { + // PHP runs registered shutdown functions before terminating. + run_shutdown_functions(); + std::process::exit(status as i32); +} + +pub fn sapi_windows_vt100_support(_resource: &crate::PhpResource) -> bool { + todo!() +} + +pub fn sapi_windows_cp_get(_kind: Option<&str>) -> i64 { + todo!() +} + +pub fn sapi_windows_cp_set(_codepage: i64) -> bool { + todo!() +} + +pub fn sapi_windows_cp_conv(_in_codepage: i64, _out_codepage: i64, _subject: &str) -> String { + todo!() +} -- cgit v1.3.1