Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
92 changes: 89 additions & 3 deletions src/Validator/Integer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,34 @@ class Integer extends Validator
*/
protected bool $loose = false;

/**
* @var int
*/
protected int $bits = 32;

/**
* @var bool
*/
protected bool $unsigned = false;

/**
* Pass true to accept integer strings as valid integer values
* This option is good for validating query string params.
*
* @param bool $loose
* @param int $bits Integer bit size (8, 16, 32, or 64)
* @param bool $unsigned Whether the integer is unsigned
* @throws \InvalidArgumentException
*/
public function __construct(bool $loose = false)
public function __construct(bool $loose = false, int $bits = 32, bool $unsigned = false)
{
if (!\in_array($bits, [8, 16, 32, 64])) {
throw new \InvalidArgumentException('Bits must be 8, 16, 32, or 64');
}

$this->loose = $loose;
$this->bits = $bits;
$this->unsigned = $unsigned;
}

/**
Expand All @@ -36,7 +55,24 @@ public function __construct(bool $loose = false)
*/
public function getDescription(): string
{
return 'Value must be a valid integer';
$signedness = $this->unsigned ? 'unsigned' : 'signed';

// Calculate min and max values based on bit size and signed/unsigned
if ($this->unsigned) {
$min = 0;
$max = (2 ** $this->bits) - 1;
} else {
$min = -(2 ** ($this->bits - 1));
$max = (2 ** ($this->bits - 1)) - 1;
}

return \sprintf(
'Value must be a valid %s %d-bit integer between %s and %s',
$signedness,
$this->bits,
\number_format($min),
\number_format($max)
);
}

/**
Expand All @@ -63,10 +99,46 @@ public function getType(): string
return self::TYPE_INTEGER;
}

/**
* Get Bits
*
* Returns the bit size of the integer.
*
* @return int
*/
public function getBits(): int
{
return $this->bits;
}

/**
* Is Unsigned
*
* Returns whether the integer is unsigned.
*
* @return bool
*/
public function isUnsigned(): bool
{
return $this->unsigned;
}

/**
* Get Format
*
* Returns the OpenAPI/JSON Schema format string for this integer configuration.
*
* @return string
*/
public function getFormat(): string
{
return 'int' . $this->bits;
}
Comment thread
ChiragAgg5k marked this conversation as resolved.

/**
* Is valid
*
* Validation will pass when $value is integer.
* Validation will pass when $value is integer and within the specified bit range.
*
* @param mixed $value
* @return bool
Expand All @@ -83,6 +155,20 @@ public function isValid(mixed $value): bool
return false;
}

// Calculate min and max values based on bit size and signed/unsigned
if ($this->unsigned) {
$min = 0;
$max = (2 ** $this->bits) - 1;
} else {
$min = -(2 ** ($this->bits - 1));
$max = (2 ** ($this->bits - 1)) - 1;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Check if value is within range
if ($value < $min || $value > $max) {
return false;
}

return true;
}
}
39 changes: 39 additions & 0 deletions tests/Validator/IntegerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,43 @@ public function testCanValidateLoosely()
$this->assertFalse($validator->isArray());
$this->assertSame(\Utopia\Validator::TYPE_INTEGER, $validator->getType());
}

public function testBitSizeAndSignedness()
{
// Default: 32-bit signed
$validator = new Integer();
$this->assertSame(32, $validator->getBits());
$this->assertFalse($validator->isUnsigned());
$this->assertSame('int32', $validator->getFormat());

// 8-bit signed: -128 to 127
$validator8 = new Integer(false, 8);
$this->assertTrue($validator8->isValid(-128));
$this->assertTrue($validator8->isValid(127));
$this->assertFalse($validator8->isValid(-129));
$this->assertFalse($validator8->isValid(128));

// 8-bit unsigned: 0 to 255
$validator8u = new Integer(false, 8, true);
$this->assertTrue($validator8u->isValid(0));
$this->assertTrue($validator8u->isValid(255));
$this->assertFalse($validator8u->isValid(-1));
$this->assertFalse($validator8u->isValid(256));

// 16-bit unsigned: 0 to 65535
$validator16u = new Integer(false, 16, true);
$this->assertTrue($validator16u->isValid(65535));
$this->assertFalse($validator16u->isValid(65536));

// 64-bit signed
$validator64 = new Integer(false, 64);
$this->assertSame('int64', $validator64->getFormat());
}

public function testInvalidBitSize()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Bits must be 8, 16, 32, or 64');
new Integer(false, 128);
}
}
Loading