deukpack 1.0.0 → 1.0.2

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.
@@ -0,0 +1,113 @@
1
+ /**
2
+ * DeukPack Compact Writer
3
+ * High-performance compact protocol serialization
4
+ */
5
+
6
+ #include "compact_writer.h"
7
+ #include <cstring>
8
+
9
+ namespace deukpack
10
+ {
11
+
12
+ CompactWriter::CompactWriter(size_t initialSize)
13
+ : position_(0)
14
+ {
15
+ currentBuffer_.resize(initialSize);
16
+ }
17
+
18
+ void CompactWriter::WriteByte(uint8_t value)
19
+ {
20
+ EnsureCapacity(1);
21
+ currentBuffer_[position_++] = value;
22
+ }
23
+
24
+ void CompactWriter::WriteVarInt(int32_t value)
25
+ {
26
+ while (value >= 0x80)
27
+ {
28
+ WriteByte((value & 0x7F) | 0x80);
29
+ value >>= 7;
30
+ }
31
+ WriteByte(value & 0x7F);
32
+ }
33
+
34
+ void CompactWriter::WriteString(const std::string &value)
35
+ {
36
+ WriteVarInt(static_cast<int32_t>(value.length()));
37
+ WriteBytes(reinterpret_cast<const uint8_t *>(value.c_str()), value.length());
38
+ }
39
+
40
+ void CompactWriter::WriteBytes(const uint8_t *data, size_t length)
41
+ {
42
+ EnsureCapacity(length);
43
+ std::memcpy(&currentBuffer_[position_], data, length);
44
+ position_ += length;
45
+ }
46
+
47
+ std::vector<uint8_t> CompactWriter::GetBuffer()
48
+ {
49
+ FlushCurrentBuffer();
50
+
51
+ if (buffers_.empty())
52
+ {
53
+ return std::vector<uint8_t>();
54
+ }
55
+
56
+ if (buffers_.size() == 1)
57
+ {
58
+ return std::move(buffers_[0]);
59
+ }
60
+
61
+ // Calculate total size
62
+ size_t totalSize = 0;
63
+ for (const auto &buffer : buffers_)
64
+ {
65
+ totalSize += buffer.size();
66
+ }
67
+
68
+ // Concatenate all buffers
69
+ std::vector<uint8_t> result;
70
+ result.reserve(totalSize);
71
+
72
+ for (const auto &buffer : buffers_)
73
+ {
74
+ result.insert(result.end(), buffer.begin(), buffer.end());
75
+ }
76
+
77
+ return result;
78
+ }
79
+
80
+ void CompactWriter::Reset()
81
+ {
82
+ buffers_.clear();
83
+ position_ = 0;
84
+ currentBuffer_.resize(1024);
85
+ }
86
+
87
+ void CompactWriter::EnsureCapacity(size_t needed)
88
+ {
89
+ if (position_ + needed > currentBuffer_.size())
90
+ {
91
+ FlushCurrentBuffer();
92
+ AllocateNewBuffer(std::max(needed * 2, static_cast<size_t>(1024)));
93
+ }
94
+ }
95
+
96
+ void CompactWriter::FlushCurrentBuffer()
97
+ {
98
+ if (position_ > 0)
99
+ {
100
+ std::vector<uint8_t> buffer(position_);
101
+ std::memcpy(buffer.data(), currentBuffer_.data(), position_);
102
+ buffers_.push_back(std::move(buffer));
103
+ position_ = 0;
104
+ }
105
+ }
106
+
107
+ void CompactWriter::AllocateNewBuffer(size_t size)
108
+ {
109
+ currentBuffer_.resize(size);
110
+ position_ = 0;
111
+ }
112
+
113
+ } // namespace deukpack
@@ -0,0 +1,380 @@
1
+ /**
2
+ * DeukPack Native C++ Implementation
3
+ * High-performance Thrift engine
4
+ */
5
+
6
+ #include <napi.h>
7
+ #include <iostream>
8
+ #include <vector>
9
+ #include <string>
10
+ #include <unordered_map>
11
+ #include <memory>
12
+ #include <chrono>
13
+ #include "thrift_engine.h"
14
+ #include "binary_writer.h"
15
+
16
+ using namespace deukpack;
17
+
18
+ // ThriftEngine implementation
19
+ class ThriftEngine::Impl
20
+ {
21
+ public:
22
+ Impl() : memoryUsage_(0) {}
23
+
24
+ ThriftAST ParseFiles(const std::vector<std::string> &filePaths)
25
+ {
26
+ auto start = std::chrono::high_resolution_clock::now();
27
+
28
+ ThriftAST ast;
29
+ // TODO: Implement actual parsing logic
30
+ // For now, return empty AST
31
+
32
+ auto end = std::chrono::high_resolution_clock::now();
33
+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
34
+ parseTime_ = duration.count();
35
+
36
+ return ast;
37
+ }
38
+
39
+ std::vector<uint8_t> Serialize(const std::unordered_map<std::string, std::string> &data,
40
+ const SerializationOptions &options)
41
+ {
42
+ auto start = std::chrono::high_resolution_clock::now();
43
+
44
+ BinaryWriter writer(options.endianness == Endianness::LITTLE_ENDIAN ? Endianness::LITTLE_ENDIAN : Endianness::BIG_ENDIAN);
45
+
46
+ // Simple serialization for demonstration
47
+ writer.WriteI32(static_cast<int32_t>(data.size()));
48
+ for (const auto &pair : data)
49
+ {
50
+ writer.WriteString(pair.first);
51
+ writer.WriteString(pair.second);
52
+ }
53
+
54
+ auto result = writer.GetBuffer();
55
+
56
+ auto end = std::chrono::high_resolution_clock::now();
57
+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
58
+ serializeTime_ = duration.count();
59
+
60
+ return result;
61
+ }
62
+
63
+ std::unordered_map<std::string, std::string> Deserialize(const std::vector<uint8_t> &data,
64
+ const SerializationOptions &options)
65
+ {
66
+ auto start = std::chrono::high_resolution_clock::now();
67
+
68
+ std::unordered_map<std::string, std::string> result;
69
+
70
+ // Simple deserialization for demonstration
71
+ if (data.size() >= 4)
72
+ {
73
+ int32_t count = *reinterpret_cast<const int32_t *>(data.data());
74
+ size_t offset = 4;
75
+
76
+ for (int32_t i = 0; i < count && offset < data.size(); i++)
77
+ {
78
+ if (offset + 4 > data.size())
79
+ break;
80
+
81
+ int32_t keyLen = *reinterpret_cast<const int32_t *>(data.data() + offset);
82
+ offset += 4;
83
+
84
+ if (offset + keyLen > data.size())
85
+ break;
86
+ std::string key(data.data() + offset, data.data() + offset + keyLen);
87
+ offset += keyLen;
88
+
89
+ if (offset + 4 > data.size())
90
+ break;
91
+ int32_t valueLen = *reinterpret_cast<const int32_t *>(data.data() + offset);
92
+ offset += 4;
93
+
94
+ if (offset + valueLen > data.size())
95
+ break;
96
+ std::string value(data.data() + offset, data.data() + offset + valueLen);
97
+ offset += valueLen;
98
+
99
+ result[key] = value;
100
+ }
101
+ }
102
+
103
+ auto end = std::chrono::high_resolution_clock::now();
104
+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
105
+ deserializeTime_ = duration.count();
106
+
107
+ return result;
108
+ }
109
+
110
+ size_t GetMemoryUsage() const
111
+ {
112
+ return memoryUsage_;
113
+ }
114
+
115
+ PerformanceMetrics GetPerformanceMetrics() const
116
+ {
117
+ PerformanceMetrics metrics;
118
+ metrics.parseTime = parseTime_;
119
+ metrics.generateTime = generateTime_;
120
+ metrics.serializeTime = serializeTime_;
121
+ metrics.deserializeTime = deserializeTime_;
122
+ metrics.memoryUsage = memoryUsage_;
123
+ metrics.fileCount = fileCount_;
124
+ metrics.lineCount = lineCount_;
125
+ return metrics;
126
+ }
127
+
128
+ void ResetMetrics()
129
+ {
130
+ parseTime_ = 0;
131
+ generateTime_ = 0;
132
+ serializeTime_ = 0;
133
+ deserializeTime_ = 0;
134
+ memoryUsage_ = 0;
135
+ fileCount_ = 0;
136
+ lineCount_ = 0;
137
+ }
138
+
139
+ private:
140
+ double parseTime_ = 0;
141
+ double generateTime_ = 0;
142
+ double serializeTime_ = 0;
143
+ double deserializeTime_ = 0;
144
+ size_t memoryUsage_ = 0;
145
+ int32_t fileCount_ = 0;
146
+ int32_t lineCount_ = 0;
147
+ };
148
+
149
+ ThriftEngine::ThriftEngine() : impl_(std::make_unique<Impl>()) {}
150
+ ThriftEngine::~ThriftEngine() = default;
151
+
152
+ ThriftAST ThriftEngine::ParseFiles(const std::vector<std::string> &filePaths)
153
+ {
154
+ return impl_->ParseFiles(filePaths);
155
+ }
156
+
157
+ std::vector<uint8_t> ThriftEngine::Serialize(const std::unordered_map<std::string, std::string> &data,
158
+ const SerializationOptions &options)
159
+ {
160
+ return impl_->Serialize(data, options);
161
+ }
162
+
163
+ std::unordered_map<std::string, std::string> ThriftEngine::Deserialize(const std::vector<uint8_t> &data,
164
+ const SerializationOptions &options)
165
+ {
166
+ return impl_->Deserialize(data, options);
167
+ }
168
+
169
+ size_t ThriftEngine::GetMemoryUsage() const
170
+ {
171
+ return impl_->GetMemoryUsage();
172
+ }
173
+
174
+ PerformanceMetrics ThriftEngine::GetPerformanceMetrics() const
175
+ {
176
+ return impl_->GetPerformanceMetrics();
177
+ }
178
+
179
+ void ThriftEngine::ResetMetrics()
180
+ {
181
+ impl_->ResetMetrics();
182
+ }
183
+
184
+ // N-API wrapper functions
185
+ Napi::Value CreateEngine(const Napi::CallbackInfo &info)
186
+ {
187
+ Napi::Env env = info.Env();
188
+
189
+ try
190
+ {
191
+ auto engine = std::make_unique<ThriftEngine>();
192
+ return Napi::External<ThriftEngine>::New(env, engine.release());
193
+ }
194
+ catch (const std::exception &e)
195
+ {
196
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
197
+ return env.Null();
198
+ }
199
+ }
200
+
201
+ Napi::Value ParseFiles(const Napi::CallbackInfo &info)
202
+ {
203
+ Napi::Env env = info.Env();
204
+
205
+ if (info.Length() < 2 || !info[0].IsExternal() || !info[1].IsArray())
206
+ {
207
+ Napi::TypeError::New(env, "Expected engine and file paths array").ThrowAsJavaScriptException();
208
+ return env.Null();
209
+ }
210
+
211
+ try
212
+ {
213
+ auto engine = info[0].As<Napi::External<ThriftEngine>>().Data();
214
+ auto filePaths = info[1].As<Napi::Array>();
215
+
216
+ std::vector<std::string> paths;
217
+ for (uint32_t i = 0; i < filePaths.Length(); i++)
218
+ {
219
+ if (filePaths.Get(i).IsString())
220
+ {
221
+ paths.push_back(filePaths.Get(i).As<Napi::String>().Utf8Value());
222
+ }
223
+ }
224
+
225
+ auto ast = engine->ParseFiles(paths);
226
+
227
+ // Convert AST to JavaScript object
228
+ auto result = Napi::Object::New(env);
229
+ result.Set("namespaces", Napi::Array::New(env));
230
+ result.Set("structs", Napi::Array::New(env));
231
+ result.Set("enums", Napi::Array::New(env));
232
+ result.Set("services", Napi::Array::New(env));
233
+ result.Set("includes", Napi::Array::New(env));
234
+
235
+ return result;
236
+ }
237
+ catch (const std::exception &e)
238
+ {
239
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
240
+ return env.Null();
241
+ }
242
+ }
243
+
244
+ Napi::Value Serialize(const Napi::CallbackInfo &info)
245
+ {
246
+ Napi::Env env = info.Env();
247
+
248
+ if (info.Length() < 3 || !info[0].IsExternal() || !info[1].IsObject() || !info[2].IsObject())
249
+ {
250
+ Napi::TypeError::New(env, "Expected engine, data object, and options object").ThrowAsJavaScriptException();
251
+ return env.Null();
252
+ }
253
+
254
+ try
255
+ {
256
+ auto engine = info[0].As<Napi::External<ThriftEngine>>().Data();
257
+ auto dataObj = info[1].As<Napi::Object>();
258
+ auto optionsObj = info[2].As<Napi::Object>();
259
+
260
+ // Convert JavaScript object to map
261
+ std::unordered_map<std::string, std::string> data;
262
+ auto keys = dataObj.GetPropertyNames();
263
+ for (uint32_t i = 0; i < keys.Length(); i++)
264
+ {
265
+ auto key = keys.Get(i).As<Napi::String>().Utf8Value();
266
+ auto value = dataObj.Get(key).As<Napi::String>().Utf8Value();
267
+ data[key] = value;
268
+ }
269
+
270
+ // Create serialization options
271
+ SerializationOptions options;
272
+ options.protocol = ThriftProtocol::BINARY;
273
+ options.endianness = Endianness::LITTLE_ENDIAN;
274
+ options.optimizeForSize = true;
275
+ options.includeDefaultValues = false;
276
+ options.validateTypes = true;
277
+
278
+ auto result = engine->Serialize(data, options);
279
+
280
+ // Convert to Node.js Buffer
281
+ auto buffer = Napi::Buffer<uint8_t>::Copy(env, result.data(), result.size());
282
+ return buffer;
283
+ }
284
+ catch (const std::exception &e)
285
+ {
286
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
287
+ return env.Null();
288
+ }
289
+ }
290
+
291
+ Napi::Value Deserialize(const Napi::CallbackInfo &info)
292
+ {
293
+ Napi::Env env = info.Env();
294
+
295
+ if (info.Length() < 3 || !info[0].IsExternal() || !info[1].IsBuffer() || !info[2].IsObject())
296
+ {
297
+ Napi::TypeError::New(env, "Expected engine, buffer, and options object").ThrowAsJavaScriptException();
298
+ return env.Null();
299
+ }
300
+
301
+ try
302
+ {
303
+ auto engine = info[0].As<Napi::External<ThriftEngine>>().Data();
304
+ auto buffer = info[1].As<Napi::Buffer<uint8_t>>();
305
+ auto optionsObj = info[2].As<Napi::Object>();
306
+
307
+ // Convert buffer to vector
308
+ std::vector<uint8_t> data(buffer.Data(), buffer.Data() + buffer.Length());
309
+
310
+ // Create serialization options
311
+ SerializationOptions options;
312
+ options.protocol = ThriftProtocol::BINARY;
313
+ options.endianness = Endianness::LITTLE_ENDIAN;
314
+ options.optimizeForSize = true;
315
+ options.includeDefaultValues = false;
316
+ options.validateTypes = true;
317
+
318
+ auto result = engine->Deserialize(data, options);
319
+
320
+ // Convert map to JavaScript object
321
+ auto resultObj = Napi::Object::New(env);
322
+ for (const auto &pair : result)
323
+ {
324
+ resultObj.Set(pair.first, pair.second);
325
+ }
326
+
327
+ return resultObj;
328
+ }
329
+ catch (const std::exception &e)
330
+ {
331
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
332
+ return env.Null();
333
+ }
334
+ }
335
+
336
+ Napi::Value GetPerformanceMetrics(const Napi::CallbackInfo &info)
337
+ {
338
+ Napi::Env env = info.Env();
339
+
340
+ if (info.Length() < 1 || !info[0].IsExternal())
341
+ {
342
+ Napi::TypeError::New(env, "Expected engine").ThrowAsJavaScriptException();
343
+ return env.Null();
344
+ }
345
+
346
+ try
347
+ {
348
+ auto engine = info[0].As<Napi::External<ThriftEngine>>().Data();
349
+ auto metrics = engine->GetPerformanceMetrics();
350
+
351
+ auto result = Napi::Object::New(env);
352
+ result.Set("parseTime", metrics.parseTime);
353
+ result.Set("generateTime", metrics.generateTime);
354
+ result.Set("serializeTime", metrics.serializeTime);
355
+ result.Set("deserializeTime", metrics.deserializeTime);
356
+ result.Set("memoryUsage", static_cast<double>(metrics.memoryUsage));
357
+ result.Set("fileCount", metrics.fileCount);
358
+ result.Set("lineCount", metrics.lineCount);
359
+
360
+ return result;
361
+ }
362
+ catch (const std::exception &e)
363
+ {
364
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
365
+ return env.Null();
366
+ }
367
+ }
368
+
369
+ Napi::Object Init(Napi::Env env, Napi::Object exports)
370
+ {
371
+ exports.Set(Napi::String::New(env, "createEngine"), Napi::Function::New(env, CreateEngine));
372
+ exports.Set(Napi::String::New(env, "parseFiles"), Napi::Function::New(env, ParseFiles));
373
+ exports.Set(Napi::String::New(env, "serialize"), Napi::Function::New(env, Serialize));
374
+ exports.Set(Napi::String::New(env, "deserialize"), Napi::Function::New(env, Deserialize));
375
+ exports.Set(Napi::String::New(env, "getPerformanceMetrics"), Napi::Function::New(env, GetPerformanceMetrics));
376
+
377
+ return exports;
378
+ }
379
+
380
+ NODE_API_MODULE(thrift_engine_native, Init)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deukpack",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "DeukPack — multi-format IDL pipeline (.deuk native, Protobuf, OpenAPI, JSON Schema, CSV, Thrift). Protobuf-aligned wire; fast C#/C++/JS codegen, CLI. v1: no Excel/table editor workflow",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -13,7 +13,7 @@
13
13
  "build:native": "node-gyp rebuild",
14
14
  "build:all": "npm run build && npm run build:cpp && npm run build:cs",
15
15
  "build:cpp": "cd native/cpp && mkdir -p build && cd build && cmake .. && make",
16
- "build:cs": "cd native/csharp && dotnet build -c Release",
16
+ "build:cs": "cd DeukPack.Protocol && dotnet build -c Release",
17
17
  "test": "jest",
18
18
  "benchmark": "node benchmarks/performance.js",
19
19
  "dev": "tsc --watch",
@@ -65,6 +65,8 @@
65
65
  "bin",
66
66
  "scripts/build_deukpack.js",
67
67
  "dist",
68
+ "native/cpp",
69
+ "binding.gyp",
68
70
  "LICENSE",
69
71
  "NOTICE",
70
72
  "README.md",