ms-nrbf-js
v0.1.0
Published
Read and write MS-NRBF (.NET Remoting Binary Format) encoded binary files
Maintainers
Readme
ms-nrbf-js
Read and write binary files encoded in the MS-NRBF format (.NET Remoting Binary Format) — the wire format used by .NET's BinaryFormatter.
Installation
npm install ms-nrbf-jsQuick start
import { readFileSync, writeFileSync } from "node:fs";
import { deserialize, serialize } from "ms-nrbf-js";
// Read
const root = deserialize(readFileSync("data.nrbf"));
// Write
writeFileSync("out.nrbf", serialize(root));API
deserialize(buf: Buffer): NrbfRoot
Parses an NRBF byte buffer and returns the root value. The return type is NrbfRoot:
type NrbfRoot = NrbfValue | NrbfMethodCall | NrbfMethodReturn;For typical object streams the result is an NrbfValue. For RPC streams it is an NrbfMethodCall or NrbfMethodReturn; check the kind discriminant:
import { deserialize } from "ms-nrbf-js";
import type { NrbfMethodCall, NrbfObject } from "ms-nrbf-js";
const root = deserialize(buf);
if (typeof root === "object" && root !== null && "kind" in root) {
if (root.kind === "MethodCall") {
const call = root as NrbfMethodCall;
console.log(call.methodName, call.typeName, call.args);
}
} else {
const obj = root as NrbfObject;
console.log(obj.typeName, obj.members);
}serialize(root: NrbfRoot): Buffer
Encodes a value tree (or method call/return) as an NRBF byte buffer. Circular object references are serialized as MemberReference records and round-trip correctly.
import { serialize } from "ms-nrbf-js";
import type { NrbfObject } from "ms-nrbf-js";
const obj: NrbfObject = {
typeName: "MyApp.Config",
libraryName: "MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
members: {
Host: "localhost",
Port: 8080,
Debug: false,
},
};
const buf = serialize(obj);Value types
NrbfValue maps .NET types to JavaScript primitives:
| .NET type | JavaScript type |
|---|---|
| null | null |
| Boolean | boolean |
| Byte, Int16, Int32, SByte, UInt16, UInt32, Single, Double | number |
| Int64, UInt64, TimeSpan | bigint |
| Char, Decimal, String | string |
| DateTime | DateTime ({ ticks: bigint; kind: DateTimeKind }) |
| Class / object | NrbfObject |
| Single-dimensional array | NrbfValue[] |
| Multi-dimensional / jagged / offset array | NrbfArray |
NrbfObject
interface NrbfObject {
typeName: string;
libraryName?: string; // absent for system-library classes
memberTypes?: { [name: string]: PrimitiveTypeEnumeration };
members: { [name: string]: NrbfValue };
}memberTypes is populated by the deserializer to preserve exact primitive types (e.g. Single vs Double, UInt32 vs Int32) and is used by the serializer to avoid lossy inference on round-trip. You can supply it yourself when constructing objects that need exact primitive typing:
import { PrimitiveTypeEnumeration } from "ms-nrbf-js";
const obj: NrbfObject = {
typeName: "Stats",
memberTypes: { ratio: PrimitiveTypeEnumeration.Single },
members: { ratio: 3.14 },
};NrbfArray
Multi-dimensional, jagged, and lower-bounded arrays are represented as NrbfArray. Elements are stored flat in row-major order.
interface NrbfArray {
arrayType: BinaryArrayTypeEnumeration; // Rectangular, Jagged, *Offset, …
lengths: number[]; // per-dimension length
lowerBounds?: number[]; // present for *Offset variants
elementBinaryType: BinaryTypeEnumeration;
elementPrimitiveType?: PrimitiveTypeEnumeration;
elementClassName?: string;
elementLibraryName?: string;
elements: NrbfValue[];
}NrbfMethodCall / NrbfMethodReturn
interface NrbfMethodCall {
kind: "MethodCall";
methodName: string;
typeName: string;
callContext?: string | NrbfObject;
args?: NrbfValue[];
}
interface NrbfMethodReturn {
kind: "MethodReturn";
returnValue?: NrbfValue;
exception?: NrbfObject;
callContext?: string | NrbfObject;
args?: NrbfValue[];
}Known limitations
- CJS — this package is ESM-only (
"type": "module").
License
MIT
