33namespace Utopia \Database \Validator ;
44
55use Utopia \Database \Database ;
6- use Utopia \Database \Helpers \BigInt as BigIntHelper ;
76use Utopia \Validator ;
87
98class BigInt extends Validator
109{
10+ public const SIGNED_MIN = '-9223372036854775808 ' ;
11+ public const SIGNED_MAX = '9223372036854775807 ' ;
12+ public const UNSIGNED_MAX = '18446744073709551615 ' ;
13+
1114 public function __construct (
1215 private readonly bool $ signed ,
1316 private readonly bool $ supportUnsigned64Bit = true
@@ -18,13 +21,13 @@ public function getDescription(): string
1821 {
1922 if ($ this ->signed ) {
2023 return 'Value must be a valid signed 64-bit integer between ' .
21- BigIntHelper ::formatIntegerString (BigIntHelper ::SIGNED_MIN ) .
22- ' and ' . BigIntHelper ::formatIntegerString (BigIntHelper ::SIGNED_MAX );
24+ self ::formatIntegerString (self ::SIGNED_MIN ) .
25+ ' and ' . self ::formatIntegerString (self ::SIGNED_MAX );
2326 }
2427
25- $ max = $ this ->supportUnsigned64Bit ? BigIntHelper ::UNSIGNED_MAX : BigIntHelper ::SIGNED_MAX ;
28+ $ max = $ this ->supportUnsigned64Bit ? self ::UNSIGNED_MAX : self ::SIGNED_MAX ;
2629 return 'Value must be a valid unsigned 64-bit integer between 0 and ' .
27- BigIntHelper ::formatIntegerString ($ max );
30+ self ::formatIntegerString ($ max );
2831 }
2932
3033 public function isArray (): bool
@@ -47,6 +50,89 @@ public function isValid(mixed $value): bool
4750 return false ;
4851 }
4952
50- return BigIntHelper::fitsBigIntRange ($ value , $ this ->signed , $ this ->supportUnsigned64Bit );
53+ return self ::fitsBigIntRange ($ value , $ this ->signed , $ this ->supportUnsigned64Bit );
54+ }
55+
56+ public static function isIntegerString (string $ value , bool $ signed = true ): bool
57+ {
58+ return \preg_match ($ signed ? '/^-?\d+$/ ' : '/^\d+$/ ' , $ value ) === 1 ;
59+ }
60+
61+ public static function fitsPhpInt (string $ value , bool $ signed = true ): bool
62+ {
63+ if (!self ::isIntegerString ($ value , $ signed )) {
64+ return false ;
65+ }
66+
67+ $ phpMax = (string )\PHP_INT_MAX ;
68+ $ phpMinAbs = \ltrim ((string )\PHP_INT_MIN , '- ' );
69+
70+ if ($ signed && \str_starts_with ($ value , '- ' )) {
71+ $ digits = self ::normalizeUnsignedString (\substr ($ value , 1 ));
72+ return self ::compareUnsignedStrings ($ digits , $ phpMinAbs ) <= 0 ;
73+ }
74+
75+ $ digits = self ::normalizeUnsignedString ($ value );
76+ return self ::compareUnsignedStrings ($ digits , $ phpMax ) <= 0 ;
77+ }
78+
79+ public static function fitsBigIntRange (string $ value , bool $ signed , bool $ supportUnsigned64Bit = true ): bool
80+ {
81+ if (!self ::isIntegerString ($ value , $ signed )) {
82+ return false ;
83+ }
84+
85+ if ($ signed ) {
86+ if (\str_starts_with ($ value , '- ' )) {
87+ $ digits = self ::normalizeUnsignedString (\substr ($ value , 1 ));
88+ $ minAbs = \ltrim (\str_replace ('- ' , '' , self ::SIGNED_MIN ), '0 ' );
89+ return self ::compareUnsignedStrings ($ digits , $ minAbs ) <= 0 ;
90+ }
91+
92+ return self ::compareUnsignedStrings ($ value , self ::SIGNED_MAX ) <= 0 ;
93+ }
94+
95+ $ max = $ supportUnsigned64Bit ? self ::UNSIGNED_MAX : self ::SIGNED_MAX ;
96+ return self ::compareUnsignedStrings ($ value , $ max ) <= 0 ;
97+ }
98+
99+ public static function normalizeUnsignedString (string $ value ): string
100+ {
101+ $ value = \trim ($ value );
102+ $ value = \ltrim ($ value , '0 ' );
103+ return $ value === '' ? '0 ' : $ value ;
104+ }
105+
106+ public static function compareUnsignedStrings (string $ a , string $ b ): int
107+ {
108+ $ a = self ::normalizeUnsignedString ($ a );
109+ $ b = self ::normalizeUnsignedString ($ b );
110+
111+ $ lenA = \strlen ($ a );
112+ $ lenB = \strlen ($ b );
113+ if ($ lenA < $ lenB ) {
114+ return -1 ;
115+ }
116+ if ($ lenA > $ lenB ) {
117+ return 1 ;
118+ }
119+ if ($ a === $ b ) {
120+ return 0 ;
121+ }
122+
123+ return $ a < $ b ? -1 : 1 ;
124+ }
125+
126+ public static function formatIntegerString (string $ value ): string
127+ {
128+ $ negative = \str_starts_with ($ value , '- ' );
129+ if ($ negative ) {
130+ $ value = \substr ($ value , 1 );
131+ }
132+
133+ $ value = self ::normalizeUnsignedString ($ value );
134+ $ formatted = \preg_replace ('/\B(?=(\d{3})+(?!\d))/ ' , ', ' , $ value ) ?? $ value ;
135+
136+ return $ negative ? "- {$ formatted }" : $ formatted ;
51137 }
52138}
0 commit comments