QCStatements.ts (7727B)
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 ID = "id"; 9 const TYPE = "type"; 10 const VALUES = "values"; 11 const QC_STATEMENT_CLEAR_PROPS = [ 12 ID, 13 TYPE 14 ]; 15 const QC_STATEMENTS_CLEAR_PROPS = [ 16 VALUES 17 ]; 18 19 export interface IQCStatement { 20 id: string; 21 type?: any; 22 } 23 24 export interface QCStatementJson { 25 id: string; 26 type?: any; 27 } 28 29 export type QCStatementParameters = PkiObjectParameters & Partial<IQCStatement>; 30 31 export type QCStatementSchema = Schema.SchemaParameters<{ 32 id?: string; 33 type?: string; 34 }>; 35 36 /** 37 * Represents the QCStatement structure described in [RFC3739](https://datatracker.ietf.org/doc/html/rfc3739) 38 */ 39 export class QCStatement extends PkiObject implements IQCStatement { 40 41 public static override CLASS_NAME = "QCStatement"; 42 43 public id!: string; 44 public type?: any; 45 46 /** 47 * Initializes a new instance of the {@link QCStatement} class 48 * @param parameters Initialization parameters 49 */ 50 constructor(parameters: QCStatementParameters = {}) { 51 super(); 52 53 this.id = pvutils.getParametersValue(parameters, ID, QCStatement.defaultValues(ID)); 54 if (TYPE in parameters) { 55 this.type = pvutils.getParametersValue(parameters, TYPE, QCStatement.defaultValues(TYPE)); 56 } 57 58 if (parameters.schema) { 59 this.fromSchema(parameters.schema); 60 } 61 } 62 63 /** 64 * Returns default values for all class members 65 * @param memberName String name for a class member 66 * @returns Default value 67 */ 68 public static override defaultValues(memberName: typeof ID): string; 69 public static override defaultValues(memberName: typeof TYPE): any; 70 public static override defaultValues(memberName: string): any { 71 switch (memberName) { 72 case ID: 73 return EMPTY_STRING; 74 case TYPE: 75 return new asn1js.Null(); 76 default: 77 return super.defaultValues(memberName); 78 } 79 } 80 81 /** 82 * Compare values with default values for all class members 83 * @param memberName String name for a class member 84 * @param memberValue Value to compare with default value 85 */ 86 public static compareWithDefault(memberName: string, memberValue: any): boolean { 87 switch (memberName) { 88 case ID: 89 return (memberValue === EMPTY_STRING); 90 case TYPE: 91 return (memberValue instanceof asn1js.Null); 92 default: 93 return super.defaultValues(memberName); 94 } 95 } 96 97 /** 98 * @inheritdoc 99 * @asn ASN.1 schema 100 * ```asn 101 * QCStatement ::= SEQUENCE { 102 * statementId QC-STATEMENT.&id({SupportedStatements}), 103 * statementInfo QC-STATEMENT.&Type({SupportedStatements}{@statementId}) OPTIONAL 104 * } 105 *``` 106 */ 107 public static override schema(parameters: QCStatementSchema = {}): Schema.SchemaType { 108 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 109 110 return (new asn1js.Sequence({ 111 name: (names.blockName || EMPTY_STRING), 112 value: [ 113 new asn1js.ObjectIdentifier({ name: (names.id || EMPTY_STRING) }), 114 new asn1js.Any({ 115 name: (names.type || EMPTY_STRING), 116 optional: true 117 }) 118 ] 119 })); 120 } 121 122 public fromSchema(schema: Schema.SchemaType): void { 123 // Clear input data first 124 pvutils.clearProps(schema, QC_STATEMENT_CLEAR_PROPS); 125 126 // Check the schema is valid 127 const asn1 = asn1js.compareSchema(schema, 128 schema, 129 QCStatement.schema({ 130 names: { 131 id: ID, 132 type: TYPE 133 } 134 }) 135 ); 136 AsnError.assertSchema(asn1, this.className); 137 138 // Get internal properties from parsed schema 139 this.id = asn1.result.id.valueBlock.toString(); 140 if (TYPE in asn1.result) 141 this.type = asn1.result.type; 142 } 143 144 public toSchema(): asn1js.Sequence { 145 const value = [ 146 new asn1js.ObjectIdentifier({ value: this.id }) 147 ]; 148 149 if (TYPE in this) 150 value.push(this.type); 151 152 // Construct and return new ASN.1 schema for this object 153 return (new asn1js.Sequence({ 154 value, 155 })); 156 } 157 158 public toJSON(): QCStatementJson { 159 const object: any = { 160 id: this.id 161 }; 162 163 if (this.type) { 164 object.type = this.type.toJSON(); 165 } 166 167 return object; 168 } 169 170 } 171 172 export interface IQCStatements { 173 values: QCStatement[]; 174 } 175 176 export interface QCStatementsJson { 177 values: QCStatementJson[]; 178 } 179 180 export type QCStatementsParameters = PkiObjectParameters & Partial<IQCStatements>; 181 182 /** 183 * Represents the QCStatements structure described in [RFC3739](https://datatracker.ietf.org/doc/html/rfc3739) 184 */ 185 export class QCStatements extends PkiObject implements IQCStatements { 186 187 public static override CLASS_NAME = "QCStatements"; 188 189 public values!: QCStatement[]; 190 191 /** 192 * Initializes a new instance of the {@link QCStatement} class 193 * @param parameters Initialization parameters 194 */ 195 constructor(parameters: QCStatementParameters = {}) { 196 super(); 197 198 this.values = pvutils.getParametersValue(parameters, VALUES, QCStatements.defaultValues(VALUES)); 199 200 if (parameters.schema) { 201 this.fromSchema(parameters.schema); 202 } 203 } 204 205 /** 206 * Returns default values for all class members 207 * @param memberName String name for a class member 208 * @returns Default value 209 */ 210 public static override defaultValues(memberName: typeof VALUES): QCStatement[]; 211 public static override defaultValues(memberName: string): any { 212 switch (memberName) { 213 case VALUES: 214 return []; 215 default: 216 return super.defaultValues(memberName); 217 } 218 } 219 220 /** 221 * Compare values with default values for all class members 222 * @param memberName String name for a class member 223 * @param memberValue Value to compare with default value 224 */ 225 public static compareWithDefault(memberName: string, memberValue: any): boolean { 226 switch (memberName) { 227 case VALUES: 228 return (memberValue.length === 0); 229 default: 230 return super.defaultValues(memberName); 231 } 232 } 233 234 /** 235 * @inheritdoc 236 * @asn ASN.1 schema 237 * ```asn 238 * QCStatements ::= SEQUENCE OF QCStatement 239 *``` 240 */ 241 public static override schema(parameters: Schema.SchemaParameters<{ 242 values?: string; 243 value?: QCStatementSchema; 244 }> = {}): Schema.SchemaType { 245 /** 246 * @type {Object} 247 * @property {string} [blockName] 248 * @property {string} [values] 249 */ 250 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 251 252 return (new asn1js.Sequence({ 253 name: (names.blockName || EMPTY_STRING), 254 value: [ 255 new asn1js.Repeated({ 256 name: (names.values || EMPTY_STRING), 257 value: QCStatement.schema(names.value || {}) 258 }), 259 ] 260 })); 261 } 262 263 public fromSchema(schema: Schema.SchemaType): void { 264 // Clear input data first 265 pvutils.clearProps(schema, QC_STATEMENTS_CLEAR_PROPS); 266 267 // Check the schema is valid 268 const asn1 = asn1js.compareSchema(schema, 269 schema, 270 QCStatements.schema({ 271 names: { 272 values: VALUES 273 } 274 }) 275 ); 276 AsnError.assertSchema(asn1, this.className); 277 278 // Get internal properties from parsed schema 279 this.values = Array.from(asn1.result.values, element => new QCStatement({ schema: element })); 280 } 281 282 public toSchema(): asn1js.Sequence { 283 // Construct and return new ASN.1 schema for this object 284 return (new asn1js.Sequence({ 285 value: Array.from(this.values, o => o.toSchema()) 286 })); 287 } 288 289 public toJSON(): QCStatementsJson { 290 return { 291 values: Array.from(this.values, o => o.toJSON()) 292 }; 293 } 294 295 }