Skip to content

Commit

Permalink
fix: get rid of ugly classes
Browse files Browse the repository at this point in the history
truly disgusting
  • Loading branch information
yamiteru committed May 2, 2024
1 parent 3c8c634 commit 7274e96
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 87 deletions.
8 changes: 4 additions & 4 deletions biome.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"$schema": "https://biomejs.dev/schemas/1.6.4/schema.json",
"files": {
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "index.ts"],
"ignore": ["node_modules"]
},
"linter": {
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "index.ts"],
"ignore": ["node_modules"],
"rules": {
"suspicious": {
Expand All @@ -15,11 +15,11 @@
}
},
"formatter": {
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "index.ts"],
"ignore": ["node_modules"]
},
"organizeImports": {
"include": ["src/**/*.ts"],
"include": ["src/**/*.ts", "index.ts"],
"ignore": ["node_modules"]
}
}
36 changes: 19 additions & 17 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import { Protocol } from "@types";
import { DataDecoder } from "./src/decoder";
import { DataEncoder } from "./src/encoder";

const mainEncoder = new DataEncoder();
const mainDecoder = new DataDecoder();
import type { Protocol } from "@types";
import { decode } from "./src/decoder";
import { encode } from "./src/encoder";

const register = {
type: "object",
properties: [
{ key: "name", type: "ascii" },
{ key: "email", type: "ascii" },
{ key: "password", type: "ascii" },
{ key: "age", type: "int", nullable: true, parse: (v) => {
if(<any>v < 0 || <any>v > 150) {
throw Error("Age should be between 0 and 150");
}

return v;
} },
]
{
key: "age",
type: "int",
nullable: true,
parse: (v) => {
if (<any>v < 0 || <any>v > 150) {
throw Error("Age should be between 0 and 150");
}

return v;
},
},
],
} satisfies Protocol.Any;

const value = {
name: "Miroslav Vrsecky",
email: "[email protected]",
password: "Test123456",
age: null
age: null,
};

const a = mainEncoder.encode(register, value);
const a = encode(register, value);

console.log(a);

const b = mainDecoder.decode(register, a);
const b = decode(register, a);

console.log(b);
60 changes: 30 additions & 30 deletions src/decoder.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
import type { Protocol } from "@types";

