<?php
 declare(strict_types=1); namespace SpomkyLabs\Pki\X509\GeneralName; use SpomkyLabs\Pki\ASN1\Element; use SpomkyLabs\Pki\ASN1\Type\TaggedType; use SpomkyLabs\Pki\ASN1\Type\UnspecifiedType; use Stringable; use UnexpectedValueException; abstract class GeneralName implements Stringable { public const TAG_OTHER_NAME = 0; public const TAG_RFC822_NAME = 1; public const TAG_DNS_NAME = 2; public const TAG_X400_ADDRESS = 3; public const TAG_DIRECTORY_NAME = 4; public const TAG_EDI_PARTY_NAME = 5; public const TAG_URI = 6; public const TAG_IP_ADDRESS = 7; public const TAG_REGISTERED_ID = 8; protected function __construct( protected int $tag ) { } public function __toString(): string { return $this->string(); } abstract public function string(): string; abstract public static function fromChosenASN1(UnspecifiedType $el): self; public static function fromASN1(TaggedType $el): self { return match ($el->tag()) { self::TAG_OTHER_NAME => OtherName::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)), self::TAG_RFC822_NAME => RFC822Name::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)), self::TAG_DNS_NAME => DNSName::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)), self::TAG_X400_ADDRESS => X400Address::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)), self::TAG_DIRECTORY_NAME => DirectoryName::fromChosenASN1($el->asExplicit()), self::TAG_EDI_PARTY_NAME => EDIPartyName::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)), self::TAG_URI => UniformResourceIdentifier::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)), self::TAG_IP_ADDRESS => IPAddress::fromChosenASN1($el->asImplicit(Element::TYPE_OCTET_STRING)), self::TAG_REGISTERED_ID => RegisteredID::fromChosenASN1($el->asImplicit(Element::TYPE_OBJECT_IDENTIFIER)), default => throw new UnexpectedValueException('GeneralName type ' . $el->tag() . ' not supported.'), }; } public function tag(): int { return $this->tag; } public function toASN1(): Element { return $this->choiceASN1(); } public function equals(self $other): bool { if ($this->tag !== $other->tag) { return false; } if ($this->choiceASN1()->toDER() !== $other->choiceASN1()->toDER()) { return false; } return true; } abstract protected function choiceASN1(): TaggedType; } 