Skip to content

Commit

Permalink
A New Writer-Up
Browse files Browse the repository at this point in the history
Additions:
- Added checks to the start of the `write` function and `Writer` constructor. TypeScript type definitions coming soon! I have a tab open about it right now :)

Changes:
- Rewrote the `write` function and `Writer` class, a similar set of changes as to what I did over on the reading side of things yesterday.
- One of the bigger changes to the write methods, now each one has all of it's logic built in, as now there's no more `write` method, only each method for writing each type. It is a little more code, but it is a bit better at showing what each function does.
- For each of the write methods with for loops, each one now uses either `for of` or `for in` loops where possible, rather than just a standard `for` loop. I like the simplicity of those a lot, and I realized that they could apply great here too.
- Added a few more variables to break up some of the looping functions, as it was pretty complex to comprehend what each section was selecting. It should also be a bit easier to debug with those in there too, since you can just add a `console.log()` to see what the variable's value is, rather than having to write the call out again to break part of it up to get the intermediate values in there.

Oh yeah!
- Listening to Closure / Continuation for the second time through as of now, "Of The New Day" right now! First time listening to it yesterday afternoon, wow did they do a great job! Can't believe PT is releasing new material again.
- Finally found a nice version of Insignificance on YouTube, so that will probably be my copy of that eventually. I also will be getting Yellow Hedgerow Dreamscape too, the album that is. The song is epic, and the extra hard to find compilation album is an extension of that. There are more and more cool hidden gems out there, you just have to look a little harder to find them!
- Oh yeah, and I came across their first concert on Bandcamp too, that is also a likely must buy! Back in 1993, at Nag's Head, an extra epic venue that used to be around. Just read that they turned it into flats in 2018 I heard, bummer! The sound quality on the recording was great, even for coming up on 30 years ago. I was -10 :O
- Ok, and I have to mention how much I love Up the Downstair, just gotta say...
  • Loading branch information
Offroaders123 committed Jun 30, 2022
1 parent e642d2c commit 11f40c5
Showing 1 changed file with 85 additions and 64 deletions.
149 changes: 85 additions & 64 deletions src/write.js
Original file line number Diff line number Diff line change
@@ -1,126 +1,147 @@
import { tags } from "./tags.js";
import { compress } from "./compression.js";

