Skip to content

Latest commit

 

History

History
1006 lines (967 loc) · 29.9 KB

decode.mdx

File metadata and controls

1006 lines (967 loc) · 29.9 KB

import { Tabs, Tab } from 'nextra-theme-docs' import Alert from '@mui/material/Alert'; import AlertTitle from '@mui/material/AlertTitle';

decode() functions

<Tabs items={[ typia, TypeGuardError.ts, IValidation.ts, Resolved.ts, ]}>

export namespace protobuf {
  export function decode<T>(buffer: Uint8Array): Resolved<T>;
  export function isDecode<T>(buffer: Uint8Array): Resolved<T> | null;
  export function assertDecode<T>(buffer: Uint8Array): Resolved<T>;
  export function validateDecode<T>(
    buffer: Uint8Array,
  ): IValidation<Resolved<T>>;
}
```typescript copy export class TypeGuardError extends Error { public readonly method: string; public readonly path: string | undefined; public readonly expected: string; public readonly value: any; } ``` ```typescript copy export type IValidation = IValidation.ISuccess | IValidation.IFailure; export namespace IValidation { export interface ISuccess { success: true; data: T; } export interface IFailure { success: false; errors: IError[]; } export interface IError { path: string; expected: string; value: any; } } ``` ```typescript showLineNumbers copy /** * Resolved type erased every methods. * * `Resolved` is a type of TMP (Type Meta Programming) type which converts * its argument as a resolved type that erased every method properties. * * If the target argument is a built-in class which returns its origin primitive type * through the `valueOf()` method like the `String` or `Number`, its return type would * be the `string` or `number`. Otherwise, the built-in class does not have the * `valueOf()` method, the return type would be same with the target argument. * * Otherwise, the target argument is a type of custom class, all of its custom methods * would be erased and its prototype would be changed to the primitive `object`. * Therefore, return type of the TMP type finally be the resolved object. * * Before | After * ------------------------|---------------------------------------- * `Boolean` | `boolean` * `Number` | `number` * `BigInt` | `bigint` * `String` | `string` * `Class` | `interface` * Native Class or Others | No change * * @template T Target argument type. * @author Jeongho Nam - https://github.com/samchon * @author Kyungsu Kang - https://github.com/kakasoo */ export type Resolved = Equal> extends true ? T : ResolvedMain;

type Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;

type ResolvedMain = T extends [never] ? never // (special trick for jsonable | null) type : ValueOf extends boolean | number | bigint | string ? ValueOf : T extends Function ? never : T extends object ? ResolvedObject : ValueOf;

type ResolvedObject = T extends Array ? IsTuple extends true ? ResolvedTuple : ResolvedMain[] : T extends Set ? Set<ResolvedMain> : T extends Map<infer K, infer V> ? Map<ResolvedMain, ResolvedMain> : T extends WeakSet | WeakMap<any, any> ? never : T extends | Date | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | BigUint64Array | Int8Array | Int16Array | Int32Array | BigInt64Array | Float32Array | Float64Array | ArrayBuffer | SharedArrayBuffer | DataView | Blob | File ? T : { [P in keyof T]: ResolvedMain<T[P]>; };

type ResolvedTuple<T extends readonly any[]> = T extends [] ? [] : T extends [infer F] ? [ResolvedMain] : T extends [infer F, ...infer Rest extends readonly any[]] ? [ResolvedMain, ...ResolvedTuple] : T extends [(infer F)?] ? [ResolvedMain?] : T extends [(infer F)?, ...infer Rest extends readonly any[]] ? [ResolvedMain?, ...ResolvedTuple] : [];

type IsTuple<T extends readonly any[] | { length: number }> = [T] extends [ never, ] ? false : T extends readonly any[] ? number extends T["length"] ? false : true : false;

type ValueOf = IsValueOf<Instance, Boolean> extends true ? boolean : IsValueOf<Instance, Number> extends true ? number : IsValueOf<Instance, String> extends true ? string : Instance;

type IsValueOf<Instance, Object extends IValueOf> = Instance extends Object ? Object extends IValueOf ? Instance extends Primitive ? false : true // not Primitive, but Object : false // cannot be : false;

interface IValueOf { valueOf(): T; }

  </Tab>
</Tabs>

Protocol Buffer Decoder.

You can easily convert a Protocol Buffer's binary data to a JavaScript object, without any extra Protocol Buffer [Message Schema](./message) definition. `typia.protobuf.decode<T>()` function analyzes your type `T`, and generates a Protocol Buffer Message Schema internally.And then, it converts the binary data to a JavaScript object.

By the way, as Protocol Buffer handles binary data directly, there's no way when `input` binary data was not encoded from the `T` typed value. In that case, unexpected behavior or internal error would be occured. Therefore, I recommend you to encode binary data of Protocol Buffer from type safe encode functions like below, Use `typia.protobuf.encode<T>()` function only when you can trust it.

  - [`typia.protobuf.isEncode<T>()`](./encode)
  - [`typia.protobuf.assertEncode<T>()`](./encode)
  - [`typia.protobuf.validateEncode<T>()`](./encode)

For reference, `typia` provides type safe decorators like below, but they are just for additional type validation like `number & Minimum<7>` or `string & Format<"uuid">` cases, that are represented by [Special Tags](../validators/tags). Thus, I repeat that, you've to ensure type safety when using decoder function.

  - `typia.protobuf.isDecode<T>()`: [`typia.is<T>()`](../validators/is) + `typia.protobuf.decode<T>()`
  - `typia.protobuf.assertDecode<T>()`: [`typia.assert<T>()`](../validators/assert) + `typia.protobuf.decode<T>()`
  - `typia.protobuf.validateDecode<T>()`: [`typia.validate<T>()`](../validators/validate) + `typia.protobuf.decode<T>()`


<br/>
<Alert severity="success">
  <AlertTitle> 
    **AOT compliation** 
  </AlertTitle>

`typia.protobuf.decode<T>()` and other similar functions are still much faster than any other competitive libraries, even though they include type checking process. This is the power of AOT compilation, writing optimal dedicated code by analyzing TypeScript type, in the compilation level.

</Alert>

<Tabs items={['TypeScript Source Code', 'Compiled JavaScript File']}>
  <Tab>
```typescript copy filename="protobuf.decode.ts" showLineNumbers
import typia, { tags } from "typia";

