Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript interface is incomplete #116

Open
keichi opened this issue Jun 6, 2019 · 7 comments
Open

TypeScript interface is incomplete #116

keichi opened this issue Jun 6, 2019 · 7 comments

Comments

@keichi
Copy link
Owner

keichi commented Jun 6, 2019

In particular, ParserOptions does implement all available options (e.g., length can be a string or function too).

@mohd-akram
Copy link
Contributor

Any update on this? Having the types in the npm package would be helpful so they're always updated.

@keichi
Copy link
Owner Author

keichi commented Apr 27, 2020

I haven't had the bandwidth to work on this yet. @types/binary-parser is still more complete than the typings in this repo.

@shayded-exe
Copy link

Would you be open to a PR to improve the built-in types based on @types/binary-parser?

@keichi
Copy link
Owner Author

keichi commented Apr 4, 2022

@rshea0 Yes it would be very much appreciated! We have improved the typings since I opened this issue so I think the typings are mostly accurate now.

@cmdcolin
Copy link
Contributor

cmdcolin commented Jul 1, 2022

is it expected that e.g. new Parser().uint32('field').parse(buf) returns any? it would be very cool if the returned types could be given actual typescript typings

@keichi
Copy link
Owner Author

keichi commented Jul 3, 2022

@cmdcolin Yes, it is expected but a type-safe interface would be very cool. Do you have any good ideas on how to implement it?

@wpyoga
Copy link
Contributor

wpyoga commented Sep 6, 2022

This is a very nice feature to have. It is not impossible to implement -- data validation libraries have been doing this for quite some time. However, I have been reading Zod's source code (looks like very advanced stuff), but I haven't yet figured out a way to recreate the same effect. Also, there are other validation libraries, it's just that Zod is the one I'm most familiar with.

See below for an example using Zod, using the IPv4 header parsing example.

Notes:

  1. parsedIpHeader is the any object parsed by binary-parser.
  2. validatedIpHeader, validatedIpHeaderV2, and validatedIpHeaderV3 are the type-inferred objects validated by zod.
  3. The method-chaining approach takes up a lot of cpu resources to process. I think it's not impossible to implement in binary-parser, and maybe we can have something like
    Parser.start()
    .uint32be("id")
    ... 
    .uint8("checksum")
    .end()
    
    Where end() marks the end of the call chain, and it's the only place where the parser types are inferred.
  4. In VS Code, I get this type hint for validatedIpHeader:
    const validatedIpHeader: {
        version: number;
        headerLength: number;
        tos: number;
        packetLength: number;
        id: number;
        offset: number;
        fragOffset: number;
        ttl: number;
        protocol: number;
        checksum: number;
        src: number[];
        dst: number[];
    }
    
Example (long block of code)

// Module import
const Parser = require('binary-parser').Parser;

// Alternative way to import the module
// import { Parser } from 'binary-parser';

// Build an IP packet header Parser
const ipHeader = new Parser()
  .endianness('big')
  .bit4('version')
  .bit4('headerLength')
  .uint8('tos')
  .uint16('packetLength')
  .uint16('id')
  .bit3('offset')
  .bit13('fragOffset')
  .uint8('ttl')
  .uint8('protocol')
  .uint16('checksum')
  .array('src', {
    type: 'uint8',
    length: 4,
  })
  .array('dst', {
    type: 'uint8',
    length: 4,
  });

// Prepare buffer to parse.
const buf = Buffer.from('450002c5939900002c06ef98adc24f6c850186d1', 'hex');

// Parse buffer and show result
console.log(ipHeader.parse(buf));

// preparation

import { z } from 'zod';
const parsedIpHeader = ipHeader.parse(buf);

// typical Zod usage

const ipHeaderValidator = z.object({
  version: z.number(),
  headerLength: z.number(),
  tos: z.number(),
  packetLength: z.number(),
  id: z.number(),
  offset: z.number(),
  fragOffset: z.number(),
  ttl: z.number(),
  protocol: z.number(),
  checksum: z.number(),
  src: z.array(z.number()).length(4),
  dst: z.array(z.number()).length(4),
});

const validatedIpHeader = ipHeaderValidator.parse(parsedIpHeader);

console.log(validatedIpHeader);

// chained -- non-typical, vscode takes a long time processing this

const ipHeaderValidatorV2 = z
  .object({})
  .extend({ version: z.number() })
  .extend({ headerLength: z.number() })
  .extend({ tos: z.number() })
  .extend({ packetLength: z.number() })
  .extend({ id: z.number() })
  .extend({ offset: z.number() })
  .extend({ fragOffset: z.number() })
  .extend({ ttl: z.number() })
  .extend({ protocol: z.number() })
  // .extend({ checksum: z.number() })
  // .extend({ src: z.array(z.number()).length(4) })
  // .extend({ dst: z.array(z.number()).length(4) });
  // if the last 3 properties are uncommented, tsc will emit an error:
  // error TS2589: Type instantiation is excessively deep and possibly infinite.

const validatedIpHeaderV2 = ipHeaderValidatorV2.parse(parsedIpHeader);

console.log(validatedIpHeaderV2);

// this works, but type hint is delayed, and vscode hogs cpu processing this

const ipHeaderValidatorV3 = z
  .object({})
  .merge(z.object({ version: z.number() }))
  .merge(z.object({ headerLength: z.number() }))
  .merge(z.object({ tos: z.number() }))
  .merge(z.object({ packetLength: z.number() }))
  .merge(z.object({ id: z.number() }))
  .merge(z.object({ offset: z.number() }))
  .merge(z.object({ fragOffset: z.number() }))
  .merge(z.object({ ttl: z.number() }))
  .merge(z.object({ protocol: z.number() }))
  .merge(z.object({ checksum: z.number() }))
  .merge(z.object({ src: z.array(z.number()).length(4) }))
  .merge(z.object({ dst: z.array(z.number()).length(4) }));

const validatedIpHeaderV3 = ipHeaderValidatorV3.parse(parsedIpHeader);

console.log(validatedIpHeaderV3);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants