Skip to content

Commit

Permalink
feat: Add support for PHP 8.2 (davidcole1340#212)
Browse files Browse the repository at this point in the history
## Small Fixes due to PHP8.2 upgrade:
- Internal PHP `ZendHashmap` changed the way that we access to the bucket ([commit](php/php-src@90b7bde#diff-dca4782c62f10b418ea7193e4641e688ffd7a9c97869f2b1a3a96e28da5653aaL371))
- Internal PHP `ArrayIterator` doesn't support parent `get_iterator` ([commit](php/php-src@15bbf6f#diff-bc002b59b592b4d44c13d898f9dc3ca60b1b1c8505a51a2a3557dfde51dfeb61L273))
  • Loading branch information
ptondereau authored Dec 20, 2022
1 parent 6965f4a commit 11e0998
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/actions/zts/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:8.1-zts
FROM php:8.2-zts

WORKDIR /tmp

Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
php: ["8.0", "8.1"]
php: ["8.0", "8.1", "8.2"]
rust: [stable, nightly]
clang: ["14"]
phpts: [ts, nts]
Expand All @@ -39,6 +39,7 @@ jobs:
php-version: ${{ matrix.php }}
env:
phpts: ${{ matrix.phpts }}
debug: true
- name: Setup Rust
uses: dtolnay/rust-toolchain@master
with:
Expand Down Expand Up @@ -87,17 +88,17 @@ jobs:
- name: Test inline examples
run: cargo test --release --all --all-features
- name: Run rustfmt
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1'
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2'
run: cargo fmt --all -- --check
- name: Run clippy
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1'
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2'
run: cargo clippy --all -- -D warnings
# Docs
- name: Run rustdoc
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1'
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2'
run: cargo rustdoc -- -D warnings
- name: Build with docs stub
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.1'
if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && matrix.php == '8.2'
env:
DOCS_RS: ""
run: cargo clean && cargo build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
os: ["ubuntu-latest"]
php: ["8.0"]
php: ["8.2"]
clang: ["14"]
mdbook: ["latest"]
steps:
Expand Down
15 changes: 12 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use bindgen::RustTarget;
use impl_::Provider;

const MIN_PHP_API_VER: u32 = 20200930;
const MAX_PHP_API_VER: u32 = 20210902;
const MAX_PHP_API_VER: u32 = 20220829;

pub trait PHPProvider<'a>: Sized {
/// Create a new PHP provider.
Expand Down Expand Up @@ -208,10 +208,18 @@ fn check_php_version(info: &PHPInfo) -> Result<()> {
// should get both the `php81` and `php82` flags.
const PHP_81_API_VER: u32 = 20210902;

if version >= PHP_81_API_VER {
const PHP_82_API_VER: u32 = 20220829;

println!("cargo:rustc-cfg=php80");

if (PHP_81_API_VER..PHP_82_API_VER).contains(&version) {
println!("cargo:rustc-cfg=php81");
}

if version >= PHP_82_API_VER {
println!("cargo:rustc-cfg=php82");
}

Ok(())
}

Expand All @@ -233,12 +241,13 @@ fn main() -> Result<()> {
}

println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=Cargo.lock");

// docs.rs runners only have PHP 7.4 - use pre-generated bindings
if env::var("DOCS_RS").is_ok() {
println!("cargo:warning=docs.rs detected - using stub bindings");
println!("cargo:rustc-cfg=php_debug");
println!("cargo:rustc-cfg=php81");
println!("cargo:rustc-cfg=php82");
std::fs::copy("docsrs_bindings.rs", out_path)
.expect("failed to copy docs.rs stub bindings to out directory");
return Ok(());
Expand Down
57 changes: 43 additions & 14 deletions docsrs_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ pub const ZEND_ACC_USE_GUARDS: u32 = 2048;
pub const ZEND_ACC_CONSTANTS_UPDATED: u32 = 4096;
pub const ZEND_ACC_NO_DYNAMIC_PROPERTIES: u32 = 8192;
pub const ZEND_HAS_STATIC_IN_METHODS: u32 = 16384;
pub const ZEND_ACC_REUSE_GET_ITERATOR: u32 = 65536;
pub const ZEND_ACC_RESOLVED_PARENT: u32 = 131072;
pub const ZEND_ACC_RESOLVED_INTERFACES: u32 = 262144;
pub const ZEND_ACC_UNRESOLVED_VARIANCE: u32 = 524288;
Expand All @@ -80,7 +79,7 @@ pub const ZEND_ACC_STRICT_TYPES: u32 = 2147483648;
pub const ZEND_ISEMPTY: u32 = 1;
pub const _ZEND_SEND_MODE_SHIFT: u32 = 25;
pub const _ZEND_IS_VARIADIC_BIT: u32 = 134217728;
pub const ZEND_MODULE_API_NO: u32 = 20210902;
pub const ZEND_MODULE_API_NO: u32 = 20220829;
pub const USING_ZTS: u32 = 0;
pub const MAY_BE_BOOL: u32 = 12;
pub const MAY_BE_ANY: u32 = 1022;
Expand Down Expand Up @@ -219,7 +218,7 @@ pub struct _zend_array {
pub gc: zend_refcounted_h,
pub u: _zend_array__bindgen_ty_1,
pub nTableMask: u32,
pub arData: *mut Bucket,
pub __bindgen_anon_1: _zend_array__bindgen_ty_2,
pub nNumUsed: u32,
pub nNumOfElements: u32,
pub nTableSize: u32,
Expand All @@ -241,6 +240,13 @@ pub struct _zend_array__bindgen_ty_1__bindgen_ty_1 {
pub nIteratorsCount: zend_uchar,
pub _unused2: zend_uchar,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union _zend_array__bindgen_ty_2 {
pub arHash: *mut u32,
pub arData: *mut Bucket,
pub arPacked: *mut zval,
}
pub type HashPosition = u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -420,6 +426,15 @@ pub struct _zend_class_iterator_funcs {
pub type zend_class_iterator_funcs = _zend_class_iterator_funcs;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _zend_class_arrayaccess_funcs {
pub zf_offsetget: *mut zend_function,
pub zf_offsetexists: *mut zend_function,
pub zf_offsetset: *mut zend_function,
pub zf_offsetunset: *mut zend_function,
}
pub type zend_class_arrayaccess_funcs = _zend_class_arrayaccess_funcs;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _zend_serialize_data {
_unused: [u8; 0],
}
Expand Down Expand Up @@ -468,6 +483,7 @@ pub struct _zend_class_mutable_data {
pub default_properties_table: *mut zval,
pub constants_table: *mut HashTable,
pub ce_flags: u32,
pub backed_enum_table: *mut HashTable,
}
pub type zend_class_mutable_data = _zend_class_mutable_data;
#[repr(C)]
Expand Down Expand Up @@ -510,11 +526,11 @@ pub struct _zend_class_entry {
pub default_static_members_count: ::std::os::raw::c_int,
pub default_properties_table: *mut zval,
pub default_static_members_table: *mut zval,
pub static_members_table__ptr: *mut *mut zval,
pub static_members_table__ptr: *mut zval,
pub function_table: HashTable,
pub properties_info: HashTable,
pub constants_table: HashTable,
pub mutable_data__ptr: *mut *mut zend_class_mutable_data,
pub mutable_data__ptr: *mut zend_class_mutable_data,
pub inheritance_cache: *mut zend_inheritance_cache_entry,
pub properties_info_table: *mut *mut _zend_property_info,
pub constructor: *mut zend_function,
Expand All @@ -531,6 +547,7 @@ pub struct _zend_class_entry {
pub __serialize: *mut zend_function,
pub __unserialize: *mut zend_function,
pub iterator_funcs_ptr: *mut zend_class_iterator_funcs,
pub arrayaccess_funcs_ptr: *mut zend_class_arrayaccess_funcs,
pub __bindgen_anon_2: _zend_class_entry__bindgen_ty_2,
pub get_iterator: ::std::option::Option<
unsafe extern "C" fn(
Expand Down Expand Up @@ -728,10 +745,10 @@ pub type zend_object_cast_t = ::std::option::Option<
readobj: *mut zend_object,
retval: *mut zval,
type_: ::std::os::raw::c_int,
) -> ::std::os::raw::c_int,
) -> zend_result,
>;
pub type zend_object_count_elements_t = ::std::option::Option<
unsafe extern "C" fn(object: *mut zend_object, count: *mut zend_long) -> ::std::os::raw::c_int,
unsafe extern "C" fn(object: *mut zend_object, count: *mut zend_long) -> zend_result,
>;
pub type zend_object_get_closure_t = ::std::option::Option<
unsafe extern "C" fn(
Expand All @@ -740,7 +757,7 @@ pub type zend_object_get_closure_t = ::std::option::Option<
fptr_ptr: *mut *mut zend_function,
obj_ptr: *mut *mut zend_object,
check_only: bool,
) -> ::std::os::raw::c_int,
) -> zend_result,
>;
pub type zend_object_get_gc_t = ::std::option::Option<
unsafe extern "C" fn(
Expand All @@ -755,7 +772,7 @@ pub type zend_object_do_operation_t = ::std::option::Option<
result: *mut zval,
op1: *mut zval,
op2: *mut zval,
) -> ::std::os::raw::c_int,
) -> zend_result,
>;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -903,13 +920,13 @@ pub struct _zend_op_array {
pub required_num_args: u32,
pub arg_info: *mut zend_arg_info,
pub attributes: *mut HashTable,
pub T: u32,
pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void,
pub cache_size: ::std::os::raw::c_int,
pub last_var: ::std::os::raw::c_int,
pub T: u32,
pub last: u32,
pub opcodes: *mut zend_op,
pub run_time_cache__ptr: *mut *mut *mut ::std::os::raw::c_void,
pub static_variables_ptr__ptr: *mut *mut HashTable,
pub static_variables_ptr__ptr: *mut HashTable,
pub static_variables: *mut HashTable,
pub vars: *mut *mut zend_string,
pub refcount: *mut u32,
Expand Down Expand Up @@ -943,6 +960,8 @@ pub struct _zend_internal_function {
pub required_num_args: u32,
pub arg_info: *mut zend_internal_arg_info,
pub attributes: *mut HashTable,
pub T: u32,
pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void,
pub handler: zif_handler,
pub module: *mut _zend_module_entry,
pub reserved: [*mut ::std::os::raw::c_void; 6usize],
Expand Down Expand Up @@ -970,6 +989,8 @@ pub struct _zend_function__bindgen_ty_1 {
pub required_num_args: u32,
pub arg_info: *mut zend_arg_info,
pub attributes: *mut HashTable,
pub T: u32,
pub run_time_cache__ptr: *mut *mut ::std::os::raw::c_void,
}
#[repr(C)]
pub struct _zend_execute_data {
Expand Down Expand Up @@ -998,6 +1019,12 @@ extern "C" {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct zend_atomic_bool_s {
pub value: u8,
}
pub type zend_atomic_bool = zend_atomic_bool_s;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _zend_stack {
pub size: ::std::os::raw::c_int,
pub top: ::std::os::raw::c_int,
Expand Down Expand Up @@ -1073,8 +1100,8 @@ pub struct _zend_executor_globals {
pub in_autoload: *mut HashTable,
pub full_tables_cleanup: bool,
pub no_extensions: bool,
pub vm_interrupt: bool,
pub timed_out: bool,
pub vm_interrupt: zend_atomic_bool,
pub timed_out: zend_atomic_bool,
pub hard_timeout: zend_long,
pub regular_list: HashTable,
pub persistent_list: HashTable,
Expand Down Expand Up @@ -1118,6 +1145,8 @@ pub struct _zend_executor_globals {
pub record_errors: bool,
pub num_errors: u32,
pub errors: *mut *mut zend_error_info,
pub filename_override: *mut zend_string,
pub lineno_override: zend_long,
pub reserved: [*mut ::std::os::raw::c_void; 6usize],
}
pub type zend_module_entry = _zend_module_entry;
Expand Down
2 changes: 1 addition & 1 deletion src/builders/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl ClassBuilder {
// disable serialization if the class has an associated object
if self.object_override.is_some() {
cfg_if::cfg_if! {
if #[cfg(php81)] {
if #[cfg(any(php81, php82))] {
class.ce_flags |= ClassFlags::NotSerializable.bits();
} else {
class.serialize = Some(crate::ffi::zend_class_serialize_deny);
Expand Down
13 changes: 8 additions & 5 deletions src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
use bitflags::bitflags;

#[cfg(not(php82))]
use crate::ffi::ZEND_ACC_REUSE_GET_ITERATOR;
use crate::ffi::{
CONST_CS, CONST_DEPRECATED, CONST_NO_FILE_CACHE, CONST_PERSISTENT, IS_ARRAY, IS_CALLABLE,
IS_CONSTANT_AST, IS_DOUBLE, IS_FALSE, IS_LONG, IS_MIXED, IS_NULL, IS_OBJECT, IS_PTR,
Expand All @@ -14,10 +16,10 @@ use crate::ffi::{
ZEND_ACC_IMPLICIT_ABSTRACT_CLASS, ZEND_ACC_INTERFACE, ZEND_ACC_LINKED, ZEND_ACC_NEARLY_LINKED,
ZEND_ACC_NEVER_CACHE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PRELOADED, ZEND_ACC_PRIVATE,
ZEND_ACC_PROMOTED, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_RESOLVED_INTERFACES,
ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_REUSE_GET_ITERATOR,
ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES, ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT,
ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE, ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS,
ZEND_ACC_VARIADIC, ZEND_HAS_STATIC_IN_METHODS, Z_TYPE_FLAGS_SHIFT, _IS_BOOL,
ZEND_ACC_RESOLVED_PARENT, ZEND_ACC_RETURN_REFERENCE, ZEND_ACC_STATIC, ZEND_ACC_STRICT_TYPES,
ZEND_ACC_TOP_LEVEL, ZEND_ACC_TRAIT, ZEND_ACC_TRAIT_CLONE, ZEND_ACC_UNRESOLVED_VARIANCE,
ZEND_ACC_USES_THIS, ZEND_ACC_USE_GUARDS, ZEND_ACC_VARIADIC, ZEND_HAS_STATIC_IN_METHODS,
Z_TYPE_FLAGS_SHIFT, _IS_BOOL,
};

use std::{convert::TryFrom, fmt::Display};
Expand Down Expand Up @@ -75,13 +77,14 @@ bitflags! {
const ConstantsUpdated = ZEND_ACC_CONSTANTS_UPDATED;
const NoDynamicProperties = ZEND_ACC_NO_DYNAMIC_PROPERTIES;
const HasStaticInMethods = ZEND_HAS_STATIC_IN_METHODS;
#[cfg(not(php82))]
const ReuseGetIterator = ZEND_ACC_REUSE_GET_ITERATOR;
const ResolvedParent = ZEND_ACC_RESOLVED_PARENT;
const ResolvedInterfaces = ZEND_ACC_RESOLVED_INTERFACES;
const UnresolvedVariance = ZEND_ACC_UNRESOLVED_VARIANCE;
const NearlyLinked = ZEND_ACC_NEARLY_LINKED;

#[cfg(php81)]
#[cfg(any(php81,php82))]
const NotSerializable = crate::ffi::ZEND_ACC_NOT_SERIALIZABLE;
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/types/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,11 +531,18 @@ impl<'a> Iter<'a> {
///
/// * `ht` - The hashtable to iterate.
pub fn new(ht: &'a ZendHashTable) -> Self {
Self {
#[cfg(not(php82))]
return Self {
ht,
pos: NonNull::new(ht.arData),
end: NonNull::new(unsafe { ht.arData.offset(ht.nNumUsed as isize) }),
}
};
#[cfg(php82)]
return Self {
ht,
pos: NonNull::new(unsafe { ht.__bindgen_anon_1.arData }),
end: NonNull::new(unsafe { ht.__bindgen_anon_1.arData.offset(ht.nNumUsed as isize) }),
};
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/types/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ impl ZendStr {
/// assert_eq!(s.len(), 13);
/// ```
pub fn len(&self) -> usize {
self.len as usize
self.len
}

/// Returns true if the string is empty, false otherwise.
Expand Down
2 changes: 1 addition & 1 deletion src/zend/ex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl ExecuteData {
#[doc(hidden)]
unsafe fn zend_call_var_num(&self, n: isize) -> *mut Zval {
let ptr = self as *const Self as *mut Zval;
ptr.offset(Self::zend_call_frame_slot() + n as isize)
ptr.offset(Self::zend_call_frame_slot() + n)
}

/// Translation of macro `ZEND_CALL_FRAME_SLOT`
Expand Down

0 comments on commit 11e0998

Please sign in to comment.