export default async function write(data,{ endian, encoding } = {}){
if (!data) throw new Error("Unexpected falsy value for the data parameter");
export default async function write(data,{ endian = "big", encoding } = {}){
if (typeof data !== "object"){
throw new Error("First argument must be an object");
}
if (endian !== "big" && endian !== "little"){
throw new Error(`Endian property must be set to either "big" or "little"`);
}

const writer = new Writer(endian);
const { name, value } = data;

writer.byte(tags.compound);
writer.string(data.name);
writer.compound(data.value);
writer.string(name);
writer.compound(value);

let result = writer.getData();

if (typeof encoding !== "undefined"){
if (encoding !== undefined){
result = await compress(result,{ encoding });
}

return typeof Buffer !== "undefined" ? Buffer.from(result) : result;
}

class Writer {
constructor(endian) {
this.buffer = new ArrayBuffer(1024);

this.dataView = new DataView(this.buffer);
this.arrayView = new Uint8Array(this.buffer);

if (endian !== "big" && endian !== "little"){
throw new Error(`First argument must be set to either "big" or "little"`);
}

this.offset = 0;
this.endian = (endian === "little");

this.endian = endian;
this.buffer = new ArrayBuffer(1024);
this.view = new DataView(this.buffer);
this.data = new Uint8Array(this.buffer);
}
accommodate(size) {
const requiredLength = this.offset + size;
if (this.buffer.byteLength >= requiredLength) return;
const required = this.offset + size;
const { byteLength } = this.buffer;
if (byteLength >= required) return;

let newLength = this.buffer.byteLength;
while (newLength < requiredLength) newLength *= 2;
let length = byteLength;
while (length < required){
length *= 2;
}

const newBuffer = new ArrayBuffer(newLength);
const newArrayView = new Uint8Array(newBuffer);
newArrayView.set(this.arrayView);
const buffer = new ArrayBuffer(length);
const data = new Uint8Array(buffer);
data.set(this.data);

if (this.offset > this.buffer.byteLength) newArrayView.fill(0,this.buffer.byteLength,this.offset);
if (this.offset > byteLength){
data.fill(0,byteLength,this.offset);
}

this.buffer = newBuffer;
this.dataView = new DataView(newBuffer);
this.arrayView = newArrayView;
}
write(type,size,value) {
this.accommodate(size);
this.dataView[`set${type}`](this.offset,value,(this.endian === "little"));
this.offset += size;
return this;
this.buffer = buffer;
this.data = data;
this.view = new DataView(this.buffer);
}
getData() {
this.accommodate(0);
const result = this.buffer.slice(0,this.offset);
return typeof Buffer !== "undefined" ? Buffer.from(result) : result;
}
byte(value) {
return this.write("Int8",1,value);
}
ubyte(value) {
return this.write("Uint8",1,value);
this.accommodate(1);
this.view.setInt8(this.offset,value);
this.offset += 1;
}
short(value) {
return this.write("Int16",2,value);
this.accommodate(2);
this.view.setInt16(this.offset,value,this.endian);
this.offset += 2;
}
int(value) {
return this.write("Int32",4,value);
this.accommodate(4);
this.view.setInt32(this.offset,value,this.endian);
this.offset += 4;
}
float(value) {
return this.write("Float32",4,value);
this.accommodate(4);
this.view.setFloat32(this.offset,value,this.endian);
this.offset += 4;
}
double(value) {
return this.write("Float64",8,value);
this.accommodate(8);
this.view.setFloat64(this.offset,value,this.endian);
this.offset += 8;
}
long(value) {
return this.write("BigInt64",8,value);
this.accommodate(8);
this.view.setBigInt64(this.offset,value,this.endian);
this.offset += 8;
}
byteArray(value) {
this.int(value.length);
this.accommodate(value.length);
this.arrayView.set(value,this.offset);
this.offset += value.length;
return this;
const { length } = value;
this.accommodate(length);
this.data.set(value,this.offset);
this.offset += length;
}
intArray(value) {
this.int(value.length);
for (let i = 0; i < value.length; i++){
this.int(value[i]);
const { length } = value;
this.int(length);
for (const entry of value){
this.int(entry);
}
return this;
}
longArray(value) {
this.int(value.length);
for (let i = 0; i < value.length; i++){
this.long(value[i]);
const { length } = value;
this.int(length);
for (const entry of value){
this.long(entry);
}
return this;
}
string(value) {
const bytes = new TextEncoder().encode(value);
this.short(bytes.length);
this.accommodate(bytes.length);
this.arrayView.set(bytes,this.offset);
this.offset += bytes.length;
return this;
value = new TextEncoder().encode(value);
const { length } = value;
this.short(length);
this.accommodate(length);
this.data.set(value,this.offset);
this.offset += length;
}
list(value) {
this.byte(tags[value.type]);
this.int(value.value.length);
for (let i = 0; i < value.value.length; i++){
this[value.type](value.value[i]);
const { type } = value;
const tag = tags[type];
const entries = value.value;
const { length } = entries;
this.byte(tag);
this.int(length);
for (const entry of entries){
this[type](entry);
}
}
compound(value) {
for (const key in value){
this.byte(tags[value[key].type]);
const entry = value[key];
const { type } = entry;
const tag = tags[type];
this.byte(tag);
this.string(key);
this[value[key].type](value[key].value);
this[type](entry.value);
}
this.byte(tags.end);
return this;
}
}

0 comments on commit 11f40c5

Please sign in to comment.