-
Notifications
You must be signed in to change notification settings - Fork 1
feat: buffer generator #64
base: main
Are you sure you want to change the base?
Conversation
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
This pull request introduces 2 alerts when merging 4570ead into 1ff9b3b - view on LGTM.com new alerts:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! I've provided the intial feedback.
Other changes required:
Travis should build and test both the generator and the generated code
The nem generated code is not compiling yet. it would be nice if we can compile it even thought the schemas and parsers are not ready to support nem yet (issues: https://github.com/symbol/catbuffer-schemas/issues)
We would do an sdk-typescript
to symbol-typescript
repo renaming and restructuring that would move folders and files around. That would change the generator a little bit. What should be do first? The repo renaming/restructuring or the generator?
have a look at the CodeQL checks
https://github.com/symbol/sdk-typescript/pull/64/checks?check_run_id=3926138865
@@ -0,0 +1,17 @@ | |||
export interface Layout { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uppercase the files in the interface folder
export interface Layout { | ||
comments: string; | ||
type: string; | ||
disposition?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replace with disposition?: DispositionType
(use enum directly when possible)
comments: string; | ||
name: string; | ||
type: string; | ||
signedness: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can be enum?
comment: Emtpy Account Restriction | ||
- builder: FinalizedBlockHeader | ||
payload: 90FD35818960C7B18B72F49A5598FA9F712A354DB38EB076C40300000000000011111111111111111111111111111111 | ||
#- builder: AccountState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why commented out?
@@ -0,0 +1,37 @@ | |||
{ | |||
"compilerOptions": { | |||
"baseUrl": "./", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we simplify the tsconfig.json files?
Compare with https://github.com/symbol/symbol-bootstrap/blob/dev/tsconfig.json
Having said that, I think we would move and change files around once we move to multimodule (like lerna)
* Inject license boilerplate to an existing file content | ||
* @param fileContent - existing generated file content | ||
*/ | ||
public static getLicense(): string[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace with
/**
* Inject license boilerplate to an existing file content
*/
public static getLicense(): string[] {
return readFileSync(path.join(__dirname, './HEADER.inc'), 'utf-8').split(/\r?\n/);
}
and we save the n-readlines
dependency
}, | ||
"dependencies": { | ||
"bigint-buffer": "^1.1.5", | ||
"fs-extra": "^10.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove fs-extra
, the generator is not using anything special. You can use standard 'fs' node module.
@@ -0,0 +1,37 @@ | |||
import * as fs from 'fs-extra'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not necessary, you can use native fs module
import * as fs from 'fs';
"typescript": "^4.3.5" | ||
}, | ||
"dependencies": { | ||
"bigint-buffer": "^1.1.5", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bigint-buffer is not used?
constructor(public readonly classSchema: Schema, schema: Schema[]) { | ||
super(schema); | ||
this.importList = ['Utils', 'Serializer']; | ||
this.generatedLines = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we void mutable instance fields that can be moved to a method?
this.generatedLines:[] could be moved to the generate() method
Original git project is here: https://github.com/rg911/symbol-ts-generator
**Copied generator readme file below
Symbol Typescript Buffer Generator
This project written in Typescript takes the parsed YAML schemas and generates the serializer and deserializer classes for both Symbol & NEM transactions and state entities.
language
Requirements
Usage
The full generator codes are created in
build
folder.Test the generator
cd build
The test spec loads predefined YAML test and perform the test on the generators.
Generated class design patten
There are 3 types of generated Typescript files:
Class
,Enum
,Helper
. The creation of each file follows the flow of common manual Typescript class generation:license boilerplate
->class header
->constructor method
->other methods
->class footer
Class
: See ClassGenerator.tsEach class has the same 3 fundamental method structure:
Constructor
,Deserializer
,Serializer
andSize property
Classes contain
inline
disposition attributes also has a parameter interface declared for passing flattened inline parameters into the constructor.All classes implements a static interface:
Serializer
which defines the none static methods and public properties.The First
creatable
inline class defined in the class schema will be used as thesuper class
.Most comment ones are transactions:
Enum:
See EnumGenerator.tsStandard Typescript key value pairs.
Helper classes:
See TransactionHelperGenerator.tsUtils.ts
: which defines all type conversion, buffer operation and array manipulation methods used in Serialize and Deserialize methods.EmbeddedTransactionHelper.ts
: which is used inAggregate Transaction
deserialization to help deserializing each embedded transaction.TransactionHelper.ts
: similar to the EmbeddedTransactionHelper which is created to help deserializing transactions but is not used in the generated codes (to improve the usability in the sdk).Generated method design patten
Constructor:
Parameters are either single field or flattened inline entity parameters.
When loading the YAML schema file, each class schema gets parsed into the schema and layout as the 'raw' input. The parsed schema then get recursively read into the final parameter list. The parameters have the sanitized name, type, size and comments depending on their type/disposition/condition values. A declarable flag is added to each parameter to decide whether or not to declare it in the constructor.
Super class is also decided per each class schema.
Deserialize:
Deserialize is
static
.The deserializer splices the whole payload buffer by each parameter's size in the specific order defined by the schema, until all payload bytes are processed. The size of the parameter can be either a static number size or calculated by it's type/disposition value. The basic 'actual size' of each parameter at this stage has been calculated in previous operations. Additional calculations based conditions and disposition values are also performed here.
Non declarable
parameters are Required.Example deserialize method:
Special inline parameter: EmbeddedTransaction
EmbeddedTransaction
is treated as a special case here since the deserialize need to parse each embedded transaction as a standalone transaction entity. Thus the generator uses a static helper fileEmbeddedTransactionHelper.ts
to archive this. This case is only applied inAggregateTransactionBody
.Example of the usage:
Serialize:
Serialize is similar to Deserialize but it is not a static method. In a reserved manner, it serialize each class parameter in the order defined by the schema.
Buffer serialize method also depends on each parameter's type, condition and disposition value.
Non declarable
parameters are Required.Example serialize method:
Size getter:
Each class contains a public get property
size
to replace theSizePrefixedEntity
and also used for serialize/deserialize processes. The getter calculates theactual size
of each class parameters (either size in number or EntityStruct.size).Similar to the other 2 class methods, conditions, disposition values are also considered when calculating the actual size.
Non declarable
parameters are Required.Example size getter:
Other miscellaneous design patten
\
is replaced as it is not Typescript friendly in comments..ignore
files are copied as static files to the output folder.