Accuracy.ts (6718B)
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 export const SECONDS = "seconds"; 9 export const MILLIS = "millis"; 10 export const MICROS = "micros"; 11 12 export interface IAccuracy { 13 /** 14 * Seconds 15 */ 16 seconds?: number; 17 /** 18 * Milliseconds 19 */ 20 millis?: number; 21 /** 22 * Microseconds 23 */ 24 micros?: number; 25 } 26 27 export type AccuracyParameters = PkiObjectParameters & Partial<IAccuracy>; 28 29 export type AccuracySchema = Schema.SchemaParameters<{ 30 seconds?: string; 31 millis?: string; 32 micros?: string; 33 }>; 34 35 /** 36 * JSON representation of {@link Accuracy} 37 */ 38 export interface AccuracyJson { 39 seconds?: number; 40 millis?: number; 41 micros?: number; 42 } 43 44 /** 45 * Represents the time deviation around the UTC time contained in GeneralizedTime. Described in [RFC3161](https://www.ietf.org/rfc/rfc3161.txt) 46 */ 47 export class Accuracy extends PkiObject implements IAccuracy { 48 49 public static override CLASS_NAME = "Accuracy"; 50 51 public seconds?: number; 52 public millis?: number; 53 public micros?: number; 54 55 /** 56 * Initializes a new instance of the {@link Accuracy} class 57 * @param parameters Initialization parameters 58 */ 59 constructor(parameters: AccuracyParameters = {}) { 60 super(); 61 62 if (SECONDS in parameters) { 63 this.seconds = pvutils.getParametersValue(parameters, SECONDS, Accuracy.defaultValues(SECONDS)); 64 } 65 if (MILLIS in parameters) { 66 this.millis = pvutils.getParametersValue(parameters, MILLIS, Accuracy.defaultValues(MILLIS)); 67 } 68 if (MICROS in parameters) { 69 this.micros = pvutils.getParametersValue(parameters, MICROS, Accuracy.defaultValues(MICROS)); 70 } 71 72 if (parameters.schema) { 73 this.fromSchema(parameters.schema); 74 } 75 } 76 77 /** 78 * Returns default values for all class members 79 * @param memberName String name for a class member 80 * @returns Default value 81 */ 82 public static override defaultValues(memberName: typeof SECONDS): number; 83 public static override defaultValues(memberName: typeof MILLIS): number; 84 public static override defaultValues(memberName: typeof MICROS): number; 85 public static override defaultValues(memberName: string): any; 86 public static override defaultValues(memberName: string): any { 87 switch (memberName) { 88 case SECONDS: 89 case MILLIS: 90 case MICROS: 91 return 0; 92 default: 93 return super.defaultValues(memberName); 94 } 95 } 96 97 /** 98 * Compare values with default values for all class members 99 * @param memberName String name for a class member 100 * @param memberValue Value to compare with default value 101 */ 102 public static compareWithDefault(memberName: typeof SECONDS | typeof MILLIS | typeof MICROS, memberValue: number): boolean; 103 public static compareWithDefault(memberName: string, memberValue: any): boolean; 104 public static compareWithDefault(memberName: string, memberValue: any): boolean { 105 switch (memberName) { 106 case SECONDS: 107 case MILLIS: 108 case MICROS: 109 return (memberValue === Accuracy.defaultValues(memberName)); 110 default: 111 return super.defaultValues(memberName); 112 } 113 } 114 115 /** 116 * @inheritdoc 117 * @asn ASN.1 schema 118 * ```asn 119 * Accuracy ::= SEQUENCE { 120 * seconds INTEGER OPTIONAL, 121 * millis [0] INTEGER (1..999) OPTIONAL, 122 * micros [1] INTEGER (1..999) OPTIONAL } 123 *``` 124 */ 125 public static override schema(parameters: AccuracySchema = {}): any { 126 const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); 127 128 return (new asn1js.Sequence({ 129 name: (names.blockName || EMPTY_STRING), 130 optional: true, 131 value: [ 132 new asn1js.Integer({ 133 optional: true, 134 name: (names.seconds || EMPTY_STRING) 135 }), 136 new asn1js.Primitive({ 137 name: (names.millis || EMPTY_STRING), 138 optional: true, 139 idBlock: { 140 tagClass: 3, // CONTEXT-SPECIFIC 141 tagNumber: 0 // [0] 142 } 143 }), 144 new asn1js.Primitive({ 145 name: (names.micros || EMPTY_STRING), 146 optional: true, 147 idBlock: { 148 tagClass: 3, // CONTEXT-SPECIFIC 149 tagNumber: 1 // [1] 150 } 151 }) 152 ] 153 })); 154 } 155 156 public fromSchema(schema: Schema.SchemaType): void { 157 // Clear input data first 158 pvutils.clearProps(schema, [ 159 SECONDS, 160 MILLIS, 161 MICROS, 162 ]); 163 164 // Check the schema is valid 165 const asn1 = asn1js.compareSchema(schema, 166 schema, 167 Accuracy.schema({ 168 names: { 169 seconds: SECONDS, 170 millis: MILLIS, 171 micros: MICROS, 172 } 173 }) 174 ); 175 AsnError.assertSchema(asn1, this.className); 176 177 // Get internal properties from parsed schema 178 if ("seconds" in asn1.result) { 179 this.seconds = asn1.result.seconds.valueBlock.valueDec; 180 } 181 if ("millis" in asn1.result) { 182 const intMillis = new asn1js.Integer({ valueHex: asn1.result.millis.valueBlock.valueHex }); 183 this.millis = intMillis.valueBlock.valueDec; 184 } 185 if ("micros" in asn1.result) { 186 const intMicros = new asn1js.Integer({ valueHex: asn1.result.micros.valueBlock.valueHex }); 187 this.micros = intMicros.valueBlock.valueDec; 188 } 189 } 190 191 public toSchema(): asn1js.Sequence { 192 //#region Create array of output sequence 193 const outputArray = []; 194 195 if (this.seconds !== undefined) 196 outputArray.push(new asn1js.Integer({ value: this.seconds })); 197 198 if (this.millis !== undefined) { 199 const intMillis = new asn1js.Integer({ value: this.millis }); 200 201 outputArray.push(new asn1js.Primitive({ 202 idBlock: { 203 tagClass: 3, // CONTEXT-SPECIFIC 204 tagNumber: 0 // [0] 205 }, 206 valueHex: intMillis.valueBlock.valueHexView 207 })); 208 } 209 210 if (this.micros !== undefined) { 211 const intMicros = new asn1js.Integer({ value: this.micros }); 212 213 outputArray.push(new asn1js.Primitive({ 214 idBlock: { 215 tagClass: 3, // CONTEXT-SPECIFIC 216 tagNumber: 1 // [1] 217 }, 218 valueHex: intMicros.valueBlock.valueHexView 219 })); 220 } 221 //#endregion 222 223 return (new asn1js.Sequence({ 224 value: outputArray 225 })); 226 } 227 public toJSON(): AccuracyJson { 228 const _object: AccuracyJson = {}; 229 230 if (this.seconds !== undefined) 231 _object.seconds = this.seconds; 232 233 if (this.millis !== undefined) 234 _object.millis = this.millis; 235 236 if (this.micros !== undefined) 237 _object.micros = this.micros; 238 239 return _object; 240 } 241 242 }