diff --git a/tools/js-class-c-struct-transpiler/test/build/Login.js b/tools/js-class-c-struct-transpiler/test/build/Login.js index 14b91d8..d4b3593 100644 --- a/tools/js-class-c-struct-transpiler/test/build/Login.js +++ b/tools/js-class-c-struct-transpiler/test/build/Login.js @@ -16,7 +16,12 @@ class Login { * @param {string} v sets the value of Email */ set Email(v) { - this._data.set(this._encoder.encode(v), 0); + if (v.length > 256) { + throw new Error("input is larger than buffer size of 256"); + } + const tmp = new Uint8Array(new ArrayBuffer(256)); + tmp.set(this._encoder.encode(v)) + this._ptr.set(tmp.buffer, 0); } /** * Password of the user @@ -30,25 +35,23 @@ class Login { * @param {string} v sets the value of Password */ set Password(v) { - this._data.set(this._encoder.encode(v), 256); - } - /** - * Get the struct representation of the object - * @return {Uint8Array} u8 array of the C struct. - */ - get bytes() { - return new Uint8Array(this._ptr); + if (v.length > 64) { + throw new Error("input is larger than buffer size of 64"); + } + const tmp = new Uint8Array(new ArrayBuffer(64)); + tmp.set(this._encoder.encode(v)) + this._ptr.set(tmp.buffer, 256); } /** * Constructs a new Login * * @param {{Email: string, Password: string, }} init The arguments to construct the object. - * @param {ArrayBuffer} ptr The pointer to the C struct. + * @param {Uint8Array} ptr The pointer to the C struct. */ constructor(init = {}, ptr = undefined) { this._size = 320; - this._ptr = ptr?.buffer || new ArrayBuffer(this._size); - this._data = new DataView(this._ptr); + this._ptr = ptr || new Uint8Array(this._size); + this._data = new DataView(this._ptr.buffer); this._encoder = new TextEncoder(); this._decoder = new TextDecoder(); diff --git a/tools/js-class-c-struct-transpiler/test/build/LoginRequest.js b/tools/js-class-c-struct-transpiler/test/build/LoginRequest.js index fc9269b..d0c4e7e 100644 --- a/tools/js-class-c-struct-transpiler/test/build/LoginRequest.js +++ b/tools/js-class-c-struct-transpiler/test/build/LoginRequest.js @@ -1,7 +1,7 @@ import Login from "./Login" /** * @typedef {Object} LoginRequest a request for a login - * @property Login Login user login info + * @property {Login} Login user login info */ class LoginRequest { /** @@ -16,25 +16,18 @@ class LoginRequest { * @param {Login} sets the value of Login */ set Login(v) { - this._data.set(v.bytes(), 0); - } - /** - * Get the struct representation of the object - * @return {Uint8Array} u8 array of the C struct. - */ - get bytes() { - return new Uint8Array(this._ptr); + this._ptr.set(v._ptr, 0); } /** * Constructs a new LoginRequest * * @param {{Login: Login, }} init The arguments to construct the object. - * @param {ArrayBuffer} ptr The pointer to the C struct. + * @param {Uint8Array} ptr The pointer to the C struct. */ constructor(init = {}, ptr = undefined) { this._size = 320; - this._ptr = ptr?.buffer || new ArrayBuffer(this._size); - this._data = new DataView(this._ptr); + this._ptr = ptr || new Uint8Array(this._size); + this._data = new DataView(this._ptr.buffer); for (const key of Object.keys(init)) { this[key] = init[key]; diff --git a/tools/js-class-c-struct-transpiler/test/build/LoginResponse.js b/tools/js-class-c-struct-transpiler/test/build/LoginResponse.js index 8ca8868..808dd7e 100644 --- a/tools/js-class-c-struct-transpiler/test/build/LoginResponse.js +++ b/tools/js-class-c-struct-transpiler/test/build/LoginResponse.js @@ -1,6 +1,6 @@ /** * @typedef {Object} LoginResponse the response from a login request - * @property boolean logical login was successful or not + * @property {boolean} logical login was successful or not */ class LoginResponse { /** @@ -8,32 +8,25 @@ class LoginResponse { * @return {boolean} gets the value of success */ get success() { - return this._data.getboolean(0, true); + return Boolean(this._data.getInt8(0, true)); } /** * login was successful or not * @param {boolean} sets the value of success */ set success(v) { - return this._data.setboolean(0, v, true); - } - /** - * Get the struct representation of the object - * @return {Uint8Array} u8 array of the C struct. - */ - get bytes() { - return new Uint8Array(this._ptr); + return this._data.setInt8(0, v ? 1 : 0, true); } /** * Constructs a new LoginResponse * * @param {{success: boolean, }} init The arguments to construct the object. - * @param {ArrayBuffer} ptr The pointer to the C struct. + * @param {Uint8Array} ptr The pointer to the C struct. */ constructor(init = {}, ptr = undefined) { this._size = 1; - this._ptr = ptr?.buffer || new ArrayBuffer(this._size); - this._data = new DataView(this._ptr); + this._ptr = ptr || new Uint8Array(this._size); + this._data = new DataView(this._ptr.buffer); for (const key of Object.keys(init)) { this[key] = init[key]; diff --git a/tools/js-class-c-struct-transpiler/test/build/User.js b/tools/js-class-c-struct-transpiler/test/build/User.js index 1aa8e92..3c87ee0 100644 --- a/tools/js-class-c-struct-transpiler/test/build/User.js +++ b/tools/js-class-c-struct-transpiler/test/build/User.js @@ -3,8 +3,8 @@ import Vector3 from "./Vector3" /** * @typedef {Object} User The user object * @property {string} Name Name of the user - * @property Login Login user login info - * @property Vector3 Vector3 last logout position of user + * @property {Login} Login user login info + * @property {Vector3} Vector3 last logout position of user */ class User { /** @@ -19,7 +19,12 @@ class User { * @param {string} v sets the value of Name */ set Name(v) { - this._data.set(this._encoder.encode(v), 0); + if (v.length > 24) { + throw new Error("input is larger than buffer size of 24"); + } + const tmp = new Uint8Array(new ArrayBuffer(24)); + tmp.set(this._encoder.encode(v)) + this._ptr.set(tmp.buffer, 0); } /** * user login info @@ -33,7 +38,7 @@ class User { * @param {Login} sets the value of Login */ set Login(v) { - this._data.set(v.bytes(), 24); + this._ptr.set(v._ptr, 24); } /** * last logout position of user @@ -47,25 +52,18 @@ class User { * @param {Vector3} sets the value of Position */ set Position(v) { - this._data.set(v.bytes(), 344); - } - /** - * Get the struct representation of the object - * @return {Uint8Array} u8 array of the C struct. - */ - get bytes() { - return new Uint8Array(this._ptr); + this._ptr.set(v._ptr, 344); } /** * Constructs a new User * * @param {{Name: string, Login: Login, Position: Vector3, }} init The arguments to construct the object. - * @param {ArrayBuffer} ptr The pointer to the C struct. + * @param {Uint8Array} ptr The pointer to the C struct. */ constructor(init = {}, ptr = undefined) { this._size = 356; - this._ptr = ptr?.buffer || new ArrayBuffer(this._size); - this._data = new DataView(this._ptr); + this._ptr = ptr || new Uint8Array(this._size); + this._data = new DataView(this._ptr.buffer); this._encoder = new TextEncoder(); this._decoder = new TextDecoder(); diff --git a/tools/js-class-c-struct-transpiler/test/build/Vector3.js b/tools/js-class-c-struct-transpiler/test/build/Vector3.js index 946a68d..d6079ce 100644 --- a/tools/js-class-c-struct-transpiler/test/build/Vector3.js +++ b/tools/js-class-c-struct-transpiler/test/build/Vector3.js @@ -1,8 +1,8 @@ /** * @typedef {Object} Vector3 A representation of a position in 3D space - * @property Float32 f32 x coordinate - * @property Float32 f32 y coordinate - * @property Float32 f32 z coordinate + * @property {Float32} f32 x coordinate + * @property {Float32} f32 y coordinate + * @property {Float32} f32 z coordinate */ class Vector3 { /** @@ -47,23 +47,16 @@ class Vector3 { set z(v) { return this._data.setFloat32(8, v, true); } - /** - * Get the struct representation of the object - * @return {Uint8Array} u8 array of the C struct. - */ - get bytes() { - return new Uint8Array(this._ptr); - } /** * Constructs a new Vector3 * * @param {{x: Float32, y: Float32, z: Float32, }} init The arguments to construct the object. - * @param {ArrayBuffer} ptr The pointer to the C struct. + * @param {Uint8Array} ptr The pointer to the C struct. */ constructor(init = {}, ptr = undefined) { this._size = 12; - this._ptr = ptr?.buffer || new ArrayBuffer(this._size); - this._data = new DataView(this._ptr); + this._ptr = ptr || new Uint8Array(this._size); + this._data = new DataView(this._ptr.buffer); for (const key of Object.keys(init)) { this[key] = init[key]; diff --git a/tools/js-class-c-struct-transpiler/test/schema.json b/tools/js-class-c-struct-transpiler/test/schema.json index 2c0aaa6..ec957e1 100644 --- a/tools/js-class-c-struct-transpiler/test/schema.json +++ b/tools/js-class-c-struct-transpiler/test/schema.json @@ -72,7 +72,7 @@ "members": { "success": { "type": "logical", - "kind": "scalar", + "kind": "logical", "comment": "login was successful or not" } } diff --git a/tools/js-class-c-struct-transpiler/test/test_server.js b/tools/js-class-c-struct-transpiler/test/test_server.js index 3a41773..0d3eb91 100644 --- a/tools/js-class-c-struct-transpiler/test/test_server.js +++ b/tools/js-class-c-struct-transpiler/test/test_server.js @@ -1,5 +1,7 @@ -import LoginRequest from "./build/LoginRequest" -import LoginResponse from "./build/LoginResponse" +import LoginRequest from "./build/LoginRequest"; +import LoginResponse from "./build/LoginResponse"; +import User from "./build/User"; +import Vector3 from "./build/Vector3"; var decoder = new TextDecoder("utf-8"); var port = 8089; @@ -18,8 +20,15 @@ wss.on("connection", function (ws) { console.log(entity.Login.Email); console.log(entity.Login.Password); - const response = new LoginResponse({success: true}); - ws.send(response.bytes, { binary: true }); // Echo back the received message + const user = new User({ + Name: "Test User", + Login: entity.Login, + Position: new Vector3({ x: 0, y: 0, z: 0 }), + }); + console.log(user.Name); + + const response = new LoginResponse({ success: true }); + ws.send(response._ptr, { binary: true }); // Echo back the received message } }); }); diff --git a/tools/js-class-c-struct-transpiler/transpile.js b/tools/js-class-c-struct-transpiler/transpile.js index ada8bc9..7a7726c 100644 --- a/tools/js-class-c-struct-transpiler/transpile.js +++ b/tools/js-class-c-struct-transpiler/transpile.js @@ -1,12 +1,6 @@ import { parseArgs } from "util"; let types = { - logical: { - c: "char", - js: "boolean", - sql: "INTEGER", - size: 1, - }, u8: { c: "unsigned char", js: "Uint8", @@ -93,23 +87,16 @@ const { values } = parseArgs({ function jsStructConstructor(size, containsString, type, args) { return ` - /** - * Get the struct representation of the object - * @return {Uint8Array} u8 array of the C struct. - */ - get bytes() { - return new Uint8Array(this._ptr); - } /** * Constructs a new ${type} * * @param ${args} init The arguments to construct the object. - * @param {ArrayBuffer} ptr The pointer to the C struct. + * @param {Uint8Array} ptr The pointer to the C struct. */ constructor(init = {}, ptr = undefined) { this._size = ${size}; - this._ptr = ptr?.buffer || new ArrayBuffer(this._size); - this._data = new DataView(this._ptr); + this._ptr = ptr || new Uint8Array(this._size); + this._data = new DataView(this._ptr.buffer); ${ containsString ? ` @@ -148,6 +135,31 @@ for (const type of Object.keys(schema)) { let typeSize = parseInt(types[propType]?.size); switch (kind) { + case "logical": + typeSize = 1; + jsData += ` + /** + * ${comment} + * @return {boolean} gets the value of ${prop} + */ + get ${prop}() { + return Boolean(this._data.getInt8(${parseInt(offset)}, true)); + } + /** + * ${comment} + * @param {boolean} sets the value of ${prop} + */ + set ${prop}(v) { + return this._data.setInt8(${parseInt( + offset + )}, v ? 1 : 0, true); + }`; + args += `${prop}: boolean, `; + typeDef += ` * @property {boolean} ${propType} ${comment}\n`; + sqlData += `, ${prop} INTEGER`; + cData += ` + char ${prop}; // ${comment}`; + break; case "string": containsString = true; typeSize = props[prop].size; @@ -167,7 +179,12 @@ for (const type of Object.keys(schema)) { * @param {string} v sets the value of ${prop} */ set ${prop}(v) { - this._data.set(this._encoder.encode(v), ${parseInt(offset)}); + if (v.length > ${parseInt(typeSize)}) { + throw new Error("input is larger than buffer size of ${parseInt(typeSize)}"); + } + const tmp = new Uint8Array(new ArrayBuffer(${parseInt(typeSize)})); + tmp.set(this._encoder.encode(v)) + this._ptr.set(tmp.buffer, ${parseInt(offset)}); }`; sqlData += `, ${prop} TEXT`; cData += ` @@ -195,7 +212,7 @@ for (const type of Object.keys(schema)) { )}, v, true); }`; args += `${prop}: ${types[propType].js}, `; - typeDef += ` * @property ${types[propType].js} ${propType} ${comment}\n`; + typeDef += ` * @property {${types[propType].js}} ${propType} ${comment}\n`; sqlData += `, ${prop} ${types[propType].sql}`; cData += ` ${types[propType].c} ${prop}; // ${comment}`; @@ -216,7 +233,7 @@ for (const type of Object.keys(schema)) { * @param {${types[propType].js}} sets the value of ${prop} */ set ${prop}(v) { - this._data.set(v.bytes(), ${offset}); + this._ptr.set(v._ptr, ${offset}); }`; const importS = `import ${propType} from "./${propType}"\n`; if (!importStatements.includes(importS)) { @@ -224,7 +241,7 @@ for (const type of Object.keys(schema)) { } const localKey = `${prop.toLowerCase()}_id`; args += `${prop}: ${types[propType].js}, `; - typeDef += ` * @property ${types[propType].js} ${propType} ${comment}\n`; + typeDef += ` * @property {${types[propType].js}} ${propType} ${comment}\n`; sqlData += `, ${localKey} INTEGER`; foreignKeys += `\n, FOREIGN KEY(${localKey}) REFERENCES ${propType}(id)` cData += `\n\t\t${types[propType].c} ${prop}; // ${comment}`;