Attribute.ts (4414B)
1 import * as asn1js from "asn1js"; 2 import * as pvutils from "pvutils"; 3 import { EMPTY_STRING } from "./constants"; 4 import { AsnError } from "./errors"; 5 import { PkiObject, PkiObjectParameters } from "./PkiObject"; 6 import * as Schema from "./Schema"; 7 8 const TYPE = "type"; 9 const VALUES = "values"; 10 const CLEAR_PROPS = [ 11 TYPE, 12 VALUES 13 ]; 14 15 export interface IAttribute { 16 /** 17 * Specifies type of attribute value 18 */ 19 type: string; 20 /** 21 * List of attribute values 22 */ 23 values: any[]; 24 } 25 26 export type AttributeParameters = PkiObjectParameters & Partial<IAttribute>; 27 28 export type AttributeSchema = Schema.SchemaParameters<{ 29 setName?: string; 30 type?: string; 31 values?: string; 32 }>; 33 34 export interface AttributeJson { 35 type: string; 36 values: any[]; 37 } 38 39 /** 40 * Represents the Attribute structure described in [RFC2986](https://datatracker.ietf.org/doc/html/rfc2986) 41 */ 42 export class Attribute extends PkiObject implements IAttribute { 43 44 public static override CLASS_NAME = "Attribute"; 45 46 public type!: string; 47 public values!: any[]; 48 49 /** 50 * Initializes a new instance of the {@link Attribute} class 51 * @param parameters Initialization parameters 52 */ 53 constructor(parameters: AttributeParameters = {}) { 54 super(); 55 56 this.type = pvutils.getParametersValue(parameters, TYPE, Attribute.defaultValues(TYPE)); 57 this.values = pvutils.getParametersValue(parameters, VALUES, Attribute.defaultValues(VALUES)); 58 59 if (parameters.schema) { 60 this.fromSchema(parameters.schema); 61 } 62 } 63 64 /** 65 * Returns default values for all class members 66 * @param memberName String name for a class member 67 * @returns Default value 68 */ 69 public static override defaultValues(memberName: typeof TYPE): string; 70 public static override defaultValues(memberName: typeof VALUES): any[]; 71 public static override defaultValues(memberName: string): any { 72 switch (memberName) { 73 case TYPE: 74 return EMPTY_STRING; 75 case VALUES: 76 return []; 77 default: 78 return super.defaultValues(memberName); 79 } 80 } 81 82 /** 83 * Compares values with default values for all class members 84 * @param memberName String name for a class member 85 * @param memberValue Value to compare with default value 86 */ 87 public static compareWithDefault(memberName: string, memberValue: any): boolean { 88 switch (memberName) { 89 case TYPE: 90 return (memberValue === EMPTY_STRING); 91 case VALUES: 92 return (memberValue.length === 0); 93 default: 94 return super.defaultValues(memberName); 95 } 96 } 97 98 /** 99 * @inheritdoc 100 * @asn ASN.1 schema 101 * ```asn 102 * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE { 103 * type ATTRIBUTE.&id({IOSet}), 104 * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) 105 * } 106 *``` 107 */ 108 public static override schema(parameters: AttributeSchema = {}) { 109 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 110 111 return (new asn1js.Sequence({ 112 name: (names.blockName || EMPTY_STRING), 113 value: [ 114 new asn1js.ObjectIdentifier({ name: (names.type || EMPTY_STRING) }), 115 new asn1js.Set({ 116 name: (names.setName || EMPTY_STRING), 117 value: [ 118 new asn1js.Repeated({ 119 name: (names.values || EMPTY_STRING), 120 value: new asn1js.Any() 121 }) 122 ] 123 }) 124 ] 125 })); 126 } 127 128 public fromSchema(schema: Schema.SchemaType): void { 129 // Clear input data first 130 pvutils.clearProps(schema, CLEAR_PROPS); 131 132 // Check the schema is valid 133 const asn1 = asn1js.compareSchema(schema, 134 schema, 135 Attribute.schema({ 136 names: { 137 type: TYPE, 138 values: VALUES 139 } 140 }) 141 ); 142 AsnError.assertSchema(asn1, this.className); 143 144 // Get internal properties from parsed schema 145 this.type = asn1.result.type.valueBlock.toString(); 146 this.values = asn1.result.values; 147 } 148 149 public toSchema(): asn1js.Sequence { 150 //#region Construct and return new ASN.1 schema for this object 151 return (new asn1js.Sequence({ 152 value: [ 153 new asn1js.ObjectIdentifier({ value: this.type }), 154 new asn1js.Set({ 155 value: this.values 156 }) 157 ] 158 })); 159 //#endregion 160 } 161 162 public toJSON(): AttributeJson { 163 return { 164 type: this.type, 165 values: Array.from(this.values, o => o.toJSON()) 166 }; 167 } 168 169 }