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