Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ Agents must follow these rules exactly:
- operation name
- shape/dtype context where possible

### Binding Maintenance (Type Intelligence)
### FFI Method Annotations (Static Analysis & IDE Support)

- Whenever a new FFI function is exported in Rust (`extern "C"`), you **MUST** update `src/FFI/Bindings.php`.
- Add the method signature to the `Bindings` interface to match the C header.
- This ensures IDEs (VS Code, PHPStorm) and static analyzers provide correct autocomplete and type checking for `$ffi->method_name(...)` calls.
- Whenever a new C function is exported in Rust (`extern "C"`), you **MUST** add a `@method` PHPDoc annotation to the class-level docblock in `src/FFI/Lib.php`.
- The annotation must mirror the C function signature using PHP types (`CData`, `int`, `float`, `bool`, `?CData`, etc.).
- This ensures IDEs (VS Code, PHPStorm) and static analyzers (PHPStan) provide correct autocomplete and type checking for `Lib::get()->method_name(...)` calls.
- Failure to do this degrades the developer experience and makes the codebase harder to maintain.

## API Design Rules
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ When modifying Rust code:
- Document all public FFI functions
- Add tests for new FFI functions in `rust/tests/`
- Ensure memory safety - use safe Rust where possible
- Update FFI bindings in `src/FFI/Bindings.php` when adding new functions
- Add `@method` annotations to `src/FFI/Lib.php` when adding new FFI functions

Example FFI function:
```rust
Expand Down
2 changes: 1 addition & 1 deletion phpstan.dist.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ parameters:
- tests
treatPhpDocTypesAsCertain: false
universalObjectCratesClasses:
- FFI\CData
- FFI\CData
8 changes: 4 additions & 4 deletions src/ArrayMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ public function toCData(): CData
return $this->cachedStruct;
}

$ffi = Lib::get();
$this->cachedShapeC = Lib::createShapeArray($this->shape);
$this->cachedStridesC = Lib::createShapeArray($this->strides);
$this->cachedStruct = $ffi->new('struct ArrayMetadata', false);
$lib = Lib::get();
$this->cachedShapeC = $lib->createCArray('size_t', $this->shape);
$this->cachedStridesC = $lib->createCArray('size_t', $this->strides);
$this->cachedStruct = $lib->new('struct ArrayMetadata', false);
$this->cachedStruct->offset = $this->offset;
$this->cachedStruct->shape = \FFI::addr($this->cachedShapeC[0]);
$this->cachedStruct->strides = \FFI::addr($this->cachedStridesC[0]);
Expand Down
12 changes: 6 additions & 6 deletions src/DType.php
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,10 @@ public function maxValue(): Complex|float|int
*/
public function createCValue(bool|Complex|float|int|null $value = null): CData
{
$ffi = Lib::get();
$lib = Lib::get();

if ($this->isComplex()) {
$cArray = $ffi->new("{$this->ffiType()}[2]");
$cArray = $lib->new("{$this->ffiType()}[2]");
if (null !== $value) {
$complex = $value instanceof Complex ? $value : new Complex((float) $value);
$cArray[0] = $complex->real;
Expand All @@ -290,7 +290,7 @@ public function createCValue(bool|Complex|float|int|null $value = null): CData
return $cArray;
}

$cValue = $ffi->new($this->ffiType());
$cValue = $lib->new($this->ffiType());

if (null !== $value) {
$cValue->cdata = $this->isBool() ? ($value ? 1 : 0) : $value;
Expand All @@ -313,10 +313,10 @@ public function createCValue(bool|Complex|float|int|null $value = null): CData
*/
public function createCArray(int $elementCount, array $values = []): CData
{
$ffi = Lib::get();
$lib = Lib::get();

if (!empty($values)) {
$cArray = $ffi->new("{$this->ffiType()}[".\count($values).']');
$cArray = $lib->new("{$this->ffiType()}[".\count($values).']');
foreach ($values as $i => $value) {
$cArray[$i] = $value;
}
Expand All @@ -326,7 +326,7 @@ public function createCArray(int $elementCount, array $values = []): CData

$primitiveCount = $this->isComplex() ? $elementCount * 2 : $elementCount;

return $ffi->new("{$this->ffiType()}[{$primitiveCount}]");
return $lib->new("{$this->ffiType()}[{$primitiveCount}]");
}

/**
Expand Down
552 changes: 0 additions & 552 deletions src/FFI/Bindings.php

This file was deleted.

370 changes: 246 additions & 124 deletions src/FFI/Lib.php

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/Traits/CanBePrinted.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ public function __toString(): string
{
$options = self::$printOptions;

$ffi = Lib::get();
$buffer = $ffi->new('char[8192]');
$lib = Lib::get();
$buffer = $lib->new('char[8192]');

$meta = $this->meta()->toCData();
$len = $ffi->ndarray_to_string(
$len = $lib->ndarray_to_string(
$this->handle,
Lib::addr($meta),
$buffer,
Expand All @@ -45,8 +45,8 @@ public function __toString(): string
}

if ($len > 8192) {
$newBuffer = $ffi->new("char[{$len}]");
$len = $ffi->ndarray_to_string(
$newBuffer = $lib->new("char[{$len}]");
$len = $lib->ndarray_to_string(
$this->handle,
Lib::addr($meta),
$newBuffer,
Expand Down
Loading
Loading