asn1-ts
Version:
ASN.1 encoding and decoding, including BER, CER, and DER.
44 lines (43 loc) • 1.9 kB
JavaScript
import dissectFloat from "./dissectFloat.mjs";
import encodeUnsignedBigEndianInteger from "./encodeUnsignedBigEndianInteger.mjs";
import encodeSignedBigEndianInteger from "./encodeSignedBigEndianInteger.mjs";
import { ASN1SpecialRealValue } from "../values.mjs";
import * as errors from "../errors.mjs";
export default function encodeX690BinaryRealNumber(value) {
if (value === 0.0) {
return new Uint8Array(0);
}
else if (Number.isNaN(value)) {
return new Uint8Array([ASN1SpecialRealValue.notANumber]);
}
else if (value === -0.0) {
return new Uint8Array([ASN1SpecialRealValue.minusZero]);
}
else if (value === Infinity) {
return new Uint8Array([ASN1SpecialRealValue.plusInfinity]);
}
else if (value === -Infinity) {
return new Uint8Array([ASN1SpecialRealValue.minusInfinity]);
}
const floatComponents = dissectFloat(value);
while (floatComponents.mantissa !== 0 && (floatComponents.mantissa % 2) === 0) {
floatComponents.mantissa = floatComponents.mantissa >>> 1;
floatComponents.exponent++;
}
if (floatComponents.exponent <= -1020) {
throw new errors.ASN1OverflowError(`REAL number ${value} (having exponent ${floatComponents.exponent}) `
+ "is too precise to encode.");
}
const singleByteExponent = ((floatComponents.exponent <= 127)
&& (floatComponents.exponent >= -128));
const firstByte = (128
| (value >= 0 ? 0 : 64)
| (singleByteExponent ? 0 : 1));
const exponentBytes = encodeSignedBigEndianInteger(floatComponents.exponent);
const mantissaBytes = encodeUnsignedBigEndianInteger(floatComponents.mantissa);
const ret = new Uint8Array(1 + exponentBytes.length + mantissaBytes.length);
ret[0] = firstByte;
ret.set(exponentBytes, 1);
ret.set(mantissaBytes, (1 + exponentBytes.length));
return ret;
}