Skip to content

Commit 4242b0c

Browse files
committed
feat: add support for serializing a struct layout
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 7b3dea1 commit 4242b0c

File tree

9 files changed

+445
-157
lines changed

9 files changed

+445
-157
lines changed

lib/node_modules/@stdlib/dstructs/struct/examples/index.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,15 @@ console.log( 'Alignment: %d', alignment );
120120
var names = Struct.fields;
121121
console.log( 'Field names: %s', names.join( ', ' ) );
122122

123-
var str = s.toString({
123+
var str1 = s.toString({
124124
'format': 'linear'
125125
});
126-
console.log( 'String:\n%s', str );
126+
console.log( 'String:\n%s', str1 );
127+
128+
var str2 = s.toString({
129+
'format': 'layout'
130+
});
131+
console.log( 'Layout: %s', str2 );
127132

128133
var o = s.toJSON();
129134
console.log( o );
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
var factory = require( './../lib' );
22+
23+
var fields1 = [
24+
{
25+
'name': 'high',
26+
'description': 'high word',
27+
'type': 'uint32',
28+
'enumerable': true,
29+
'writable': true,
30+
'castingMode': 'none'
31+
},
32+
{
33+
'name': 'low',
34+
'description': 'low word',
35+
'type': 'uint32',
36+
'enumerable': true,
37+
'writable': true,
38+
'castingMode': 'none'
39+
}
40+
];
41+
var Struct1 = factory( fields1 );
42+
43+
var fields2 = [
44+
{
45+
'name': 'double',
46+
'description': 'double-precision floating-point number',
47+
'type': 'float64',
48+
'enumerable': true,
49+
'writable': true,
50+
'castingMode': 'none'
51+
},
52+
{
53+
'name': 'words',
54+
'description': 'high and low words',
55+
'type': new Struct1(),
56+
'enumerable': true,
57+
'writable': true,
58+
'castingMode': 'none'
59+
}
60+
];
61+
var Struct2 = factory( fields2 );
62+
63+
var s = new Struct2();
64+
// returns <Struct>
65+
66+
var byteLength = Struct2.byteLength;
67+
console.log( 'Byte length: %d', byteLength );
68+
69+
var alignment = Struct2.alignment;
70+
console.log( 'Alignment: %d', alignment );
71+
72+
var names = Struct2.fields;
73+
console.log( 'Field names: %s', names.join( ', ' ) );
74+
75+
var str1 = s.toString({
76+
'format': 'layout'
77+
});
78+
console.log( 'String:\n%s', str1 );
79+
80+
var str2 = s.toString({
81+
'format': 'layout'
82+
});
83+
console.log( 'Layout: %s', str2 );
84+
85+
var o = s.toJSON();
86+
console.log( o );
87+
88+
var offset = Struct2.byteOffsetOf( 'double' );
89+
console.log( 'Offset: %d', offset );

lib/node_modules/@stdlib/dstructs/struct/examples/union.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,15 @@ console.log( 'Alignment: %d', alignment );
6262
var names = Struct.fields;
6363
console.log( 'Field names: %s', names.join( ', ' ) );
6464

65-
var str = s.toString({
65+
var str1 = s.toString({
6666
'format': 'linear'
6767
});
68-
console.log( 'String:\n%s', str );
68+
console.log( 'String:\n%s', str1 );
69+
70+
var str2 = s.toString({
71+
'format': 'layout'
72+
});
73+
console.log( 'Layout: %s', str2 );
6974

7075
var o = s.toJSON();
7176
console.log( o );

lib/node_modules/@stdlib/dstructs/struct/examples/union_with_complex.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,15 @@ console.log( 'Alignment: %d', alignment );
6262
var names = Struct.fields;
6363
console.log( 'Field names: %s', names.join( ', ' ) );
6464

65-
var str = s.toString({
65+
var str1 = s.toString({
6666
'format': 'linear'
6767
});
68-
console.log( 'String:\n%s', str );
68+
console.log( 'String:\n%s', str1 );
69+
70+
var str2 = s.toString({
71+
'format': 'layout'
72+
});
73+
console.log( 'Layout: %s', str2 );
6974

7075
var o = s.toJSON();
7176
console.log( o );

lib/node_modules/@stdlib/dstructs/struct/examples/union_with_struct.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,15 @@ console.log( 'Alignment: %d', alignment );
8181
var names = Struct2.fields;
8282
console.log( 'Field names: %s', names.join( ', ' ) );
8383

84-
var str = s.toString({
84+
var str1 = s.toString({
8585
'format': 'linear'
8686
});
87-
console.log( 'String:\n%s', str );
87+
console.log( 'String:\n%s', str1 );
88+
89+
var str2 = s.toString({
90+
'format': 'layout'
91+
});
92+
console.log( 'Layout: %s', str2 );
8893

8994
var o = s.toJSON();
9095
console.log( o );
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var replace = require( '@stdlib/string/base/replace' );
24+
var format = require( '@stdlib/string/format' );
25+
26+
27+
// FUNCTIONS //
28+
29+
/**
30+
* Returns a new regular expression for matching byte parameters.
31+
*
32+
* @private
33+
* @returns {RegExp} regular expression
34+
*/
35+
function reByteOffset() {
36+
return /\[(\d{1,}),/g;
37+
}
38+
39+
/**
40+
* Returns a function for replacing byte values in a serialized struct.
41+
*
42+
* @private
43+
* @param {NonNegativeInteger} offset - byte offset
44+
* @returns {Function} replacer function
45+
*/
46+
function replacer( offset ) {
47+
return wrapped;
48+
49+
/**
50+
* Callback invoked for each match.
51+
*
52+
* @private
53+
* @param {string} match - matched substring
54+
* @param {string} p1 - first matched capture group substring
55+
* @returns {string} replacement string
56+
*/
57+
function wrapped( match, p1 ) {
58+
return format( '[%u,', offset+parseInt( p1, 10 ) );
59+
}
60+
}
61+
62+
63+
// MAIN //
64+
65+
/**
66+
* Serializes a struct to a layout format.
67+
*
68+
* ## Notes
69+
*
70+
* - The output format is a multi-column format having the following layout:
71+
*
72+
* ```text
73+
* | ...<dtype(s)>[byte_offset,byte_length] |
74+
* ```
75+
*
76+
* For example,
77+
*
78+
* ```text
79+
* |<double>[0,8]|<bool>[8,1]|<double>[16,16]|<double,uint32>[32,8]|
80+
* ```
81+
*
82+
* @private
83+
* @param {Array<Object>} fields - list of normalized fields
84+
* @returns {string} string representation
85+
*/
86+
function layoutFormat( fields ) {
87+
var out;
88+
var tmp;
89+
var re;
90+
var N;
91+
var o;
92+
var i;
93+
94+
N = fields.length;
95+
96+
// Create a new regular expression for matching byte offsets:
97+
re = reByteOffset();
98+
99+
out = [];
100+
for ( i = 0; i < N; i++ ) {
101+
o = fields[ i ];
102+
103+
// If we are currently processing fields in a union, move along to the next non-union field...
104+
if ( i > 0 && ( o.byteOffset === fields[ i-1 ].byteOffset ) ) {
105+
continue;
106+
}
107+
// If the current type is a struct, we need to serialize and then post-process...
108+
if ( o.isStructType ) {
109+
tmp = o.type.toString({
110+
'format': 'layout'
111+
});
112+
out.push( replace( tmp, re, replacer( o.byteOffset ) ) );
113+
continue;
114+
}
115+
// Format the field data:
116+
out.push( format( '|<%s>[%u,%u]', o.type, o.byteOffset, o.byteLength ) );
117+
}
118+
tmp = format( '%s|', out.join( '' ) );
119+
120+
// If we having a trailing `||` due to a nested struct, remove the final `|`:
121+
if ( tmp[ tmp.length-2 ] === '|' ) {
122+
tmp = tmp.substring( 0, tmp.length-1 );
123+
}
124+
return tmp;
125+
}
126+
127+
128+
// EXPORTS //
129+
130+
module.exports = layoutFormat;

0 commit comments

Comments
 (0)