struct-frame 0.0.25__py3-none-any.whl → 0.0.28__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of struct-frame might be problematic. Click here for more details.

struct_frame/py_gen.py CHANGED
@@ -17,6 +17,7 @@ py_types = {"uint8": "uint8",
17
17
  "double": "float64",
18
18
  "uint64": 'uint64',
19
19
  "int64": 'int64',
20
+ "string": "str", # Add string type support
20
21
  }
21
22
 
22
23
 
@@ -58,14 +59,51 @@ class FieldPyGen():
58
59
 
59
60
  var_name = field.name
60
61
  type_name = field.fieldType
62
+
63
+ # Handle basic type resolution
61
64
  if type_name in py_types:
62
- type_name = py_types[type_name]
65
+ base_type = py_types[type_name]
63
66
  else:
64
- type_name = '%s%s' % (pascalCase(field.package), type_name)
65
67
  if field.isEnum:
66
- type_name = 'uint8 #%s' % type_name
68
+ # For enums, use the full enum class name for better type safety
69
+ base_type = '%s%s' % (pascalCase(field.package), type_name)
70
+ else:
71
+ base_type = '%s%s' % (pascalCase(field.package), type_name)
72
+
73
+ # Handle arrays
74
+ if field.is_array:
75
+ if field.fieldType == "string":
76
+ # String arrays require both array size and individual element size
77
+ if field.size_option is not None:
78
+ type_annotation = f"list[{base_type}] # Fixed string array size={field.size_option}, each max {field.element_size} chars"
79
+ elif field.max_size is not None:
80
+ type_annotation = f"list[{base_type}] # Bounded string array max_size={field.max_size}, each max {field.element_size} chars"
81
+ else:
82
+ type_annotation = f"list[{base_type}] # String array"
83
+ else:
84
+ # Non-string arrays
85
+ if field.size_option is not None:
86
+ type_annotation = f"list[{base_type}] # Fixed array size={field.size_option}"
87
+ elif field.max_size is not None:
88
+ type_annotation = f"list[{base_type}] # Bounded array max_size={field.max_size}"
89
+ else:
90
+ type_annotation = f"list[{base_type}] # Array"
91
+ # Handle strings with size info
92
+ elif field.fieldType == "string":
93
+ if field.size_option is not None:
94
+ # Fixed string - exact length
95
+ type_annotation = f"str # Fixed string size={field.size_option}"
96
+ elif field.max_size is not None:
97
+ # Variable string - up to max length
98
+ type_annotation = f"str # Variable string max_size={field.max_size}"
99
+ else:
100
+ # Fallback (shouldn't happen with validation)
101
+ type_annotation = "str # String"
102
+ else:
103
+ # Regular field
104
+ type_annotation = base_type
67
105
 
68
- result += ' %s: %s' % (var_name, type_name)
106
+ result += ' %s: %s' % (var_name, type_annotation)
69
107
 
70
108
  leading_comment = field.comments
71
109
  if leading_comment:
@@ -86,7 +124,7 @@ class MessagePyGen():
86
124
  result = '#%s\n' % c
87
125
 
88
126
  structName = '%s%s' % (pascalCase(msg.package), msg.name)
89
- result += 'class %s(Structured):\n' % structName
127
+ result += 'class %s(Structured, byte_order=ByteOrder.LE, byte_order_mode=ByteOrderMode.OVERRIDE):\n' % structName
90
128
  result += ' msg_size = %s\n' % msg.size
91
129
  if msg.id != None:
92
130
  result += ' msg_id = %s\n' % msg.id
@@ -94,7 +132,42 @@ class MessagePyGen():
94
132
  result += '\n'.join([FieldPyGen.generate(f)
95
133
  for key, f in msg.fields.items()])
96
134
 
97
- return result + '\n'
135
+ result += '\n\n def __str__(self):\n'
136
+ result += f' out = "{msg.name} Msg, ID {msg.id}, Size {msg.size} \\n"\n'
137
+ for key, f in msg.fields.items():
138
+ result += f' out += f"{key} = '
139
+ result += '{self.' + key + '}\\n"\n'
140
+ result += f' out += "\\n"\n'
141
+ result += f' return out'
142
+
143
+ result += '\n\n def to_dict(self, include_name = True, include_id = True):\n'
144
+ result += ' out = {}\n'
145
+ # Handle all field types including arrays
146
+ for key, f in msg.fields.items():
147
+ if f.is_array:
148
+ if f.isDefaultType or f.isEnum or f.fieldType == "string":
149
+ # Array of primitives, enums, or strings
150
+ result += f' out["{key}"] = self.{key}\n'
151
+ else:
152
+ # Array of nested messages - convert each element
153
+ result += f' out["{key}"] = [item.to_dict(False, False) for item in self.{key}]\n'
154
+ elif f.isDefaultType or f.isEnum or f.fieldType == "string":
155
+ # Regular primitive, enum, or string field
156
+ result += f' out["{key}"] = self.{key}\n'
157
+ else:
158
+ # Nested message field
159
+ if getattr(f, 'flatten', False):
160
+ # Merge nested dict into parent
161
+ result += f' out.update(self.{key}.to_dict(False, False))\n'
162
+ else:
163
+ result += f' out["{key}"] = self.{key}.to_dict(False, False)\n'
164
+ result += ' if include_name:\n'
165
+ result += f' out["name"] = "{msg.name}"\n'
166
+ result += ' if include_id:\n'
167
+ result += f' out["msg_id"] = "{msg.id}"\n'
168
+ result += ' return out\n'
169
+
170
+ return result
98
171
 
99
172
  @staticmethod
100
173
  def get_initializer(msg, null_init):
struct_frame/ts_gen.py CHANGED
@@ -18,6 +18,23 @@ ts_types = {
18
18
  "uint32": 'UInt32LE',
19
19
  "uint64": 'BigInt64LE',
20
20
  "int64": 'BigUInt64LE',
21
+ "string": 'String',
22
+ }
23
+
24
+ # TypeScript type mappings for array declarations
25
+ ts_array_types = {
26
+ "int8": 'number',
27
+ "uint8": 'number',
28
+ "int16": 'number',
29
+ "uint16": 'number',
30
+ "bool": 'boolean',
31
+ "double": 'number',
32
+ "float": 'number',
33
+ "int32": 'number',
34
+ "uint32": 'number',
35
+ "uint64": 'bigint',
36
+ "int64": 'bigint',
37
+ "string": 'string',
21
38
  }
22
39
 
23
40
 
@@ -65,18 +82,66 @@ class FieldTsGen():
65
82
  def generate(field, packageName):
66
83
  result = ''
67
84
  isEnum = False
68
- # isEnum = field.pbtype in ('ENUM', 'UENUM')
69
85
  var_name = StyleC.var_name(field.name)
70
86
  type_name = field.fieldType
71
- if type_name in ts_types:
72
- type_name = ts_types[type_name]
73
- else:
74
- type_name = '%s_%s' % (packageName, StyleC.struct_name(type_name))
75
87
 
76
- if isEnum:
77
- result += ' .UInt8(\'%s\', typed<%s>())' % (var_name, type_name)
88
+ # Handle arrays
89
+ if field.is_array:
90
+ if field.fieldType == "string":
91
+ if field.size_option is not None: # Fixed size array [size=X]
92
+ # Fixed string array: string[size] -> Array<string> with fixed length
93
+ result += f' // Fixed string array: {field.size_option} strings, each exactly {field.element_size} chars\n'
94
+ result += f' .Array(\'{var_name}\', \'String\', {field.size_option})'
95
+ else: # Variable size array [max_size=X]
96
+ # Variable string array: string[max_size=X, element_size=Y] -> Array<string> with count
97
+ result += f' // Variable string array: up to {field.max_size} strings, each max {field.element_size} chars\n'
98
+ result += f' .UInt8(\'{var_name}_count\')\n'
99
+ result += f' .Array(\'{var_name}_data\', \'String\', {field.max_size})'
100
+ else:
101
+ # Regular type arrays
102
+ if type_name in ts_types:
103
+ base_type = ts_types[type_name]
104
+ else:
105
+ base_type = f'{packageName.lower()}_{StyleC.struct_name(type_name).lower()}'
106
+
107
+ if field.size_option is not None: # Fixed size array [size=X]
108
+ # Fixed array: type[size] -> Array<type> with fixed length
109
+ # For fixed arrays, size_option contains the exact size
110
+ array_size = field.size_option
111
+ result += f' // Fixed array: always {array_size} elements\n'
112
+ result += f' .Array(\'{var_name}\', \'{base_type}\', {array_size})'
113
+ else: # Variable size array [max_size=X]
114
+ # Variable array: type[max_size=X] -> count + Array<type>
115
+ max_count = field.max_size # For variable arrays, max_size is the maximum count
116
+ result += f' // Variable array: up to {max_count} elements\n'
117
+ result += f' .UInt8(\'{var_name}_count\')\n'
118
+ result += f' .Array(\'{var_name}_data\', \'{base_type}\', {max_count})'
78
119
  else:
79
- result += ' .%s(\'%s\')' % (type_name, var_name)
120
+ # Non-array fields (existing logic)
121
+ if field.fieldType == "string":
122
+ if hasattr(field, 'size_option') and field.size_option is not None:
123
+ # Fixed string: string[size] -> fixed length string
124
+ result += f' // Fixed string: exactly {field.size_option} chars\n'
125
+ result += f' .String(\'{var_name}\', {field.size_option})'
126
+ elif hasattr(field, 'max_size') and field.max_size is not None:
127
+ # Variable string: string[max_size=X] -> length + data
128
+ result += f' // Variable string: up to {field.max_size} chars\n'
129
+ result += f' .UInt8(\'{var_name}_length\')\n'
130
+ result += f' .String(\'{var_name}_data\', {field.max_size})'
131
+ else:
132
+ # Default string handling (should not occur with new parser)
133
+ result += f' .String(\'{var_name}\')'
134
+ else:
135
+ # Regular types
136
+ if type_name in ts_types:
137
+ type_name = ts_types[type_name]
138
+ else:
139
+ type_name = f'{packageName}_{StyleC.struct_name(type_name)}'
140
+
141
+ if isEnum:
142
+ result += f' .UInt8(\'{var_name}\', typed<{type_name}>())'
143
+ else:
144
+ result += f' .{type_name}(\'{var_name}\')'
80
145
 
81
146
  leading_comment = field.comments
82
147
  if leading_comment:
@@ -182,11 +247,14 @@ class FileTsGen():
182
247
  yield '\n'
183
248
 
184
249
  if package.messages:
185
- yield 'export function get_message_length(msg_id : number){\n switch (msg_id)\n {\n'
186
- for key, msg in package.sortedMessages().items():
187
-
188
- package_msg_name = '%s_%s' % (package.name, msg.name)
189
- yield ' case %s_msgid: return %s_max_size;\n' % (package_msg_name, package_msg_name)
190
-
191
- yield ' default: break;\n } return 0;\n}'
250
+ # Only generate get_message_length if there are messages with IDs
251
+ messages_with_id = [
252
+ msg for key, msg in package.sortedMessages().items() if msg.id]
253
+ if messages_with_id:
254
+ yield 'export function get_message_length(msg_id : number){\n switch (msg_id)\n {\n'
255
+ for msg in messages_with_id:
256
+ package_msg_name = '%s_%s' % (package.name, msg.name)
257
+ yield ' case %s_msgid: return %s_max_size;\n' % (package_msg_name, package_msg_name)
258
+
259
+ yield ' default: break;\n } return 0;\n}'
192
260
  yield '\n'
