Parse and validate AT Protocol Lexicons with DTO generation for Laravel
at main 2.5 kB view raw
1<?php 2 3namespace SocialDept\AtpSchema\Data\Types; 4 5use SocialDept\AtpSchema\Data\TypeDefinition; 6use SocialDept\AtpSchema\Exceptions\RecordValidationException; 7 8class BytesType extends TypeDefinition 9{ 10 /** 11 * Minimum byte length. 12 */ 13 public readonly ?int $minLength; 14 15 /** 16 * Maximum byte length. 17 */ 18 public readonly ?int $maxLength; 19 20 /** 21 * Create a new BytesType. 22 */ 23 public function __construct( 24 ?string $description = null, 25 ?int $minLength = null, 26 ?int $maxLength = null 27 ) { 28 parent::__construct('bytes', $description); 29 30 $this->minLength = $minLength; 31 $this->maxLength = $maxLength; 32 } 33 34 /** 35 * Create from array data. 36 */ 37 public static function fromArray(array $data): self 38 { 39 return new self( 40 description: $data['description'] ?? null, 41 minLength: $data['minLength'] ?? null, 42 maxLength: $data['maxLength'] ?? null 43 ); 44 } 45 46 /** 47 * Convert to array. 48 */ 49 public function toArray(): array 50 { 51 $array = ['type' => $this->type]; 52 53 if ($this->description !== null) { 54 $array['description'] = $this->description; 55 } 56 57 if ($this->minLength !== null) { 58 $array['minLength'] = $this->minLength; 59 } 60 61 if ($this->maxLength !== null) { 62 $array['maxLength'] = $this->maxLength; 63 } 64 65 return $array; 66 } 67 68 /** 69 * Validate a value against this type definition. 70 */ 71 public function validate(mixed $value, string $path = ''): void 72 { 73 if (! is_string($value)) { 74 throw RecordValidationException::invalidType($path, 'bytes (base64 string)', gettype($value)); 75 } 76 77 // Validate base64 encoding 78 $decoded = base64_decode($value, true); 79 80 if ($decoded === false || base64_encode($decoded) !== $value) { 81 throw RecordValidationException::invalidValue($path, 'must be valid base64-encoded data'); 82 } 83 84 // Length validation on decoded bytes 85 $length = strlen($decoded); 86 87 if ($this->minLength !== null && $length < $this->minLength) { 88 throw RecordValidationException::invalidValue($path, "must be at least {$this->minLength} bytes"); 89 } 90 91 if ($this->maxLength !== null && $length > $this->maxLength) { 92 throw RecordValidationException::invalidValue($path, "must be at most {$this->maxLength} bytes"); 93 } 94 } 95}