1 module types.oidtype;
2 import asn1;
3 import codec : ASN1ValueException;
4 import std.ascii : isGraphical;
5 
6 ///
7 public alias OIDNode = ObjectIdentifierNode;
8 /**
9     A struct representing a single node in an OID, which has a mandatory
10     number and an optional descriptor.
11 */
12 public
13 struct ObjectIdentifierNode
14 {
15     /**
16         The unique unsigned integral number associated with a node in the
17         object identifier hierarchy.
18     */
19     immutable public size_t number;
20     /**
21         The descriptor string is an ObjectDescriptor, which is defined as:
22 
23         $(MONO ObjectDescriptor ::= [UNIVERSAL 7] IMPLICIT GraphicString)
24 
25         GraphicString is just $(D 0x20) to $(D 0x7E), therefore
26         ObjectDescriptor is just $(D 0x20) to $(D 0x7E).
27 
28         It is used to describe the object identified by this node.
29     */
30     immutable public string descriptor;
31 
32     /// Override for use of the `==` operand.
33     public @safe @nogc nothrow
34     bool opEquals(const OIDNode other) const
35     {
36         return (this.number == other.number);
37     }
38 
39     ///
40     @system
41     unittest
42     {
43         immutable OIDNode a = OIDNode(1, "iso");
44         immutable OIDNode b = OIDNode(1, "not-iso");
45         assert(a == b);
46     }
47 
48     /// Override for the use of the '>', '<', '<=', and '>=' operands.
49     public @safe @nogc nothrow
50     ptrdiff_t opCmp(ref const OIDNode other) const
51     {
52         return cast(ptrdiff_t) (this.number - other.number);
53     }
54 
55     /**
56         An override so that associative arrays can use an $(D OIDNode) as a
57         key.
58         Returns: A $(D size_t) that represents a hash of the $(D OIDNode)
59     */
60     public nothrow @trusted
61     size_t toHash() const
62     {
63         return typeid(this.number).getHash(cast(const void*) &this.number);
64     }
65 
66     ///
67     @system
68     unittest
69     {
70         immutable OIDNode a = OIDNode(1, "iso");
71         immutable OIDNode b = OIDNode(2, "even-more-iso");
72         assert(b > a);
73     }
74 
75     /// The simple numeric constructor. Does not throw exceptions.
76     public @safe @nogc nothrow
77     this(in size_t number)
78     {
79         this.number = number;
80         this.descriptor = "";
81     }
82 
83     /**
84         A constructor that accepts a descriptor string.
85         The descriptor string is an ObjectDescriptor, which is defined as:
86 
87         $(MONO ObjectDescriptor ::= [UNIVERSAL 7] IMPLICIT GraphicString)
88 
89         $(MONO GraphicString) is just a string containing only characters between
90         and including $(D 0x20) and $(D 0x7E), therefore ObjectDescriptor is just
91         $(D 0x20) and $(D 0x7E).
92 
93         Throws:
94         $(UL
95             $(LI $(D ASN1ValueException) if the encoded value contains any bytes
96                 outside of $(D 0x20) to $(D 0x7E))
97         )
98     */
99     public @system
100     this(in size_t number, in string descriptor)
101     {
102         foreach (immutable character; descriptor)
103         {
104             if ((!character.isGraphical) && (character != ' '))
105             {
106                 throw new ASN1ValueException
107                 (
108                     "This exception was thrown because you tried to decode " ~
109                     "a GraphicString that contained a character that " ~
110                     "is not graphical (a character whose ASCII encoding " ~
111                     "is outside of the range 0x20 to 0x7E). The offending " ~
112                     "character is '" ~ character ~ "'. " ~
113                     "For more information on Object Identifiers, read the " ~
114                     "International Telecommunications Union's X.660 specification, " ~
115                     "which can be found at " ~
116                     "http://www.itu.int/rec/T-REC-X.660-201107-I/en. " ~
117                     "If you believe that you have " ~
118                     "discovered a bug, please create an issue on the GitHub page's Issues " ~
119                     "section at: https://github.com/JonathanWilbur/asn1-d/issues. "
120                 );
121             }
122         }
123         this.number = number;
124         this.descriptor = descriptor;
125     }
126 
127     @system
128     unittest
129     {
130         immutable OIDNode a = OIDNode(1, "Nitro dubs & T-Rix");
131         assert(a.descriptor == "Nitro dubs & T-Rix");
132         immutable OIDNode b = OIDNode(1, " ");
133         assert(b.descriptor == " ");
134         immutable OIDNode c = OIDNode(1, "");
135         assert(c.descriptor == "");
136         assertThrown!ASN1ValueException(OIDNode(1, "\xD7"));
137         assertThrown!ASN1ValueException(OIDNode(1, "\t"));
138         assertThrown!ASN1ValueException(OIDNode(1, "\r"));
139         assertThrown!ASN1ValueException(OIDNode(1, "\n"));
140         assertThrown!ASN1ValueException(OIDNode(1, "\b"));
141         assertThrown!ASN1ValueException(OIDNode(1, "\v"));
142         assertThrown!ASN1ValueException(OIDNode(1, "\f"));
143         assertThrown!ASN1ValueException(OIDNode(1, "\0"));
144     }
145 }