export class DataDecoder implements Protocol.Decoders {
private offset: number;
type Position = {
offset: number;
};

constructor() {
this.offset = 0;
}

run(type: any, view: DataView) {
if (type.nullable && view.getUint8(this.offset++) === 1) {
return null;
}

return type.parse
? type.parse((this as any)[type.type](type, view))
: (this as any)[type.type](type, view);
}

int(_: Protocol.Int, view: DataView) {
return view.getUint8(this.offset++);
}

ascii(_: Protocol.Int, view: DataView) {
const length = view.getUint8(this.offset++);
const TYPES = {
int: (position: Position, _: Protocol.Int, view: DataView) => {
return view.getUint8(position.offset++);
},
ascii: (position: Position, _: Protocol.Int, view: DataView) => {
const length = view.getUint8(position.offset++);

let result = "";

for (let i = 0; i < length; ++i) {
result += String.fromCharCode(view.getUint8(this.offset++));
result += String.fromCharCode(view.getUint8(position.offset++));
}

return result;
}

object(type: Protocol.Object, view: DataView) {
},
object: (position: Position, type: Protocol.Object, view: DataView) => {
const result: Record<string, unknown> = {};

for (let i = 0; i < type.properties.length; ++i) {
result[type.properties[i].key] = this.run(type.properties[i], view);
result[type.properties[i].key] = run(position, type.properties[i], view);
}

return result;
},
};

const run = (position: Position, type: any, view: DataView) => {
if (type.nullable && view.getUint8(position.offset++) === 1) {
return null;
}

decode(type: Protocol.Any, buffer: ArrayBuffer) {
return this.run(type, new DataView(buffer));
const result = (TYPES as any)[type.type](position, type, view);

if (type.parse) {
type.parse(result);
}
}

return result;
};

export const decode = (type: Protocol.Any, buffer: ArrayBuffer) => {
return run({ offset: 0 }, type, new DataView(buffer));
};
77 changes: 41 additions & 36 deletions src/encoder.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,52 @@
import type { Protocol } from "@types";
import type { Buffer } from "@utils";
import { alloc, check, free } from "@utils";

const TYPES = {
int: (buffer: Buffer, _: Protocol.Int, value: number) => {
check(buffer, 1);
buffer.view.setUint8(buffer.offset++, value);
},
ascii: (buffer: Buffer, _: Protocol.Ascii, value: string) => {
check(buffer, 1 + value.length);
buffer.view.setUint8(buffer.offset++, value.length);

export class DataEncoder implements Protocol.Encoders {
private buffer: ArrayBuffer;
private view: DataView;
private offset: number;

constructor() {
this.buffer = new ArrayBuffer(1024);
this.view = new DataView(this.buffer);
this.offset = 0;
}

run(type: any, value: unknown) {
if (type.nullable) {
this.view.setUint8(this.offset++, +(value === null));
for (let i = 0; i < value.length; ++i) {
buffer.view.setUint8(buffer.offset++, value.charCodeAt(i));
}
},
object: (
buffer: Buffer,
type: Protocol.Object,
value: Record<string, unknown>,
) => {
for (let i = 0; i < type.properties.length; ++i) {
run(buffer, type.properties[i], value[type.properties[i].key]);
}
},
};

(this as any)[type.type](
type,
type.parse && value !== null ? type.parse(value) : value,
);
const run = (buffer: Buffer, type: any, value: unknown) => {
if (type.nullable) {
check(buffer, 1);
buffer.view.setUint8(buffer.offset++, +(value === null));
}

int(_: Protocol.Int, value: number) {
this.view.setUint8(this.offset++, value);
if (type.parse && value !== null) {
type.parse(value);
}

ascii(_: Protocol.Ascii, value: string) {
this.view.setUint8(this.offset++, value.length);
(TYPES as any)[type.type](buffer, type, value);
};

for (let i = 0; i < value.length; ++i) {
this.view.setUint8(this.offset++, value.charCodeAt(i));
}
}
export const encode = (type: Protocol.Any, value: unknown) => {
const buffer = alloc();

object(type: Protocol.Object, value: Record<string, unknown>) {
for (let i = 0; i < type.properties.length; ++i) {
this.run(type.properties[i], value[type.properties[i].key]);
}
}
run(buffer, type, value);

encode(type: Protocol.Any, value: unknown) {
this.run(type, value);
return this.buffer.slice(0, this.offset);
}
}
const result = buffer.buffer.slice(0, buffer.offset);

free(buffer);

return result;
};
40 changes: 40 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export type Buffer = {
offset: number;
buffer: ArrayBuffer;
view: DataView;
};

const MAX_BUFFERS = 12;
const DEFAULT_SIZE = 1024;
const MAX_SIZE = DEFAULT_SIZE * 128;

const FREE: Buffer[] = [];

export const alloc = (): Buffer => {
if (FREE.length) {
return FREE.pop() as Buffer;
}

const buffer = new ArrayBuffer(DEFAULT_SIZE, { maxByteLength: MAX_SIZE });

return {
buffer,
view: new DataView(buffer),
offset: 0,
};
};

export const free = (buffer: Buffer) => {
if (FREE.length < MAX_BUFFERS) {
buffer.buffer.resize(DEFAULT_SIZE);
buffer.offset = 0;

FREE.push(buffer);
}
};

export const check = (buffer: Buffer, size: number) => {
if (buffer.buffer.byteLength + size > DEFAULT_SIZE) {
buffer.buffer.resize(buffer.buffer.byteLength * 2);
}
};
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"paths": {
"@types": [
"types.ts"
],
"@utils": [
"utils.ts"
]
}
},
Expand Down

0 comments on commit 7274e96

Please sign in to comment.