<?php
 declare(strict_types=1); namespace SpomkyLabs\Pki\ASN1\Util; use Brick\Math\BigInteger; use InvalidArgumentException; use Stringable; use Throwable; use function mb_strlen; final class BigInt implements Stringable { private readonly BigInteger $value; private ?string $number = null; private ?int $_intNum = null; private function __construct(BigInteger|int|string $num) { if (! $num instanceof BigInteger) { try { $num = BigInteger::of($num); } catch (Throwable) { throw new InvalidArgumentException('Unable to convert to integer.'); } } $this->value = $num; } public function __toString(): string { return $this->base10(); } public static function create(BigInteger|int|string $num): self { return new self($num); } public static function fromUnsignedOctets(string $octets): self { if (mb_strlen($octets, '8bit') === 0) { throw new InvalidArgumentException('Empty octets.'); } return self::create(BigInteger::fromBytes($octets, false)); } public static function fromSignedOctets(string $octets): self { if (mb_strlen($octets, '8bit') === 0) { throw new InvalidArgumentException('Empty octets.'); } return self::create(BigInteger::fromBytes($octets)); } public function base10(): string { if ($this->number === null) { $this->number = $this->value->toBase(10); } return $this->number; } public function toInt(): int { if (! isset($this->_intNum)) { $this->_intNum = $this->value->toInt(); } return $this->_intNum; } public function getValue(): BigInteger { return $this->value; } public function unsignedOctets(): string { return $this->value->toBytes(false); } public function signedOctets(): string { return $this->value->toBytes(); } } 