1<?php
2/**
3 * This file is part of the FreeDSx ASN1 package.
4 *
5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11namespace FreeDSx\Asn1\Type;
12
13use ArrayIterator;
14use Countable;
15use IteratorAggregate;
16use function count;
17
18/**
19 * Abstract ASN.1 type.
20 *
21 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
22 */
23abstract class AbstractType implements Countable, IteratorAggregate
24{
25    public const TAG_CLASS_UNIVERSAL = 0x00;
26
27    public const TAG_CLASS_CONTEXT_SPECIFIC = 0x80;
28
29    public const TAG_CLASS_APPLICATION = 0x40;
30
31    public const TAG_CLASS_PRIVATE = 0xC0;
32
33    public const TAG_TYPE_BOOLEAN = 0x01;
34
35    public const TAG_TYPE_INTEGER = 0x02;
36
37    public const TAG_TYPE_BIT_STRING = 0x03;
38
39    public const TAG_TYPE_OCTET_STRING = 0x04;
40
41    public const TAG_TYPE_NULL = 0x05;
42
43    public const TAG_TYPE_OID = 0x06;
44
45    public const TAG_TYPE_OBJECT_DESCRIPTOR = 0x07;
46
47    public const TAG_TYPE_EXTERNAL = 0x08;
48
49    public const TAG_TYPE_REAL = 0x09;
50
51    public const TAG_TYPE_ENUMERATED = 0x0A;
52
53    public const TAG_TYPE_EMBEDDED_PDV = 0x0B;
54
55    public const TAG_TYPE_UTF8_STRING = 0x0C;
56
57    public const TAG_TYPE_RELATIVE_OID = 0x0D;
58
59    public const TAG_TYPE_SEQUENCE = 0x10;
60
61    public const TAG_TYPE_SET = 0x11;
62
63    public const TAG_TYPE_NUMERIC_STRING = 0x12;
64
65    public const TAG_TYPE_PRINTABLE_STRING = 0x13;
66
67    public const TAG_TYPE_TELETEX_STRING = 0x14;
68
69    public const TAG_TYPE_VIDEOTEX_STRING = 0x15;
70
71    public const TAG_TYPE_IA5_STRING = 0x16;
72
73    public const TAG_TYPE_UTC_TIME = 0x17;
74
75    public const TAG_TYPE_GENERALIZED_TIME = 0x18;
76
77    public const TAG_TYPE_GRAPHIC_STRING = 0x19;
78
79    public const TAG_TYPE_VISIBLE_STRING = 0x1A;
80
81    public const TAG_TYPE_GENERAL_STRING = 0x1B;
82
83    public const TAG_TYPE_UNIVERSAL_STRING = 0x1C;
84
85    public const TAG_TYPE_CHARACTER_STRING = 0x1D;
86
87    public const TAG_TYPE_BMP_STRING = 0x1E;
88
89    /**
90     * Used in the tag to denote a constructed type.
91     */
92    public const CONSTRUCTED_TYPE = 0x20;
93
94    /**
95     * @var scalar|null
96     */
97    protected $value;
98
99    /**
100     * @var null|int|string
101     */
102    protected $tagNumber;
103
104    /**
105     * @var int
106     */
107    protected $taggingClass = self::TAG_CLASS_UNIVERSAL;
108
109    /**
110     * @var bool
111     */
112    protected $isConstructed = false;
113
114    /**
115     * @var AbstractType[]
116     */
117    protected $children = [];
118
119    /**
120     * @param mixed $value
121     */
122    public function __construct($value)
123    {
124        $this->value = $value;
125    }
126
127    /**
128     * @return bool
129     */
130    public function getIsConstructed(): bool
131    {
132        return $this->isConstructed;
133    }
134
135    /**
136     * @param bool $isConstructed
137     * @return $this
138     */
139    public function setIsConstructed(bool $isConstructed)
140    {
141        $this->isConstructed = $isConstructed;
142
143        return $this;
144    }
145
146    /**
147     * @param int $taggingClass
148     * @return $this
149     */
150    public function setTagClass(int $taggingClass)
151    {
152        $this->taggingClass = $taggingClass;
153
154        return $this;
155    }
156
157    /**
158     * @return int
159     */
160    public function getTagClass(): int
161    {
162        return $this->taggingClass;
163    }
164
165    /**
166     * @return int|null|string
167     */
168    public function getTagNumber()
169    {
170        return $this->tagNumber;
171    }
172
173    /**
174     * @param int|null|string $int
175     * @return $this
176     */
177    public function setTagNumber($int)
178    {
179        $this->tagNumber = $int;
180
181        return $this;
182    }
183
184    public function getValue()
185    {
186        return $this->value;
187    }
188
189    /**
190     * @param int $index
191     * @return bool
192     */
193    public function hasChild(int $index)
194    {
195        return isset($this->children[$index]);
196    }
197
198    /**
199     * @param AbstractType ...$types
200     * @return $this
201     */
202    public function setChildren(...$types)
203    {
204        $this->children = $types;
205
206        return $this;
207    }
208
209    /**
210     * @return AbstractType[]
211     */
212    public function getChildren(): array
213    {
214        return $this->children;
215    }
216
217    /**
218     * @param int $index
219     * @return null|AbstractType
220     */
221    public function getChild(int $index): ?AbstractType
222    {
223        return $this->children[$index] ?? null;
224    }
225
226    /**
227     * @param AbstractType ...$types
228     * @return $this
229     */
230    public function addChild(...$types)
231    {
232        foreach ($types as $type) {
233            $this->children[] = $type;
234        }
235
236        return $this;
237    }
238
239    /**
240     * @return int
241     */
242    public function count(): int
243    {
244        return count($this->children);
245    }
246
247    /**
248     * @return ArrayIterator<AbstractType>
249     */
250    public function getIterator(): ArrayIterator
251    {
252        return new ArrayIterator($this->children);
253    }
254}
255