Skip to content

Commit

Permalink
WIP. Improve namespaces and code layout.
Browse files Browse the repository at this point in the history
  • Loading branch information
onethumb committed Dec 27, 2024
1 parent aa430ad commit aa55d31
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 207 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,22 @@ $crc64Nvme = Crc64\Ffi::fromCode(
### Using the CRC-64/NVME FFI object

#### Calculate CRC-64/NVME checksums:

```php
use Awesomized\Checksums\Crc64;

/** @var \FFI $crc64Fast */

// calculate the checksum of a string
$checksum = Crc64\Nvme::calculate(
crc64Nvme: $crc64Fast,
ffi: $crc64Fast,
string: 'hello, world!'
); // f8046e40c403f1d0

// calculate the checksum of a file, which will chunk through the file optimally,
// limiting RAM usage and maximizing throughput
$checksum = Crc64\Nvme::calculateFile(
crc64Nvme: $crc64Fast,
ffi: $crc64Fast,
filename: 'path/to/hello-world'
); // f8046e40c403f1d0
```
Expand Down
8 changes: 3 additions & 5 deletions cli/calculate.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@

require __DIR__ . '/../vendor/autoload.php';

$ffi = Crc64\Ffi::fromHeaderFile(
headerFile: Crc64\Ffi::whichHeaderFile(),
);
$ffi = Crc64\Ffi::fromHeaderFile();

if (is_readable($argv[1])) {
echo Crc64\Nvme::calculateFile(
crc64Nvme: $ffi,
ffi: $ffi,
filename: $argv[1],
) . PHP_EOL;

exit(0);
}

echo Crc64\Nvme::calculate(
crc64Nvme: $ffi,
ffi: $ffi,
string: $argv[1],
) . PHP_EOL;
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
},
"autoload": {
"psr-4": {
"Awesomized\\Checksums\\Crc64\\": "src/"
"Awesomized\\Checksums\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Awesomized\\Checksums\\Crc64\\tests\\": "tests/"
"Awesomized\\Checksums\\tests\\": "tests/"
}
},
"require-dev": {
Expand Down
24 changes: 12 additions & 12 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion preload.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

use Awesomized\Checksums\Crc64;

require 'src/Ffi.php';
require 'src/FfiInterface.php';
require 'src/FfiTrait.php';
require 'src/Crc64/Ffi.php';

\FFI::load(
Crc64\Ffi::whichHeaderFile(),
Expand Down
135 changes: 7 additions & 128 deletions src/Crc64/Ffi.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,147 +2,26 @@

declare(strict_types=1);

namespace Awesomized\Checksums;
namespace Awesomized\Checksums\Crc64;

use FFI\Exception;
use FFI\ParserException;
use Awesomized\Checksums;

/**
* FFI helper.
*
* Just wraps the FFI functionality to provide a more convenient API, documentation, and defaults.
* FFI (Foreign Function Interface) helper for CRC-64/NVME checksum calculations.
*/
final class Ffi
final class Ffi implements Checksums\FfiInterface
{
private const string SCOPE_DEFAULT = 'CRC64NVME';
use Checksums\FfiTrait;

/**
* @var array<string, \FFI>
*/
private static array $ffis = [];
public const string SCOPE_DEFAULT = 'CRC64NVME';

/**
* Creates a new FFI instance from the given C declarations and library name.
*
* @param string $code The C declarations
* @param string|null $library The name of the shared library
*
* @throws ParserException
* @throws Exception
*/
public static function fromCode(
string $code,
?string $library = null,
): \FFI {
$id = $code . $library;

if (isset(self::$ffis[$id])) {
return self::$ffis[$id];
}

$ffi = \FFI::cdef(
code: $code,
lib: $library,
);

/**
* Verify that the FFI instance is valid by calling digest_new() method before caching.
*
* @psalm-suppress UndefinedMethod - FFI method, can't tell if it's defined or not
*/
// @phpstan-ignore-next-line
$ffi->digest_new();

return self::$ffis[$id] = $ffi;
}

/**
* Creates a new FFI instance from the given preloaded scope.
*
* @link https://www.php.net/manual/en/opcache.preloading.php
* @link https://www.php.net/manual/en/ffi.examples-complete.php
*
* @param string $ffiScopeName The FFI_SCOPE used during preloading
*/
public static function fromPreloadScope(
string $ffiScopeName = self::SCOPE_DEFAULT,
): \FFI {
$id = $ffiScopeName;

if (isset(self::$ffis[$id])) {
return self::$ffis[$id];
}

$ffi = \FFI::scope(
name: $ffiScopeName,
);

/**
* Verify that the FFI instance is valid by calling digest_new() method before caching.
*
* @psalm-suppress UndefinedMethod - FFI method, can't tell if it's defined or not
*/
// @phpstan-ignore-next-line
$ffi->digest_new();

return self::$ffis[$id] = $ffi;
}

/**
* Creates a new FFI instance from the given C header file.
*
* @param string $headerFile The C header file
*
* @throws \InvalidArgumentException
*/
public static function fromHeaderFile(
string $headerFile = '',
): \FFI {
if ('' === $headerFile) {
$headerFile = self::whichHeaderFile();
}

$id = $headerFile;

if (isset(self::$ffis[$id])) {
return self::$ffis[$id];
}

$ffi = \FFI::load(
filename: $headerFile,
);

if (null === $ffi) {
throw new \InvalidArgumentException(
message: 'Failed to load the FFI instance from the header file ' . $headerFile,
);
}

/**
* Verify that the FFI instance is valid by calling digest_new() method before caching.
*
* @psalm-suppress UndefinedMethod - FFI method, can't tell if it's defined or not
*/
// @phpstan-ignore-next-line
$ffi->digest_new();

return self::$ffis[$id] = $ffi;
}

/**
* Attempts to determine the correct header file for the current platform.
*
* @return string The path to the header file
*/
public static function whichHeaderFile(): string
{
$headerFile = match (PHP_OS_FAMILY) {
return match (PHP_OS_FAMILY) {
'Darwin' => 'crc64nvme-darwin.h',
'Windows' => 'crc64nvme-windows.h',
default => 'crc64nvme-linux.h',
};

return __DIR__ . '/../' . $headerFile;
}

public static function whichLibrary(): string
Expand Down
52 changes: 6 additions & 46 deletions src/Crc64/Nvme.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Awesomized\Checksums\Crc64;

use Awesomized\Checksums;
use FFI;

/**
Expand All @@ -12,15 +13,8 @@
* @see \Awesomized\Checksums\Crc64\Ffi
* @link https://github.com/awesomized/crc64fast-nvme
*/
final class Nvme
final class Nvme implements Checksums\CrcInterface
{
/**
* The default read chunk size for file checksum calculation.
*
* 512 KiB turned out to be the fastest in my test cases.
*/
private const int READ_CHUNK_SIZE_DEFAULT = 524288;

private FFI\CData $digestHandle;

/**
Expand Down Expand Up @@ -50,45 +44,21 @@ public function __construct(
$this->digestHandle = $digestHandle;
}

/**
* Calculates the CRC-64 checksum for a string.
*
* @param FFI $crc64Nvme The FFI instance for the CRC-64 NVMe library.
* @param string $string The string to calculate the CRC-64 checksum for.
*
* @return string The calculated CRC-64 checksum as a hexadecimal string (due to signed large int issues in PHP).
*
* @throws \InvalidArgumentException
* @throws \RuntimeException
*/
public static function calculate(
FFI $crc64Nvme,
FFI $ffi,
string $string,
): string {
return (new self(
crc64Nvme: $crc64Nvme,
crc64Nvme: $ffi,
))
->write(
string: $string,
)
->sum();
}

/**
* Calculates the CRC-64 checksum for a file.
*
* @param FFI $crc64Nvme The FFI instance for the CRC-64 NVMe library.
* @param string $filename The file or URL.
* @param int<1, max> $readChunkSize The size of the chunks to read from the file. Adjust as necessary for your
* environment.
*
* @return string The calculated CRC-64 checksum as a hexadecimal string (due to signed large int issues in PHP).
*
* @throws \InvalidArgumentException
* @throws \RuntimeException
*/
public static function calculateFile(
FFI $crc64Nvme,
FFI $ffi,
string $filename,
int $readChunkSize = self::READ_CHUNK_SIZE_DEFAULT,
): string {
Expand All @@ -104,7 +74,7 @@ public static function calculateFile(
}

$nvme = new self(
crc64Nvme: $crc64Nvme,
crc64Nvme: $ffi,
);

while (
Expand All @@ -130,11 +100,6 @@ public static function calculateFile(
return $nvme->sum();
}

/**
* Writes a string to the CRC-64 checksum calculation.
*
* @throws \RuntimeException
*/
public function write(
string $string,
): self {
Expand All @@ -157,11 +122,6 @@ public function write(
return $this;
}

/**
* Returns the calculated CRC-64 checksum as a hexadecimal string (due to signed large int issues in PHP).
*
* @throws \RuntimeException
*/
public function sum(): string
{
try {
Expand Down
Loading

0 comments on commit aa55d31

Please sign in to comment.