Skip to content

Commit

Permalink
nt string and short string added
Browse files Browse the repository at this point in the history
  • Loading branch information
jkulvich committed Jun 6, 2020
1 parent 552c35b commit a200e95
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 83 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ Or it can be used as a part of big binary serialization library.
- [ ] uint64 // ES2020 only with BigInt
- [ ] float
- [ ] double
- [ ] bool
- [x] bool
- [ ] string
- [ ] ntstring // Null Terminated String (default)
- [ ] shstring // Short String (255 bytes max)
- [ ] fxstring // String with fixed size. Null Terminated if less than size
- [x] string // Null Terminated String (default)
- [x] short-string // Short String (255 bytes max)
- [ ] fixed-string // String with fixed size. Null Terminated if less than size

# Examples

Expand Down
8 changes: 4 additions & 4 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@
- [ ] uint64 // Только ES2020 с BigInt
- [ ] float
- [ ] double
- [ ] bool
- [x] bool
- [ ] string
- [ ] ntstring // Строка завершающаяся null символом (стандартная)
- [ ] shstring // Короткая строка (максимум 255 байт)
- [ ] fxstring // Строка фиксированного размера. Завершается null, если короче размера
- [x] string // Строка завершающаяся null символом (стандартная)
- [x] short-string // Короткая строка (максимум 255 байт)
- [ ] fixed-string // Строка фиксированного размера. Завершается null, если короче размера

# Примеры

Expand Down
76 changes: 6 additions & 70 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,8 @@
import * as bytes from "@/bytes"
import {assertIntBytesLength} from "@/checks";

export default class ToBin {

// Casts unsigned byte to Uint8Array
static byte(num: number, littleEndian = false) {
return bytes.fromInt(num, 1, false, littleEndian)
}

// Casts bytes to unsigned byte
static fromByte(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, 1)
return bytes.toInt(data, false, littleEndian)
}

// Casts signed byte to Uint8Array
static sbyte(num: number, littleEndian = false) {
return bytes.fromInt(num, 1, true, littleEndian)
}

// Casts bytes to signed byte
static fromSByte(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, 1)
return bytes.toInt(data, true, littleEndian)
}

// Casts signed int16 to Uint8Array
static int16(num: number, littleEndian = false) {
return bytes.fromInt(num, 2, true, littleEndian)
}

// Casts bytes to signed int16
static fromInt16(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, 2)
return bytes.toInt(data, true, littleEndian)
}

// Casts unsigned int16 to Uint8Array
static uint16(num: number, littleEndian = false) {
return bytes.fromInt(num, 2, false, littleEndian)
}

// Casts bytes to unsigned int16
static fromUInt16(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, 2)
return bytes.toInt(data, false, littleEndian)
}

// Casts signed int32 to Uint8Array
static int32(num: number, littleEndian = false) {
return bytes.fromInt(num, 4, true, littleEndian)
}

// Casts bytes to signed int32
static fromInt32(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, 2)
return bytes.toInt(data, true, littleEndian)
}

// Casts unsigned int32 to Uint8Array
static uint32(num: number, littleEndian = false) {
return bytes.fromInt(num, 4, false, littleEndian)
}

// Casts bytes to unsigned int32
static fromUInt32(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, 2)
return bytes.toInt(data, false, littleEndian)
}
import * as convert from "@/convert"
import {DataSize, DataType} from "@/types";

export default {
...convert,
size: DataSize,
type: DataType,
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"ts-mocha": "^7.0.0",
"ts-node": "^8.10.2",
"tsconfig-paths": "^3.9.0",
"typedoc": "^0.17.7",
"typescript": "^3.9.5"
}
}
4 changes: 4 additions & 0 deletions src/__tests__/bytes.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import {DataType} from "@/types";

const assert = require("assert").strict
import * as bytes from "@/bytes"
import * as convert from "@/convert"
import {convertString} from "@/convert";