interface ICustomer {
  id: number & tags.Type<"int32">;
  email: string & tags.Format<"email">;
  name: string;
  pet: null | ICat | IDog;
  memo: null | Map<string, string>;
  logins: Array<ICustomerLogin>;
}
interface ICat {
  type: "cat";
  name: string;
  ribbon: boolean;
}
interface IDog {
  type: "dog";
  name: string;
  hunt: boolean;
}
interface ICustomerLogin {
  success: boolean;
  href: string & tags.Format<"url">;
  referrer: string & tags.Format<"url">;
  ip: string & (tags.Format<"ipv4"> | tags.Format<"ipv6">);
  time: string & tags.Format<"date-time">;
}

const data: ICustomer = typia.random<ICustomer>();
const encoded: Uint8Array = typia.protobuf.encode(data);
typia.protobuf.decode<ICustomer>(encoded);
```javascript copy filename="protobuf.decode.js" showLineNumbers "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const typia_1 = __importDefault(require("typia")); const data = ((generator) => { const $generator = typia_1.default.random.generator; const $pick = typia_1.default.random.pick; const $ro0 = (_recursive = false, _depth = 0) => ({ id: (generator?.customs ?? $generator.customs)?.number?.([ { name: 'Type<"int32">', kind: "type", value: "int32", }, ]) ?? (generator?.integer ?? $generator.integer)(0, 100), email: (generator?.customs ?? $generator.customs)?.string?.([ { name: 'Format<"email">', kind: "format", value: "email", }, ]) ?? (generator?.email ?? $generator.email)(), name: (generator?.customs ?? $generator.customs)?.string?.([]) ?? (generator?.string ?? $generator.string)(), pet: $pick([ () => null, () => $ro1(_recursive, _recursive ? 1 + _depth : _depth), () => $ro2(_recursive, _recursive ? 1 + _depth : _depth), ])(), memo: $pick([ () => null, () => new Map( (generator?.array ?? $generator.array)(() => [ (generator?.customs ?? $generator.customs)?.string?.([]) ?? (generator?.string ?? $generator.string)(), (generator?.customs ?? $generator.customs)?.string?.([]) ?? (generator?.string ?? $generator.string)(), ]), ), ])(), logins: (generator?.array ?? $generator.array)(() => $ro3(_recursive, _recursive ? 1 + _depth : _depth), ), }); const $ro1 = (_recursive = false, _depth = 0) => ({ type: "cat", name: (generator?.customs ?? $generator.customs)?.string?.([]) ?? (generator?.string ?? $generator.string)(), ribbon: (generator?.boolean ?? $generator.boolean)(), }); const $ro2 = (_recursive = false, _depth = 0) => ({ type: "dog", name: (generator?.customs ?? $generator.customs)?.string?.([]) ?? (generator?.string ?? $generator.string)(), hunt: (generator?.boolean ?? $generator.boolean)(), }); const $ro3 = (_recursive = false, _depth = 0) => ({ success: (generator?.boolean ?? $generator.boolean)(), href: (generator?.customs ?? $generator.customs)?.string?.([ { name: 'Format<"url">', kind: "format", value: "url", }, ]) ?? (generator?.url ?? $generator.url)(), referrer: (generator?.customs ?? $generator.customs)?.string?.([ { name: 'Format<"url">', kind: "format", value: "url", }, ]) ?? (generator?.url ?? $generator.url)(), ip: $pick([ () => (generator?.customs ?? $generator.customs)?.string?.([ { name: 'Format<"ipv4">', kind: "format", value: "ipv4", }, ]) ?? (generator?.ipv4 ?? $generator.ipv4)(), () => (generator?.customs ?? $generator.customs)?.string?.([ { name: 'Format<"ipv6">', kind: "format", value: "ipv6", }, ]) ?? (generator?.ipv6 ?? $generator.ipv6)(), ])(), time: (generator?.customs ?? $generator.customs)?.string?.([ { name: 'Format<"date-time">', kind: "format", value: "date-time", }, ]) ?? (generator?.datetime ?? $generator.datetime)(), }); return $ro0(); })(); const encoded = ((input) => { const $throws = typia_1.default.protobuf.encode.throws; const $Sizer = typia_1.default.protobuf.encode.Sizer; const $Writer = typia_1.default.protobuf.encode.Writer; const encoder = (writer) => { const $peo0 = (input) => { // property "id"; writer.uint32(8); writer.int32(input.id); // property "email"; writer.uint32(18); writer.string(input.email); // property "name"; writer.uint32(26); writer.string(input.name); // property "pet"; if (null !== input.pet) { if ("cat" === input.pet.type) (() => { // 4 -> ICat; writer.uint32(34); writer.fork(); $peo1(input.pet); writer.ldelim(); })(); else if ("dog" === input.pet.type) (() => { // 5 -> IDog; writer.uint32(42); writer.fork(); $peo2(input.pet); writer.ldelim(); })(); else $throws({ expected: "(ICat | IDog)", value: input.pet, }); } // property "memo"; if (null !== input.memo) { for (const [key, value] of input.memo) { writer.uint32(50); writer.fork(); writer.uint32(10); writer.string(key); writer.uint32(18); writer.string(value); writer.ldelim(); } } // property "logins"; if (0 !== input.logins.length) { for (const elem of input.logins) { // 7 -> ICustomerLogin; writer.uint32(58); writer.fork(); $peo3(elem); writer.ldelim(); } } }; const $peo1 = (input) => { // property "type"; writer.uint32(10); writer.string(input.type); // property "name"; writer.uint32(18); writer.string(input.name); // property "ribbon"; writer.uint32(24); writer.bool(input.ribbon); }; const $peo2 = (input) => { // property "type"; writer.uint32(10); writer.string(input.type); // property "name"; writer.uint32(18); writer.string(input.name); // property "hunt"; writer.uint32(24); writer.bool(input.hunt); }; const $peo3 = (input) => { // property "success"; writer.uint32(8); writer.bool(input.success); // property "href"; writer.uint32(18); writer.string(input.href); // property "referrer"; writer.uint32(26); writer.string(input.referrer); // property "ip"; writer.uint32(34); writer.string(input.ip); // property "time"; writer.uint32(42); writer.string(input.time); }; const $io1 = (input) => "cat" === input.type && "string" === typeof input.name && "boolean" === typeof input.ribbon; const $io2 = (input) => "dog" === input.type && "string" === typeof input.name && "boolean" === typeof input.hunt; const $io3 = (input) => "boolean" === typeof input.success && "string" === typeof input.href && /^(?:https?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu.test( input.href, ) && "string" === typeof input.referrer && /^(?:https?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu.test( input.referrer, ) && "string" === typeof input.ip && (/^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/.test( input.ip, ) || /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))$/i.test( input.ip, )) && "string" === typeof input.time && !isNaN(new Date(input.time).getTime()); const $iu0 = (input) => (() => { if ("cat" === input.type) return $io1(input); else if ("dog" === input.type) return $io2(input); else return false; })(); //ICustomer; $peo0(input); return writer; }; const sizer = encoder(new $Sizer()); const writer = encoder(new $Writer(sizer)); return writer.buffer(); })(data); ((input) => { const $Reader = typia_1.default.protobuf.decode.Reader; const $pdo0 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { id: undefined, email: "", name: "", pet: null, memo: null, logins: [], }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // int32; output.id = reader.int32(); break; case 2: // string; output.email = reader.string(); break; case 3: // string; output.name = reader.string(); break; case 4: // ICat; output.pet = $pdo1(reader, reader.uint32()); break; case 5: // IDog; output.pet = $pdo2(reader, reader.uint32()); break; case 6: // type: Map; (() => { output.memo ??= new Map(); const piece = reader.uint32() + reader.index(); const entry = { key: "", value: "", }; while (reader.index() < piece) { const kind = reader.uint32(); switch (kind >>> 3) { case 1: // string; entry.key = reader.string(); break; case 2: // string; entry.value = reader.string(); break; default: reader.skipType(kind & 7); break; } } output.memo.set(entry.key, entry.value); })(); break; case 7: // type: Array; output.logins.push($pdo3(reader, reader.uint32())); break; default: reader.skipType(tag & 7); break; } } return output; }; const $pdo1 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { type: undefined, name: "", ribbon: undefined, }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // string; output.type = reader.string(); break; case 2: // string; output.name = reader.string(); break; case 3: // bool; output.ribbon = reader.bool(); break; default: reader.skipType(tag & 7); break; } } return output; }; const $pdo2 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { type: undefined, name: "", hunt: undefined, }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // string; output.type = reader.string(); break; case 2: // string; output.name = reader.string(); break; case 3: // bool; output.hunt = reader.bool(); break; default: reader.skipType(tag & 7); break; } } return output; }; const $pdo3 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { success: undefined, href: "", referrer: "", ip: "", time: "", }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // bool; output.success = reader.bool(); break; case 2: // string; output.href = reader.string(); break; case 3: // string; output.referrer = reader.string(); break; case 4: // string; output.ip = reader.string(); break; case 5: // string; output.time = reader.string(); break; default: reader.skipType(tag & 7); break; } } return output; }; const reader = new $Reader(input); return $pdo0(reader); })(encoded); ```