@@ -0,0 +1,311 @@
1
+ Metadata-Version: 2.4
2
+ Name: struct-frame
3
+ Version: 0.0.28
4
+ Summary: A framework for serializing data with headers
5
+ Project-URL: Homepage, https://github.com/mylonics/struct-frame
6
+ Project-URL: Issues, https://github.com/mylonics/struct-frame/issues
7
+ Author-email: Rijesh Augustine <rijesh@mylonics.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Requires-Python: >=3.8
13
+ Requires-Dist: proto-schema-parser>=1.4.5
14
+ Requires-Dist: structured-classes>=3.1.0
15
+ Description-Content-Type: text/markdown
16
+
17
+
18
+ # Struct Frame
19
+
20
+ A multi-language code generation framework that converts Protocol Buffer (.proto) files into serialization/deserialization code for C, TypeScript, Python, and GraphQL. It provides framing and parsing utilities for structured message communication.
21
+
22
+ ## Quick Start
23
+
24
+ ### Installation
25
+ ```bash
26
+ # Install Python dependencies
27
+ pip install proto-schema-parser structured-classes
28
+
29
+ # Install Node.js dependencies (for TypeScript)
30
+ npm install
31
+ ```
32
+
33
+ ### Basic Usage
34
+ ```bash
35
+ # Generate code for all languages
36
+ PYTHONPATH=src python3 src/main.py examples/myl_vehicle.proto --build_c --build_ts --build_py --build_gql
37
+
38
+ # Run comprehensive test suite
39
+ python test_all.py
40
+
41
+ # Generated files will be in the generated/ directory
42
+ ```
43
+
44
+ ### Test Suite
45
+
46
+ The project includes a comprehensive test suite that validates code generation, compilation, and serialization across all supported languages:
47
+
48
+ ```bash
49
+ # Run all tests
50
+ python test_all.py
51
+
52
+ # Run with verbose output
53
+ python tests/run_tests.py --verbose
54
+
55
+ # Skip specific languages
56
+ python tests/run_tests.py --skip-ts --skip-c
57
+
58
+ # Generate code only (no compilation/execution)
59
+ python tests/run_tests.py --generate-only
60
+ ```
61
+
62
+ See `tests/README.md` for detailed test documentation.
63
+
64
+ ### Language-Specific Examples
65
+
66
+ #### Python
67
+ ```bash
68
+ python src/main.py examples/myl_vehicle.proto --build_py
69
+ # Use generated Python classes directly
70
+ ```
71
+
72
+ #### TypeScript
73
+ ```bash
74
+ python src/main.py examples/myl_vehicle.proto --build_ts
75
+ npx tsc examples/index.ts --outDir generated/
76
+ node generated/examples/index.js
77
+ ```
78
+
79
+ #### C
80
+ ```bash
81
+ python src/main.py examples/myl_vehicle.proto --build_c
82
+ gcc examples/main.c -I generated/c -o main
83
+ ./main
84
+ ```
85
+
86
+ #### GraphQL
87
+ ```bash
88
+ python src/main.py examples/myl_vehicle.proto --build_gql
89
+ # Use generated .graphql schema files
90
+ ```
91
+
92
+ ## Feature Compatibility Matrix
93
+
94
+ | Feature | C | TypeScript | Python | GraphQL | Status |
95
+ |---------|---|------------|--------|---------|--------|
96
+ | **Core Types** | ✓ | ✓ | ✓ | ✓ | Stable |
97
+ | **String** | ✓ | ✓ | ✓ | ✓ | Stable |
98
+ | **Enums** | ✓ | ✓ | ✓ | ✓ | Stable |
99
+ | **Nested Messages** | ✓ | ✓ | ✓ | ✓ | Stable |
100
+ | **Message IDs** | ✓ | ✓ | ✓ | N/A | Stable |
101
+ | **Message Serialization** | ✓ | ✓ | ✓ | N/A | Stable |
102
+ | **Flatten** | N/A | N/A | ✓ | ✓ | Partial |
103
+ | **Arrays** | ✓ | ✓ | ✓ | ✓ | Stable |
104
+
105
+ **Legend:**
106
+ - **✓** - Feature works as documented
107
+ - **Partial** - Basic functionality works, some limitations
108
+ - **✗** - Feature not yet available
109
+ - **N/A** - Not applicable for this language
110
+
111
+ ## Project Structure
112
+
113
+ - `src/struct_frame/` - Core code generation framework
114
+ - `generate.py` - Main parser and validation logic
115
+ - `*_gen.py` - Language-specific code generators
116
+ - `boilerplate/` - Runtime libraries for each language
117
+ - `examples/` - Example .proto files and usage demos
118
+ - `main.c` - C API demonstration (encoding/decoding, parsing)
119
+ - `index.ts` - TypeScript API demonstration (similar functionality)
120
+ - `*.proto` - Protocol Buffer definitions for examples
121
+ - `generated/` - Output directory for generated code (git-ignored)
122
+
123
+ ## Protocol Buffer Schema Reference
124
+
125
+ ### Supported Data Types
126
+
127
+ | Type | Size (bytes) | Description | Range/Notes |
128
+ |------|--------------|-------------|-------------|
129
+ | **Integers** |
130
+ | `int8` | 1 | Signed 8-bit integer | -128 to 127 |
131
+ | `uint8` | 1 | Unsigned 8-bit integer | 0 to 255 |
132
+ | `int16` | 2 | Signed 16-bit integer | -32,768 to 32,767 |
133
+ | `uint16` | 2 | Unsigned 16-bit integer | 0 to 65,535 |
134
+ | `int32` | 4 | Signed 32-bit integer | -2.1B to 2.1B |
135
+ | `uint32` | 4 | Unsigned 32-bit integer | 0 to 4.3B |
136
+ | `int64` | 8 | Signed 64-bit integer | Large integers |
137
+ | `uint64` | 8 | Unsigned 64-bit integer | Large positive integers |
138
+ | **Floating Point** |
139
+ | `float` | 4 | Single precision (IEEE 754) | 7 decimal digits |
140
+ | `double` | 8 | Double precision (IEEE 754) | 15-17 decimal digits |
141
+ | **Other** |
142
+ | `bool` | 1 | Boolean value | `true` or `false` |
143
+ | `string` | Variable | UTF-8 encoded string | Length-prefixed |
144
+ | `EnumType` | 1 | Custom enumeration | Defined in .proto |
145
+ | `MessageType` | Variable | Nested message | User-defined structure |
146
+
147
+ > **Note:** All types use little-endian byte order for cross-platform compatibility.
148
+
149
+ ### Array Support
150
+
151
+ Arrays (repeated fields) support all data types - primitives, enums, and messages across all target languages.
152
+
153
+ | Array Type | Syntax | Memory Usage | Use Case |
154
+ |------------|--------|--------------|----------|
155
+ | **Fixed** | `repeated type field = N [size=X];` | `sizeof(type) * X` | Matrices, buffers (always full) |
156
+ | **Bounded** | `repeated type field = N [max_size=X];` | 1 byte (count) + `sizeof(type) * X` | Dynamic lists with limits |
157
+ | **String Arrays** | `repeated string field = N [max_size=X, element_size=Y];` | 1 byte (count) + `X * Y` bytes | Text collections with size limits |
158
+
159
+ ```proto
160
+ message ArrayExample {
161
+ repeated float matrix = 1 [size=9]; // 3x3 matrix (always 9 elements)
162
+ repeated string names = 2 [max_size=10, element_size=32]; // Up to 10 strings, each max 32 chars
163
+ repeated int32 values = 3 [max_size=100]; // Up to 100 integers (variable count)
164
+ }
165
+ ```
166
+
167
+ **Generated Output** (all languages now supported):
168
+ - **Python**: `matrix: list[float]`, `names: list[str]`, `values: list[int]`
169
+ - **C**: `float matrix[9]`, `struct { uint8_t count; char data[10][32]; } names`
170
+ - **TypeScript**: `Array('matrix', 'Float32LE', 9)`, `Array('names_data', 'String', 10)`
171
+ - **GraphQL**: `matrix: [Float!]!`, `names: [String!]!`, `values: [Int!]!`
172
+
173
+ > **Important**: String arrays require both `max_size` (or `size`) AND `element_size` parameters because they are "arrays of arrays" - you need to specify both how many strings AND the maximum size of each individual string. This ensures predictable memory layout and prevents buffer overflows.
174
+
175
+ ### String Type
176
+
177
+ Strings are a special case of bounded character arrays with built-in UTF-8 encoding and null-termination handling across all target languages.
178
+
179
+ | String Type | Syntax | Memory Usage | Use Case |
180
+ |-------------|--------|--------------|----------|
181
+ | **Fixed String** | `string field = N [size=X];` | `X` bytes | Fixed-width text fields |
182
+ | **Variable String** | `string field = N [max_size=X];` | 1 byte (length) + `X` bytes | Text with known maximum length |
183
+
184
+ ```proto
185
+ message StringExample {
186
+ string device_name = 1 [size=16]; // Exactly 16 characters (pad with nulls)
187
+ string description = 2 [max_size=256]; // Up to 256 characters (length-prefixed)
188
+ string error_msg = 3 [max_size=128]; // Up to 128 characters for error messages
189
+ }
190
+ ```
191
+
192
+ **String Benefits:**
193
+ - **Simplified Schema**: No need to specify `repeated uint8` for text data
194
+ - **Automatic Encoding**: UTF-8 encoding/decoding handled by generators
195
+ - **Null Handling**: Proper null-termination and padding for fixed strings
196
+ - **Type Safety**: Clear distinction between binary data and text
197
+ - **Cross-Language**: Consistent string handling across C, TypeScript, and Python
198
+
199
+ ### Message Options
200
+
201
+ **Message ID (`msgid`)** - Required for serializable messages:
202
+ ```proto
203
+ message MyMessage {
204
+ option msgid = 42; // Must be unique within package (0-65535)
205
+ string content = 1;
206
+ }
207
+ ```
208
+
209
+ ### Field Options
210
+
211
+ **Flatten (`flatten=true`)** - Merge nested message fields into parent:
212
+ ```proto
213
+ message Position {
214
+ double lat = 1;
215
+ double lon = 2;
216
+ }
217
+
218
+ message Status {
219
+ Position pos = 1 [flatten=true]; // lat, lon become direct fields
220
+ float battery = 2;
221
+ }
222
+ ```
223
+
224
+ **Array Options** - Control array behavior:
225
+ ```proto
226
+ message Data {
227
+ repeated int32 fixed_buffer = 1 [size=256]; // Always 256 integers
228
+ repeated int32 var_buffer = 2 [max_size=256]; // Up to 256 integers
229
+ repeated string messages = 3 [max_size=10, element_size=64]; // Up to 10 strings, each max 64 chars
230
+ string device_name = 4 [size=32]; // Always 32 characters
231
+ string description = 5 [max_size=256]; // Up to 256 characters
232
+ }
233
+ ```
234
+
235
+ ## Complete Example
236
+
237
+ ```proto
238
+ package sensor_system;
239
+
240
+ enum SensorType {
241
+ TEMPERATURE = 0;
242
+ HUMIDITY = 1;
243
+ PRESSURE = 2;
244
+ }
245
+
246
+ message Position {
247
+ double lat = 1;
248
+ double lon = 2;
249
+ float alt = 3;
250
+ }
251
+
252
+ message SensorReading {
253
+ option msgid = 1;
254
+
255
+ uint32 device_id = 1;
256
+ int64 timestamp = 2;
257
+ SensorType type = 3;
258
+
259
+ // Device name (fixed 16-character string)
260
+ string device_name = 4 [size=16];
261
+
262
+ // Sensor location (flattened)
263
+ Position location = 5 [flatten=true];
264
+
265
+ // Measurement values (up to 8 readings)
266
+ repeated float values = 6 [max_size=8];
267
+
268
+ // Calibration matrix (always 3x3 = 9 elements)
269
+ repeated float calibration = 7 [size=9];
270
+
271
+ // Error message (up to 128 characters)
272
+ string error_msg = 8 [max_size=128];
273
+
274
+ bool valid = 9;
275
+ }
276
+
277
+ message DeviceStatus {
278
+ option msgid = 2;
279
+
280
+ uint32 device_id = 1;
281
+ repeated SensorReading recent_readings = 2 [max_size=10];
282
+ float battery_level = 3;
283
+ }
284
+ ```
285
+
286
+ ## Schema Validation Rules
287
+
288
+ - **Message IDs**: Must be unique within package (0-65535)
289
+ - **Field numbers**: Must be unique within message
290
+ - **Array requirements**: All `repeated` fields must specify `[size=X]` (fixed) or `[max_size=X]` (bounded)
291
+ - **String requirements**: All `string` fields must specify `[size=X]` (fixed) or `[max_size=X]` (variable)
292
+ - **String array requirements**: `repeated string` fields must specify both array size AND `[element_size=Y]`
293
+ - **Flatten constraints**: No field name collisions after flattening
294
+ - **Size limits**: Arrays limited to 255 elements maximum
295
+
296
+ ## Code Generation
297
+
298
+ ```bash
299
+ # Generate all languages
300
+ python src/main.py schema.proto --build_c --build_ts --build_py --build_gql
301
+
302
+ # Language-specific paths
303
+ python src/main.py schema.proto --build_py --py_path output/python/
304
+ python src/main.py schema.proto --build_c --c_path output/c/
305
+ python src/main.py schema.proto --build_ts --ts_path output/typescript/
306
+ python src/main.py schema.proto --build_gql --gql_path output/graphql/
307
+ ```
308
+
309
+ ## Additional Documentation
310
+
311
+ - **[Array Implementation Guide](ARRAY_IMPLEMENTATION.md)** - Comprehensive documentation of array features, syntax, and generated code examples across all languages
@@ -0,0 +1,12 @@
1
+ struct_frame/__init__.py,sha256=m9hfIbcgCYvt-fIeYrJRQyk6I7rq35jSdZIhrMmZntg,374
2
+ struct_frame/__main__.py,sha256=tIybnBeFHvwiwVhodVOSnxhne5AX_80mtXBx4rneSB4,143
3
+ struct_frame/base.py,sha256=1Z_0vMkwz0X8r2hIVLv5yuhwwD929LwNMzVKBqFxxac,2012
4
+ struct_frame/c_gen.py,sha256=I-VFeVmOBlvjZuRehljEjRxJComWGIwOsNe1ex77RLI,9555
5
+ struct_frame/generate.py,sha256=8YL4MJ--vvOsv5MFqGjKSATSulanEqX_Qf0Jew6x7UU,23416
6
+ struct_frame/gql_gen.py,sha256=jDLsyZJmfpVBpdXE06mixZ3D01NAmRioGJqk_FoQt90,7543
7
+ struct_frame/py_gen.py,sha256=EQqw8u2o-FszROviQyQCpF45bbx0KqjdqVBefpyDqH4,7932
8
+ struct_frame/ts_gen.py,sha256=glT9eA--j_8vaR8tHQ0ekDg7udIVgE9FGA4MGAwiCsA,10103
9
+ struct_frame-0.0.28.dist-info/METADATA,sha256=30k3JtXITayQdbY9UmOxcHTriwp3A9k7rX_EirMMXGU,10831
10
+ struct_frame-0.0.28.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
11
+ struct_frame-0.0.28.dist-info/licenses/LICENSE,sha256=UjbLtGfcHCIqJg9UzEVGoNW8fyX4Ah9ZbsuAmJ_vhmk,1094
12
+ struct_frame-0.0.28.dist-info/RECORD,,
@@ -1,103 +0,0 @@
1
- #pragma once
2
- #include "stdbool.h"
3
- #include "stdint.h"
4
- #include "string.h"
5
- #include "struct_frame_types.h"
6
-
7
- static inline struct checksum_t fletcher_checksum_calculation(uint8_t *buffer, uint8_t data_length) {
8
- checksum_t checksum;
9
-
10
- for (int i = 0; i < data_length; i++) {
11
- checksum.byte1 += buffer[i];
12
- checksum.byte2 += checksum.byte1;
13
- }
14
- return checksum;
15
- }
16
-
17
- static inline bool msg_encode(struct_buffer *buffer, void *msg_buffer, uint8_t msg_id, uint8_t size) {
18
- if (buffer->in_progress) {
19
- return false;
20
- }
21
- buffer->in_progress = true;
22
-
23
- buffer->data[buffer->size++] = buffer->config.start_byte;
24
- buffer->crc_start_loc = buffer->size;
25
- buffer->data[buffer->size++] = msg_id;
26
-
27
- if (buffer->config.has_len) {
28
- buffer->data[buffer->size++] = size;
29
- }
30
- memcpy(buffer->data + buffer->size, (uint8_t *)msg_buffer, size);
31
- buffer->size += size;
32
- if (buffer->config.has_crc) {
33
- checksum_t crc =
34
- fletcher_checksum_calculation(buffer->data + buffer->crc_start_loc, buffer->crc_start_loc - buffer->size);
35
- buffer->data[buffer->size++] = crc.byte1;
36
- buffer->data[buffer->size++] = crc.byte2;
37
- }
38
- buffer->in_progress = false;
39
- return true;
40
- }
41
-
42
- static inline void *msg_reserve(struct_buffer *buffer, uint8_t msg_id, uint8_t size) {
43
- if (buffer->in_progress) {
44
- return 0;
45
- }
46
- buffer->in_progress = true;
47
- buffer->data[buffer->size++] = buffer->config.start_byte;
48
-
49
- buffer->data[buffer->size++] = msg_id;
50
- if (buffer->config.has_len) {
51
- buffer->data[buffer->size++] = size;
52
- }
53
-
54
- void *out = &buffer->data[buffer->size];
55
- buffer->size += size;
56
-
57
- return out;
58
- }
59
-
60
- static inline bool msg_finish(struct_buffer *buffer) {
61
- if (buffer->in_progress == false) {
62
- return false;
63
- }
64
- if (buffer->config.has_crc) {
65
- checksum_t crc =
66
- fletcher_checksum_calculation(buffer->data + buffer->crc_start_loc, buffer->crc_start_loc - buffer->size);
67
- buffer->data[buffer->size++] = crc.byte1;
68
- buffer->data[buffer->size++] = crc.byte2;
69
- }
70
- buffer->in_progress = false;
71
- return true;
72
- }
73
-
74
- #define MESSAGE_HELPER(funcname, name, msg_size, msg_id) \
75
- static inline bool funcname##_encode(struct_buffer *buffer, name *name##_obj) { \
76
- return msg_encode(buffer, name##_obj, msg_id, msg_size); \
77
- } \
78
- static inline bool funcname##_reserve(struct_buffer *buffer, name **msg) { \
79
- void *ptr = msg_reserve(buffer, msg_id, msg_size); \
80
- if (ptr) { \
81
- *msg = (name *)ptr; \
82
- return true; \
83
- } \
84
- return false; \
85
- } \
86
- static inline bool funcname##_finish(struct_buffer *buffer) { return msg_finish(buffer); } \
87
- static inline name funcname##_get(struct_buffer *buffer) { \
88
- name msg = *(name *)(buffer->data); \
89
- return msg; \
90
- } \
91
- static inline name funcname##_get(uint8_t *buffer) { \
92
- name msg = *(name *)(buffer); \
93
- return msg; \
94
- } \
95
- static inline name funcname##_get_from_buffer_result(buffer_parser_result_t result) { \
96
- name msg = *(name *)(result.msg_loc); \
97
- return msg; \
98
- } \
99
- static inline name *funcname##_get_ref(struct_buffer *buffer) { return (name *)(buffer->data); } \
100
- static inline name *funcname##_get_ref(uint8_t *buffer) { return (name *)(buffer); } \
101
- static inline name *funcname##_get_ref_from_buffer_result(buffer_parser_result_t result) { \
102
- return (name *)(result.msg_loc); \
103
- }