PackField.php 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. <?php
  2. declare(strict_types=1);
  3. namespace ZipStream;
  4. use RuntimeException;
  5. /**
  6. * @internal
  7. * TODO: Make class readonly when requiring PHP 8.2 exclusively
  8. */
  9. class PackField
  10. {
  11. public const MAX_V = 0xFFFFFFFF;
  12. public const MAX_v = 0xFFFF;
  13. public function __construct(
  14. public readonly string $format,
  15. public readonly int|string $value
  16. ) {}
  17. /**
  18. * Create a format string and argument list for pack(), then call
  19. * pack() and return the result.
  20. */
  21. public static function pack(self ...$fields): string
  22. {
  23. $fmt = array_reduce($fields, function (string $acc, self $field) {
  24. return $acc . $field->format;
  25. }, '');
  26. $args = array_map(function (self $field) {
  27. switch ($field->format) {
  28. case 'V':
  29. if ($field->value > self::MAX_V) {
  30. throw new RuntimeException(print_r($field->value, true) . ' is larger than 32 bits');
  31. }
  32. break;
  33. case 'v':
  34. if ($field->value > self::MAX_v) {
  35. throw new RuntimeException(print_r($field->value, true) . ' is larger than 16 bits');
  36. }
  37. break;
  38. case 'P': break;
  39. default:
  40. break;
  41. }
  42. return $field->value;
  43. }, $fields);
  44. return pack($fmt, ...$args);
  45. }
  46. }