Reusable functions

<Tabs items={[ typia, TypeGuardError.ts, IValidation.ts, Resolved.ts, ]}>

export namespace protobuf {
  export function createDecode<T>(): (buffer: Uint8Array) => Resolved<T>;
  export function createIsDecode<T>: (buffer: Uint8Array) => Resolved<T> | null;
  export function createAssertDecode<T>(): (buffer: Uint8Array) => Resolved<T>;
  export function createValidateDecode<T>(): (
      buffer: Uint8Array
  ) => IValidation<Resolved<T>>;
}
```typescript copy export class TypeGuardError extends Error { public readonly method: string; public readonly path: string | undefined; public readonly expected: string; public readonly value: any; } ``` ```typescript copy export type IValidation = IValidation.ISuccess | IValidation.IFailure; export namespace IValidation { export interface ISuccess { success: true; data: T; } export interface IFailure { success: false; errors: IError[]; } export interface IError { path: string; expected: string; value: any; } } ``` ```typescript showLineNumbers copy import typia, { tags } from "typia";

interface ICustomer { id: number & tags.Type<"int32">; email: string & tags.Format<"email">; name: string; pet: null | ICat | IDog; memo: null | Map<string, string>; logins: Array; } interface ICat { type: "cat"; name: string; ribbon: boolean; } interface IDog { type: "dog"; name: string; hunt: boolean; } interface ICustomerLogin { success: boolean; href: string & tags.Format<"url">; referrer: string & tags.Format<"url">; ip: string & (tags.Format<"ipv4"> | tags.Format<"ipv6">); time: string & tags.Format<"date-time">; }

const data: ICustomer = typia.random(); const encoded: Uint8Array = typia.protobuf.encode(data); typia.protobuf.decode(encoded);

  </Tab>
</Tabs>

Reusable `typia.protobuf.decode<T>()` function generators.

If you repeat to call `typia.protobuf.decode<T>()` function on the same type, size of JavaScript files would be larger because of duplicated AOT compilation. To prevent it, you can generate reusable function through `typia.protobuf.createDecode<T>()` function.

Just look at the code below, then you may understand how to use it.

<Tabs items={['TypeScript Source Code', 'Compiled JavaScript File']}>
  <Tab>
```typescript copy filename="protobuf.createDecode.ts" showLineNumbers
import typia, { tags } from "typia";