describe('fromInt', () => {
[
Expand Down
34 changes: 34 additions & 0 deletions src/__tests__/convert.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {DataType} from "@/types";

const assert = require("assert").strict
import * as bytes from "@/bytes"
import * as convert from "@/convert"
import {convertString} from "@/convert";

describe('nt strings to bin to str', () => {
[
{data: "hello"},
{data: "Hi, how are you?"},
{data: "Тестовая строка"},
].forEach(test => {
it(`${test.data} to bin <-> str`, () => {
const data = convert.convertString(test.data)
const str = convert.parseString(data)
assert.deepEqual(str, test.data)
})
})
})

describe('short strings to bin to str', () => {
[
{data: "hello"},
{data: "Hi, how are you?"},
{data: "Тестовая строка"},
].forEach(test => {
it(`${test.data} to bin <-> str`, () => {
const data = convert.convertShortString(test.data)
const str = convert.parseShortString(data)
assert.deepEqual(str, test.data)
})
})
})
2 changes: 1 addition & 1 deletion src/checks.ts → src/asserts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function assertInteger(num: number) {
}

// Checks that the value in the size
export function assertIntSize(num: number, size: number, sign = false) {
export function assertIntValue(num: number, size: number, sign = false) {
const fullBits = 256 ** size - 1
const max = sign ? (fullBits / 2) | 0 : fullBits
const min = sign ? -(max + 1) : 0
Expand Down
4 changes: 2 additions & 2 deletions src/bytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
Set of functions for working with bytes
*/

import {assertIntBytesLength, assertInteger, assertIntSize, assertSize} from "@/checks";
import {assertIntBytesLength, assertInteger, assertIntValue, assertSize} from "@/asserts";

// Returns bytes for integer number
export function fromInt(num: number, size: number, sign = false, littleEndian = false) {
assertInteger(num)
assertSize(size)
assertIntSize(num, size, sign)
assertIntValue(num, size, sign)

const bytes = new Uint8Array(size)
for (let i = 0; i < size; i++) {
Expand Down
120 changes: 120 additions & 0 deletions src/convert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import * as bytes from "./bytes"
import {DataSize, DataType} from "@/types";
import {assertIntBytesLength} from "@/asserts";

// Conversion error
class ConvertError extends Error {
name = "Convert"
}

export function convertSByte(value: number) {
return bytes.fromInt(value, DataSize.Byte, true)
}

export function parseSByte(data: Uint8Array) {
assertIntBytesLength(data, DataSize.Byte)
return bytes.toInt(data, true)
}

export function convertByte(value: number) {
return bytes.fromInt(value, DataSize.Byte, false)
}

export function parseByte(data: Uint8Array) {
assertIntBytesLength(data, DataSize.Byte)
return bytes.toInt(data, false)
}

export function convertInt16(value: number, littleEndian = false) {
return bytes.fromInt(value, DataSize.Word, true, littleEndian)
}

export function parseInt16(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, DataSize.Word)
return bytes.toInt(data, true, littleEndian)
}

export function convertUInt16(value: number, littleEndian = false) {
return bytes.fromInt(value, DataSize.Word, false, littleEndian)
}

export function parseUInt16(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, DataSize.Word)
return bytes.toInt(data, false, littleEndian)
}

export function convertInt32(value: number, littleEndian = false) {
return bytes.fromInt(value, DataSize.DWord, true, littleEndian)
}

export function parseInt32(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, DataSize.DWord)
return bytes.toInt(data, true, littleEndian)
}

export function convertUInt32(value: number, littleEndian = false) {
return bytes.fromInt(value, DataSize.DWord, false, littleEndian)
}

export function parseUInt32(data: Uint8Array, littleEndian = false) {
assertIntBytesLength(data, DataSize.DWord)
return bytes.toInt(data, false, littleEndian)
}

export function convertBool(value: boolean) {
return bytes.fromInt(value ? 1 : 0, DataSize.Byte, false)
}

export function parseBool(data: Uint8Array) {
assertIntBytesLength(data, DataSize.Byte)
return bytes.toInt(data, false, false) > 0
}

export function convertString(value: string) {
const data = new TextEncoder().encode(value)
const buff = new Uint8Array(data.length + 1)
buff.set(data)
buff.set([0], data.length)
return buff
}

export function parseString(data: Uint8Array, encoding = "utf-8") {
for (let i = 0; i < data.length; i++) {
if (data[i] === 0) {
const str = data.slice(0, i)
return new TextDecoder(encoding).decode(str)
}
}
throw new ConvertError(`endless string without \\0 at the end of the bytes array`)
}

export function convertShortString(value: string) {
const data = new TextEncoder().encode(value)
if (data.length > 255)
throw new ConvertError(`too long for short string, expected less 256, got: ${data.length}`)
const buff = new Uint8Array(data.length + 1)
buff[0] = data.length
buff.set(data, 1)
return buff
}

export function parseShortString(data: Uint8Array, encoding = "utf-8") {
if (data.length === 0)
throw new ConvertError(`empty bytes array, it isn't correct string format even empty string`)
const length = data[0]
return new TextDecoder(encoding).decode(data.slice(1, length + 1))
}


// // Converts any data array to bytes array
// export function convertSequence(type: DataType | string, value: Array<any>, littleEndian = false) {
// let buffer = new Uint8Array(0)
// value.forEach(val => {
// const data = convert(type, val, littleEndian)
// const newbuf = new Uint8Array(buffer.length + data.length)
// newbuf.set(buffer)
// newbuf.set(data, buffer.length)
// buffer = newbuf
// })
// return buffer
// }
30 changes: 30 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Shortcuts for most common data sizes
export enum DataSize {
Byte = 1,
Word = 2,
DWord = 4,
QWord = 8,
TWord = 10,
OWord = 16,
YWord = 32,
ZWord = 64,
NullTerminated = 0,
}

// Shortcuts for most common data types
export enum DataType {
Byte = "byte",
SByte = "sbyte",
Int16 = "int16",
UInt16 = "uint16",
Int32 = "int32",
UInt32 = "uint32",
Int64 = "int64",
UInt64 = "uint64",
Float = "float",
Double = "double",
Bool = "bool",
String = "string",
ShortString = "short-string",
FixedString = "fixed-string",
}
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"paths": {
"@/*": [
"src/*"
],
"^/*": [
"./*"
]
}
},
Expand Down
Loading

0 comments on commit a200e95

Please sign in to comment.