export const encode = typia.protobuf.createDecode<ICustomer>();

interface ICustomer {
  id: number & tags.Type<"int32">;
  email: string & tags.Format<"email">;
  name: string;
  pet: null | ICat | IDog;
  memo: null | Map<string, string>;
  logins: Array<ICustomerLogin>;
}
interface ICat {
  type: "cat";
  name: string;
  ribbon: boolean;
}
interface IDog {
  type: "dog";
  name: string;
  hunt: boolean;
}
interface ICustomerLogin {
  success: boolean;
  href: string & tags.Format<"url">;
  referrer: string & tags.Format<"url">;
  ip: string & (tags.Format<"ipv4"> | tags.Format<"ipv6">);
  time: string & tags.Format<"date-time">;
}
```javascript copy filename="protobuf.createDecode.js" showLineNumbers "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.encode = void 0; const typia_1 = __importDefault(require("typia")); const encode = (input) => { const $Reader = typia_1.default.protobuf.createDecode.Reader; const $pdo0 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { id: undefined, email: "", name: "", pet: null, memo: null, logins: [], }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // int32; output.id = reader.int32(); break; case 2: // string; output.email = reader.string(); break; case 3: // string; output.name = reader.string(); break; case 4: // ICat; output.pet = $pdo1(reader, reader.uint32()); break; case 5: // IDog; output.pet = $pdo2(reader, reader.uint32()); break; case 6: // type: Map; (() => { output.memo ??= new Map(); const piece = reader.uint32() + reader.index(); const entry = { key: "", value: "", }; while (reader.index() < piece) { const kind = reader.uint32(); switch (kind >>> 3) { case 1: // string; entry.key = reader.string(); break; case 2: // string; entry.value = reader.string(); break; default: reader.skipType(kind & 7); break; } } output.memo.set(entry.key, entry.value); })(); break; case 7: // type: Array; output.logins.push($pdo3(reader, reader.uint32())); break; default: reader.skipType(tag & 7); break; } } return output; }; const $pdo1 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { type: undefined, name: "", ribbon: undefined, }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // string; output.type = reader.string(); break; case 2: // string; output.name = reader.string(); break; case 3: // bool; output.ribbon = reader.bool(); break; default: reader.skipType(tag & 7); break; } } return output; }; const $pdo2 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { type: undefined, name: "", hunt: undefined, }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // string; output.type = reader.string(); break; case 2: // string; output.name = reader.string(); break; case 3: // bool; output.hunt = reader.bool(); break; default: reader.skipType(tag & 7); break; } } return output; }; const $pdo3 = (reader, length = -1) => { length = length < 0 ? reader.size() : reader.index() + length; const output = { success: undefined, href: "", referrer: "", ip: "", time: "", }; while (reader.index() < length) { const tag = reader.uint32(); switch (tag >>> 3) { case 1: // bool; output.success = reader.bool(); break; case 2: // string; output.href = reader.string(); break; case 3: // string; output.referrer = reader.string(); break; case 4: // string; output.ip = reader.string(); break; case 5: // string; output.time = reader.string(); break; default: reader.skipType(tag & 7); break; } } return output; }; const reader = new $Reader(input); return $pdo0(reader); }; exports.encode = encode; ```

References

Protocol Buffer supports special numeric types like int32 or uint64 that are not supported in TypeScript. Also, types of Protocol Buffer cannot fully meet TypeScript type specs either, as expression power of TypeScript types are much stronger than Protocol Buffer.

To know how to define special numeric types like uint64, and to understand which TypeScript types are not supported in Protocol Buffer specs, it would better to read below documents. I recommend you to read them before using typia.protobuf.decode<T>() related functions.