skir-cc-gen 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.
package/README.md CHANGED
@@ -7,20 +7,65 @@ Official plugin for generating C++ code from [.skir](https://github.com/gepheum/
7
7
 
8
8
  Targets C++17 and higher.
9
9
 
10
- ## Installation
11
-
12
- From your project's root directory, run `npm i --save-dev skir-cc-gen`.
10
+ ## Set up
13
11
 
14
12
  In your `skir.yml` file, add the following snippet under `generators`:
15
13
  ```yaml
16
14
  - mod: skir-cc-gen
15
+ outDir: ./src/skirout
17
16
  config:
18
- writeGoogleTestHeaders: true
17
+ writeGoogleTestHeaders: true # If you use GoogleTest
18
+ ```
19
+
20
+ ## Runtime dependencies
21
+
22
+ The generated C++ code depends on the [skir client library](https://github.com/gepheum/skir-cc-gen/tree/main/client), [absl](https://abseil.io/) and optionally [GoogleTest](https://github.com/google/googletest).
23
+
24
+ ### If you use CMake
25
+
26
+ Add this to your `CMakeLists.txt`:
27
+
28
+ ```cmake
29
+ include(FetchContent)
30
+
31
+ # Should be ON if writeGoogleTestHeaders is true
32
+ option(BUILD_TESTING "Build tests" OFF)
33
+
34
+ # Abseil (required, version 20250814.0+)
35
+ FetchContent_Declare(
36
+ absl
37
+ GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git
38
+ GIT_TAG 20250814.1 # Use 20250814.0 or later
39
+ )
40
+ set(ABSL_PROPAGATE_CXX_STD ON)
41
+ FetchContent_MakeAvailable(absl)
42
+
43
+ if(BUILD_TESTING)
44
+ # GoogleTest (optional - only if you use writeGoogleTestHeaders)
45
+ FetchContent_Declare(
46
+ googletest
47
+ GIT_REPOSITORY https://github.com/google/googletest.git
48
+ GIT_TAG v1.15.2 # Pick the latest tag
49
+ )
50
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
51
+ FetchContent_MakeAvailable(googletest)
52
+ endif()
53
+
54
+ # skir-client
55
+ FetchContent_Declare(
56
+ skir-client
57
+ GIT_REPOSITORY https://github.com/gepheum/skir-cc-gen.git
58
+ GIT_TAG main # Or pick a specific commit/tag
59
+ SOURCE_SUBDIR client
60
+ )
61
+ FetchContent_MakeAvailable(skir-client)
19
62
  ```
20
63
 
21
- The `npm run skir` command will now generate C++ code within the `skirout` directory.
64
+ See this [example](https://github.com/gepheum/skir-cc-example/blob/main/CMakeLists.txt).
65
+
66
+ ### If you use Bazel
22
67
 
23
- For more information, see this C++ project [example](https://github.com/gepheum/skir-cc-example).
68
+ Refer to this example [BUILD.bazel](https://github.com/gepheum/skir-cc-example/blob/main/BUILD.bazel) file.
24
69
 
25
70
  ## C++ generated code guide
26
71
 
@@ -36,6 +81,7 @@ replaced with underscores.
36
81
  ```c++
37
82
  #include "skirout/user.h"
38
83
 
84
+ using ::skirout_user::SubscriptionStatus;
39
85
  using ::skirout_user::User;
40
86
  using ::skirout_user::UserRegistry;
41
87
  ```
@@ -64,7 +110,7 @@ User jane = {
64
110
  .user_id = 43,
65
111
  };
66
112
 
67
- // ${StructName}::whole forces you to initialize all the fields of the struct.
113
+ // ${Struct}::whole forces you to initialize all the fields of the struct.
68
114
  // You will get a compile-time error if you miss one.
69
115
  User lyla = User::whole{
70
116
  .name = "Lyla Doe",
@@ -86,20 +132,22 @@ User lyla = User::whole{
86
132
 
87
133
  ```c++
88
134
 
89
- // Use skirout::${kFieldName} for constant variants.
90
- User::SubscriptionStatus john_status = skirout::kFree;
91
- User::SubscriptionStatus jane_status = skirout::kPremium;
135
+ // Use skirout::${kFieldName} or ${Enum}::${kFieldName} for constant variants.
136
+ SubscriptionStatus john_status = skirout::kFree;
137
+ SubscriptionStatus jane_status = skirout::kPremium;
138
+ SubscriptionStatus lara_status = SubscriptionStatus::kFree;
92
139
 
93
140
  // Compilation error: MONDAY is not a field of the SubscriptionStatus enum.
94
- // User::SubscriptionStatus sara_status = skirout::kMonday;
95
-
96
- // Use skirout::wrap_${field_name} for data variants.
97
- User::SubscriptionStatus jade_status =
98
- skirout::wrap_trial_start_time(absl::FromUnixMillis(1743682787000));
99
-
100
- // The ${kFieldName} and wrap_${field_name} symbols are also defined in the
101
- // generated class.
102
- User::SubscriptionStatus lara_status = User::SubscriptionStatus::kFree;
141
+ // SubscriptionStatus sara_status = skirout::kMonday;
142
+
143
+ // Use wrap_${field_name} for wrapper variants.
144
+ SubscriptionStatus jade_status =
145
+ skirout::wrap_trial(SubscriptionStatus::Trial({
146
+ .start_time = absl::FromUnixMillis(1743682787000),
147
+ }));
148
+ SubscriptionStatus roni_status = SubscriptionStatus::wrap_trial({
149
+ .start_time = absl::FromUnixMillis(1743682787000),
150
+ });
103
151
  ```
104
152
 
105
153
  ### Conditions on enums
@@ -109,28 +157,28 @@ if (john_status == skirout::kFree) {
109
157
  std::cout << "John, would you like to upgrade to premium?\n";
110
158
  }
111
159
 
112
- // Call is_${field_name}() to check if the enum holds a data variant.
113
- if (jade_status.is_trial_start_time()) {
114
- // as_${field_name}() returns the value held by the enum
115
- const absl::Time trial_start_time = jade_status.as_trial_start_time();
116
- std::cout << "Jade's trial started on " << trial_start_time << "\n";
160
+ // Call is_${field_name}() to check if the enum holds a wrapper variant.
161
+ if (jade_status.is_trial()) {
162
+ // as_${field_name}() returns the wrapped value
163
+ const SubscriptionStatus::Trial& trial = jade_status.as_trial();
164
+ std::cout << "Jade's trial started on " << trial.start_time << "\n";
117
165
  }
118
166
 
119
167
  // One way to do an exhaustive switch on an enum.
120
168
  switch (lara_status.kind()) {
121
- case User::SubscriptionStatus::kind_type::kUnknown:
169
+ case SubscriptionStatus::kind_type::kUnknown:
122
170
  // UNKNOWN is the default value for an uninitialized SubscriptionStatus.
123
171
  // ...
124
172
  break;
125
- case User::SubscriptionStatus::kind_type::kFreeConst:
173
+ case SubscriptionStatus::kind_type::kFreeConst:
126
174
  // ...
127
175
  break;
128
- case User::SubscriptionStatus::kind_type::kPremiumConst:
176
+ case SubscriptionStatus::kind_type::kPremiumConst:
129
177
  // ...
130
178
  break;
131
- case User::SubscriptionStatus::kind_type::kTrialStartTimeWrapper: {
132
- const absl::Time& trial_start_time = lara_status.as_trial_start_time();
133
- std::cout << "Lara's trial started on " << trial_start_time << "\n";
179
+ case SubscriptionStatus::kind_type::kTrialWrapper: {
180
+ const SubscriptionStatus::Trial& trial = lara_status.as_trial();
181
+ std::cout << "Lara's trial started on " << trial.start_time << "\n";
134
182
  }
135
183
  }
136
184
 
@@ -145,10 +193,9 @@ struct Visitor {
145
193
  void operator()(skirout::k_premium) const {
146
194
  std::cout << "Lara's subscription status is PREMIUM\n";
147
195
  }
148
- void operator()(
149
- User::SubscriptionStatus::wrap_trial_start_time_type& w) const {
150
- const absl::Time& trial_start_time = w.value;
151
- std::cout << "Lara's trial started on " << trial_start_time << "\n";
196
+ void operator()(SubscriptionStatus::wrap_trial_type& w) const {
197
+ const SubscriptionStatus::Trial& trial = w.value;
198
+ std::cout << "Lara's trial started on " << trial.start_time << "\n";
152
199
  }
153
200
  };
154
201
  lara_status.visit(Visitor());
@@ -212,6 +259,13 @@ assert(maybe_jane != nullptr && *maybe_jane == jane);
212
259
 
213
260
  assert(users.find_or_default(44).name == "Lyla Doe");
214
261
  assert(users.find_or_default(45).name == "");
262
+
263
+ // If multiple items have the same key, find_or_null and find_or_default
264
+ // return the last one. Duplicates are allowed but generally discouraged.
265
+ User evil_lyla = lyla;
266
+ evil_lyla.name = "Evil Lyla";
267
+ users.push_back(evil_lyla);
268
+ assert(users.find_or_default(44).name == "Evil Lyla");
215
269
  ```
216
270
 
217
271
  ### Equality and hashing
@@ -265,7 +319,7 @@ assert(reserialized_type_descriptor.ok());
265
319
  ### Static reflection
266
320
 
267
321
  Static reflection allows you to inspect and modify values of generated
268
- skir types in a typesafe maneer.
322
+ skir types in a typesafe manner.
269
323
 
270
324
  See [string_capitalizer.h](https://github.com/gepheum/skir-cc-example/blob/main/string_capitalizer.h).
271
325
 
@@ -287,10 +341,10 @@ std::cout << tarzan_copy << "\n";
287
341
  // .picture: "🐒",
288
342
  // },
289
343
  // },
290
- // .subscription_status: ::skirout::wrap_trial_start_time(absl::FromUnixMillis(1743592409000 /* 2025-04-02T11:13:29+00:00 */)),
344
+ // .subscription_status:
345
+ // ::skirout::wrap_trial_start_time(absl::FromUnixMillis(1743592409000 /*
346
+ // 2025-04-02T11:13:29+00:00 */)),
291
347
  // }
292
-
293
- // ...
294
348
  ```
295
349
 
296
350
  ### Writing unit tests with GoogleTest
@@ -323,13 +377,14 @@ EXPECT_THAT(john, (StructIs<User>{
323
377
  #### Enum matchers
324
378
 
325
379
  ```c++
326
- User::SubscriptionStatus john_status = skirout::kFree;
380
+ SubscriptionStatus john_status = skirout::kFree;
327
381
 
328
382
  EXPECT_THAT(john_status, testing::Eq(skirout::kFree));
329
383
 
330
- User::SubscriptionStatus jade_status =
331
- skirout::wrap_trial_start_time(absl::FromUnixMillis(1743682787000));
384
+ SubscriptionStatus jade_status = SubscriptionStatus::wrap_trial(
385
+ {.start_time = absl::FromUnixMillis(1743682787000)});
332
386
 
333
- EXPECT_THAT(jade_status, IsTrialStartTime());
334
- EXPECT_THAT(jade_status, IsTrialStartTime(testing::Gt(absl::UnixEpoch())));
387
+ EXPECT_THAT(jade_status, IsTrial());
388
+ EXPECT_THAT(jade_status, IsTrial(StructIs<SubscriptionStatus::Trial>{
389
+ .start_time = testing::Gt(absl::UnixEpoch())}));
335
390
  ```
@@ -0,0 +1,90 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+ project(skir-client CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 17)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+
7
+ # ============================================================================
8
+ # Dependencies - Use existing targets if available, otherwise find them
9
+ # ============================================================================
10
+
11
+ # Abseil - check if already provided by parent project
12
+ if(NOT TARGET absl::base)
13
+ find_package(absl REQUIRED)
14
+ endif()
15
+
16
+ # GoogleTest - optional, only needed for testing library
17
+ if(NOT DEFINED SKIR_ENABLE_TESTING)
18
+ # Default: enable testing if GTest is available
19
+ if(TARGET GTest::gtest)
20
+ set(SKIR_ENABLE_TESTING ON)
21
+ else()
22
+ find_package(GTest QUIET)
23
+ if(GTest_FOUND)
24
+ set(SKIR_ENABLE_TESTING ON)
25
+ else()
26
+ set(SKIR_ENABLE_TESTING OFF)
27
+ endif()
28
+ endif()
29
+ endif()
30
+
31
+ message(STATUS "Skir testing library: ${SKIR_ENABLE_TESTING}")
32
+
33
+ # ============================================================================
34
+ # Main skir library
35
+ # ============================================================================
36
+
37
+ add_library(skir
38
+ skir.cc
39
+ skir.h
40
+ )
41
+
42
+ target_include_directories(skir PUBLIC
43
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
44
+ $<INSTALL_INTERFACE:include>
45
+ )
46
+
47
+ target_link_libraries(skir PUBLIC
48
+ absl::base
49
+ absl::flat_hash_map
50
+ absl::hash
51
+ absl::check
52
+ absl::die_if_null
53
+ absl::status
54
+ absl::statusor
55
+ absl::strings
56
+ absl::time
57
+ absl::optional
58
+ absl::variant
59
+ )
60
+
61
+ # ============================================================================
62
+ # Testing library (interface library with header-only implementation)
63
+ # Only built if GTest is available
64
+ # ============================================================================
65
+
66
+ if(SKIR_ENABLE_TESTING)
67
+ add_library(skir_testing INTERFACE)
68
+
69
+ target_sources(skir_testing INTERFACE
70
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/skir.testing.h>
71
+ $<INSTALL_INTERFACE:include/skir.testing.h>
72
+ )
73
+
74
+ target_include_directories(skir_testing INTERFACE
75
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
76
+ $<INSTALL_INTERFACE:include>
77
+ )
78
+
79
+ target_link_libraries(skir_testing INTERFACE
80
+ skir
81
+ absl::base
82
+ absl::die_if_null
83
+ GTest::gtest
84
+ GTest::gmock
85
+ )
86
+
87
+ message(STATUS "Skir testing library target created")
88
+ else()
89
+ message(STATUS "Skir testing library disabled (GTest not available)")
90
+ endif()
package/client/skir.cc CHANGED
@@ -996,6 +996,63 @@ void ParseFieldOrVariant(JsonTokenizer& tokenizer, FieldOrVariant& out) {
996
996
  }
997
997
  } // namespace
998
998
 
999
+ skir::service::RawResponse MakeOkJsonResponse(std::string data) {
1000
+ return {
1001
+ .data = std::move(data),
1002
+ .status_code = 200,
1003
+ .content_type = "application/json",
1004
+ };
1005
+ }
1006
+
1007
+ skir::service::RawResponse MakeOkHtmlResponse(std::string data) {
1008
+ return {
1009
+ .data = std::move(data),
1010
+ .status_code = 200,
1011
+ .content_type = "text/html; charset=utf-8",
1012
+ };
1013
+ }
1014
+
1015
+ std::string GetStudioHtml(absl::string_view studio_app_js_url) {
1016
+ const std::string escaped_url =
1017
+ absl::StrReplaceAll(studio_app_js_url, {{"&", "&amp;"},
1018
+ {"<", "&lt;"},
1019
+ {">", "&gt;"},
1020
+ {"\"", "&quot;"},
1021
+ {"'", "&#39;"}});
1022
+ return absl::StrCat(R"html(<!DOCTYPE html>
1023
+
1024
+ <html>
1025
+ <head>
1026
+ <meta charset="utf-8" />
1027
+ <title>Skir Studio</title>
1028
+ <script src=")html",
1029
+ escaped_url,
1030
+ R"html("></script>
1031
+ </head>
1032
+ <body style="margin: 0; padding: 0;">
1033
+ <skir-studio-app></skir-studio-app>
1034
+ </body>
1035
+ </html>
1036
+ )html");
1037
+ }
1038
+
1039
+ skir::service::RawResponse MakeBadRequestResponse(std::string data) {
1040
+ return {
1041
+ .data = std::move(data),
1042
+ .status_code = 400,
1043
+ .content_type = "text/plain; charset=utf-8",
1044
+ };
1045
+ }
1046
+
1047
+ skir::service::RawResponse MakeServerErrorResponse(std::string data,
1048
+ int status_code) {
1049
+ return {
1050
+ .data = std::move(data),
1051
+ .status_code = status_code,
1052
+ .content_type = "text/plain; charset=utf-8",
1053
+ };
1054
+ }
1055
+
999
1056
  JsonTokenType JsonTokenizer::Next() {
1000
1057
  if (!state_.status.ok()) return JsonTokenType::kError;
1001
1058
  return state_.token_type = NextImpl(state_);
@@ -1368,7 +1425,7 @@ void Int64Adapter::Parse(ByteSource& source, int64_t& out) {
1368
1425
  ParseNumber(source, out);
1369
1426
  }
1370
1427
 
1371
- void Uint64Adapter::Append(uint64_t input, ByteSink& out) {
1428
+ void Hash64Adapter::Append(uint64_t input, ByteSink& out) {
1372
1429
  if (input < 232) {
1373
1430
  out.Push(input);
1374
1431
  } else if (input < 4294967296) {
@@ -1382,11 +1439,11 @@ void Uint64Adapter::Append(uint64_t input, ByteSink& out) {
1382
1439
  }
1383
1440
  }
1384
1441
 
1385
- void Uint64Adapter::Parse(JsonTokenizer& tokenizer, uint64_t& out) {
1442
+ void Hash64Adapter::Parse(JsonTokenizer& tokenizer, uint64_t& out) {
1386
1443
  ParseJsonNumber(tokenizer, out);
1387
1444
  }
1388
1445
 
1389
- void Uint64Adapter::Parse(ByteSource& source, uint64_t& out) {
1446
+ void Hash64Adapter::Parse(ByteSource& source, uint64_t& out) {
1390
1447
  ParseNumber(source, out);
1391
1448
  }
1392
1449
 
@@ -1730,8 +1787,8 @@ void ReflectionPrimitiveTypeAdapter::Append(
1730
1787
  out.out += "\"int64\"";
1731
1788
  break;
1732
1789
  }
1733
- case skir::reflection::PrimitiveType::kUint64: {
1734
- out.out += "\"uint64\"";
1790
+ case skir::reflection::PrimitiveType::kHash64: {
1791
+ out.out += "\"hash64\"";
1735
1792
  break;
1736
1793
  }
1737
1794
  case skir::reflection::PrimitiveType::kFloat32: {
@@ -1764,7 +1821,7 @@ void ReflectionPrimitiveTypeAdapter::Parse(
1764
1821
  {"bool", skir::reflection::PrimitiveType::kBool},
1765
1822
  {"int32", skir::reflection::PrimitiveType::kInt32},
1766
1823
  {"int64", skir::reflection::PrimitiveType::kInt64},
1767
- {"uint64", skir::reflection::PrimitiveType::kUint64},
1824
+ {"hash64", skir::reflection::PrimitiveType::kHash64},
1768
1825
  {"float32", skir::reflection::PrimitiveType::kFloat32},
1769
1826
  {"float64", skir::reflection::PrimitiveType::kFloat64},
1770
1827
  {"timestamp", skir::reflection::PrimitiveType::kTimestamp},
@@ -2098,7 +2155,7 @@ void UnrecognizedValues::ParseFrom(JsonTokenizer& tokenizer) {
2098
2155
  break;
2099
2156
  }
2100
2157
  case JsonTokenType::kUnsignedInteger: {
2101
- Uint64Adapter::Append(tokenizer.state().uint_value, bytes_);
2158
+ Hash64Adapter::Append(tokenizer.state().uint_value, bytes_);
2102
2159
  tokenizer.Next();
2103
2160
  break;
2104
2161
  }
@@ -2252,8 +2309,8 @@ void UnrecognizedValues::AppendTo(DenseJson& out) const {
2252
2309
  const uint8_t byte = *source.pos;
2253
2310
  if (byte <= 234) {
2254
2311
  uint64_t number = 0;
2255
- Uint64Adapter::Parse(source, number);
2256
- Uint64Adapter::Append(number, out);
2312
+ Hash64Adapter::Parse(source, number);
2313
+ Hash64Adapter::Append(number, out);
2257
2314
  } else {
2258
2315
  switch (static_cast<uint8_t>(byte - 235)) {
2259
2316
  case 0:
package/client/skir.h CHANGED
@@ -432,7 +432,7 @@ class keyed_items {
432
432
  kUint8,
433
433
  kUint16,
434
434
  kUint32,
435
- kUint64,
435
+ kHash64,
436
436
  };
437
437
  SlotType slot_type_ = SlotType::kUint8;
438
438
  bool being_mutated_ = false;
@@ -477,7 +477,7 @@ class keyed_items {
477
477
  case SlotType::kUint32:
478
478
  PutSlot<uint32_t>(key_hash, next_index);
479
479
  break;
480
- case SlotType::kUint64:
480
+ case SlotType::kHash64:
481
481
  PutSlot<uint64_t>(key_hash, next_index);
482
482
  break;
483
483
  }
@@ -573,7 +573,7 @@ class keyed_items {
573
573
  } else if (capacity <= std::numeric_limits<uint32_t>::max()) {
574
574
  return SlotType::kUint32;
575
575
  } else {
576
- return SlotType::kUint64;
576
+ return SlotType::kHash64;
577
577
  }
578
578
  }
579
579
 
@@ -765,7 +765,7 @@ enum class PrimitiveType {
765
765
  kBool,
766
766
  kInt32,
767
767
  kInt64,
768
- kUint64,
768
+ kHash64,
769
769
  kFloat32,
770
770
  kFloat64,
771
771
  kTimestamp,
@@ -882,64 +882,120 @@ struct enum_wrapper_variant {
882
882
 
883
883
  namespace service {
884
884
 
885
- enum class ResponseType {
886
- // The method invocation succeeded and the response data is in JSON format.
887
- kOkJson,
888
- // The method invocation succeeded and the response data is in HTML format.
889
- kOkHtml,
890
- // The method invocation failed because the request was malformed.
891
- // The response data is "bad-request:" followed by an error message.
892
- kBadRequest,
893
- // The method invocation resulted in an error on the server side.
894
- // The response data is "server-error:" followed by an error message.
895
- kServerError,
896
- };
897
-
898
- // Raw response returned by the server.
899
- struct RawResponse {
900
- // The meaning of this string depends on the response type.
901
- std::string data;
902
- ResponseType type{};
885
+ // HTTP status codes for errors.
886
+ enum class HttpErrorCode {
887
+ k400_BadRequest = 400,
888
+ k401_Unauthorized = 401,
889
+ k402_PaymentRequired = 402,
890
+ k403_Forbidden = 403,
891
+ k404_NotFound = 404,
892
+ k405_MethodNotAllowed = 405,
893
+ k406_NotAcceptable = 406,
894
+ k407_ProxyAuthenticationRequired = 407,
895
+ k408_RequestTimeout = 408,
896
+ k409_Conflict = 409,
897
+ k410_Gone = 410,
898
+ k411_LengthRequired = 411,
899
+ k412_PreconditionFailed = 412,
900
+ k413_ContentTooLarge = 413,
901
+ k414_UriTooLong = 414,
902
+ k415_UnsupportedMediaType = 415,
903
+ k416_RangeNotSatisfiable = 416,
904
+ k417_ExpectationFailed = 417,
905
+ k418_ImATeapot = 418,
906
+ k421_MisdirectedRequest = 421,
907
+ k422_UnprocessableContent = 422,
908
+ k423_Locked = 423,
909
+ k424_FailedDependency = 424,
910
+ k425_TooEarly = 425,
911
+ k426_UpgradeRequired = 426,
912
+ k428_PreconditionRequired = 428,
913
+ k429_TooManyRequests = 429,
914
+ k431_RequestHeaderFieldsTooLarge = 431,
915
+ k451_UnavailableForLegalReasons = 451,
916
+ k500_InternalServerError = 500,
917
+ k501_NotImplemented = 501,
918
+ k502_BadGateway = 502,
919
+ k503_ServiceUnavailable = 503,
920
+ k504_GatewayTimeout = 504,
921
+ k505_HttpVersionNotSupported = 505,
922
+ k506_VariantAlsoNegotiates = 506,
923
+ k507_InsufficientStorage = 507,
924
+ k508_LoopDetected = 508,
925
+ k510_NotExtended = 510,
926
+ k511_NetworkAuthenticationRequired = 511,
927
+ };
928
+
929
+ // Represents an error with a specific HTTP status code.
930
+ // Use this as a return type from service methods when you want to control the
931
+ // HTTP error code sent to clients. For generic errors where the default 500
932
+ // status code is acceptable, use absl::Status instead.
933
+ struct Error {
934
+ HttpErrorCode code = HttpErrorCode::k500_InternalServerError;
935
+ std::string message;
936
+ };
937
+
938
+ // Represents either a successful Response or an Error with a specific HTTP
939
+ // status code. Use this as the return type for service methods when you need
940
+ // fine-grained control over HTTP error codes. For simple error handling where
941
+ // generic HTTP status codes are sufficient, use absl::StatusOr<Response>
942
+ // instead.
943
+ template <typename Response>
944
+ class ErrorOr {
945
+ public:
946
+ ErrorOr() = default;
947
+ ErrorOr(const ErrorOr&) = default;
948
+ ErrorOr(ErrorOr&&) = default;
903
949
 
904
- int status_code() const {
905
- switch (type) {
906
- case ResponseType::kOkJson:
907
- case ResponseType::kOkHtml:
908
- return 200;
909
- case ResponseType::kBadRequest:
910
- return 400;
911
- case ResponseType::kServerError:
912
- return 500;
913
- }
950
+ ErrorOr(Response response) : variant_(std::move(response)) {}
951
+ ErrorOr(Error error) : variant_(std::move(error)) {}
952
+ ErrorOr(absl::StatusOr<Response> response_or_error) {
953
+ (*this) = std::move(response_or_error);
914
954
  }
915
955
 
916
- absl::string_view content_type() const {
917
- switch (type) {
918
- case ResponseType::kOkJson: {
919
- static const char kApplicationJson[] = "application/json";
920
- return kApplicationJson;
921
- }
922
- case ResponseType::kOkHtml: {
923
- static const char kTextHtml[] = "text/html";
924
- return kTextHtml;
925
- }
926
- case ResponseType::kBadRequest:
927
- case ResponseType::kServerError: {
928
- static const char kTextPlain[] = "text/plain; charset=utf-8";
929
- return kTextPlain;
930
- }
956
+ ErrorOr& operator=(const ErrorOr&) = default;
957
+ ErrorOr& operator=(ErrorOr&&) = default;
958
+
959
+ ErrorOr& operator=(Response response) {
960
+ variant_ = std::move(response);
961
+ return *this;
962
+ }
963
+ ErrorOr& operator=(Error error) {
964
+ variant_ = std::move(error);
965
+ return *this;
966
+ }
967
+ ErrorOr& operator=(absl::StatusOr<Response> response_or_error) {
968
+ if (response_or_error.ok()) {
969
+ variant_ = *std::move(response_or_error);
970
+ } else {
971
+ variant_ = Error{
972
+ HttpErrorCode::k500_InternalServerError,
973
+ absl::StrCat("server error: ", response_or_error.status().message())};
931
974
  }
975
+ return *this;
932
976
  }
933
977
 
978
+ bool ok() const { return std::holds_alternative<Response>(variant_); }
979
+
980
+ const std::variant<Response, Error>& variant() const { return variant_; }
981
+ std::variant<Response, Error>& variant() { return variant_; }
982
+
983
+ private:
984
+ using variant_type = std::variant<Response, Error>;
985
+ variant_type variant_;
986
+ };
987
+
988
+ // Raw response returned by the server.
989
+ struct RawResponse {
990
+ std::string data;
991
+ int status_code{};
992
+ std::string content_type;
993
+
934
994
  absl::StatusOr<std::string> AsStatus() && {
935
- switch (type) {
936
- case ResponseType::kOkJson:
937
- case ResponseType::kOkHtml:
938
- return std::move(data);
939
- case ResponseType::kBadRequest:
940
- case ResponseType::kServerError:
941
- return absl::UnknownError(std::move(data));
995
+ if (status_code >= 200 && status_code < 300) {
996
+ return std::move(data);
942
997
  }
998
+ return absl::UnknownError(std::move(data));
943
999
  }
944
1000
  };
945
1001
 
@@ -975,14 +1031,22 @@ class HttpHeaders {
975
1031
  absl::flat_hash_map<std::string, std::vector<std::string>> map_;
976
1032
  };
977
1033
 
1034
+ // Options for handling service requests.
1035
+ struct ServiceOptions {
1036
+ UnrecognizedValuesPolicy unrecognized_values =
1037
+ UnrecognizedValuesPolicy::kDrop;
1038
+ std::string studio_app_js_url =
1039
+ "https://cdn.jsdelivr.net/npm/skir-studio/dist/skir-studio-standalone.js";
1040
+ };
1041
+
978
1042
  // Sends RPCs to a skir service.
979
1043
  class Client {
980
1044
  public:
981
1045
  virtual ~Client() = default;
982
1046
 
983
1047
  virtual absl::StatusOr<std::string> operator()(
984
- absl::string_view request_data, const HttpHeaders& request_headers,
985
- HttpHeaders& response_headers) const = 0;
1048
+ absl::string_view request_data,
1049
+ const HttpHeaders& request_headers) const = 0;
986
1050
  };
987
1051
 
988
1052
  } // namespace service
@@ -990,6 +1054,12 @@ class Client {
990
1054
 
991
1055
  namespace skir_internal {
992
1056
 
1057
+ skir::service::RawResponse MakeOkJsonResponse(std::string data);
1058
+ skir::service::RawResponse MakeOkHtmlResponse(std::string data);
1059
+ skir::service::RawResponse MakeBadRequestResponse(std::string data);
1060
+ skir::service::RawResponse MakeServerErrorResponse(std::string data,
1061
+ int status_code);
1062
+
993
1063
  template <typename T>
994
1064
  T& get(T& input) {
995
1065
  return input;
@@ -1406,7 +1476,7 @@ struct Int64Adapter {
1406
1476
  static constexpr bool IsEnum() { return false; }
1407
1477
  };
1408
1478
 
1409
- struct Uint64Adapter {
1479
+ struct Hash64Adapter {
1410
1480
  static bool IsDefault(uint64_t input) { return !input; }
1411
1481
 
1412
1482
  template <typename Out>
@@ -1429,7 +1499,7 @@ struct Uint64Adapter {
1429
1499
  static void Parse(ByteSource& source, uint64_t& out);
1430
1500
 
1431
1501
  static skir::reflection::Type GetType(skir_type<uint64_t>) {
1432
- return skir::reflection::PrimitiveType::kUint64;
1502
+ return skir::reflection::PrimitiveType::kHash64;
1433
1503
  }
1434
1504
 
1435
1505
  static void RegisterRecords(skir_type<uint64_t>,
@@ -1603,7 +1673,7 @@ void GetAdapter(skir_type<T>) {
1603
1673
  inline BoolAdapter GetAdapter(skir_type<bool>);
1604
1674
  inline Int32Adapter GetAdapter(skir_type<int32_t>);
1605
1675
  inline Int64Adapter GetAdapter(skir_type<int64_t>);
1606
- inline Uint64Adapter GetAdapter(skir_type<uint64_t>);
1676
+ inline Hash64Adapter GetAdapter(skir_type<uint64_t>);
1607
1677
  inline Float32Adapter GetAdapter(skir_type<float>);
1608
1678
  inline Float64Adapter GetAdapter(skir_type<double>);
1609
1679
  inline TimestampAdapter GetAdapter(skir_type<absl::Time>);
@@ -2364,7 +2434,7 @@ skir::service::HttpHeaders HttplibToSkirHeaders(const HttplibHeaders& input) {
2364
2434
 
2365
2435
  template <typename MethodsTuple, std::size_t... Indices>
2366
2436
  constexpr bool unique_method_numbers_impl(std::index_sequence<Indices...>) {
2367
- constexpr std::array<int, sizeof...(Indices)> numbers = {
2437
+ constexpr std::array<int64_t, sizeof...(Indices)> numbers = {
2368
2438
  std::get<Indices>(MethodsTuple()).kNumber...};
2369
2439
  for (std::size_t i = 0; i < sizeof...(Indices); ++i) {
2370
2440
  for (std::size_t j = i + 1; j < sizeof...(Indices); ++j) {
@@ -2593,33 +2663,19 @@ struct MethodListAdapter {
2593
2663
  inline MethodDescriptorAdapter GetAdapter(skir_type<MethodDescriptor>);
2594
2664
  inline MethodListAdapter GetAdapter(skir_type<MethodList>);
2595
2665
 
2596
- constexpr absl::string_view kRestudioHtml = R"html(<!DOCTYPE html>
2597
-
2598
- <html>
2599
- <head>
2600
- <meta charset="utf-8" />
2601
- <title>RESTudio</title>
2602
- <script src="https://cdn.jsdelivr.net/npm/restudio/dist/restudio-standalone.js"></script>
2603
- </head>
2604
- <body style="margin: 0; padding: 0;">
2605
- <restudio-app></restudio-app>
2606
- </body>
2607
- </html>
2608
- )html";
2609
-
2610
- template <typename ServiceImpl, typename RequestMeta, typename ResponseMeta>
2666
+ std::string GetStudioHtml(absl::string_view studio_app_js_url);
2667
+
2668
+ template <typename ServiceImpl, typename RequestMeta>
2611
2669
  class HandleRequestOp {
2612
2670
  public:
2613
2671
  HandleRequestOp(ServiceImpl* absl_nonnull service_impl,
2614
2672
  absl::string_view request_body,
2615
- skir::UnrecognizedValuesPolicy unrecognized_values,
2616
- const RequestMeta* absl_nonnull request_meta,
2617
- ResponseMeta* absl_nonnull response_meta)
2673
+ const skir::service::ServiceOptions* absl_nonnull options,
2674
+ const RequestMeta* absl_nonnull request_meta)
2618
2675
  : service_impl_(*service_impl),
2619
2676
  request_body_(request_body),
2620
- unrecognized_values_(unrecognized_values),
2621
- request_meta_(*request_meta),
2622
- response_meta_(*response_meta) {}
2677
+ options_(*options),
2678
+ request_meta_(*request_meta) {}
2623
2679
 
2624
2680
  skir::service::RawResponse Run() {
2625
2681
  if (request_body_ == "" || request_body_ == "list") {
@@ -2631,20 +2687,16 @@ class HandleRequestOp {
2631
2687
  typename ServiceImpl::methods());
2632
2688
  ReadableJson json;
2633
2689
  MethodListAdapter::Append(method_list, json);
2634
- return {
2635
- json.out,
2636
- skir::service::ResponseType::kOkJson,
2637
- };
2638
- } else if (request_body_ == "debug" || request_body_ == "restudio") {
2639
- return {std::string(kRestudioHtml), skir::service::ResponseType::kOkHtml};
2690
+ return skir_internal::MakeOkJsonResponse(json.out);
2691
+ } else if (request_body_ == "studio") {
2692
+ return skir_internal::MakeOkHtmlResponse(
2693
+ GetStudioHtml(options_.studio_app_js_url));
2640
2694
  }
2641
2695
 
2642
2696
  if (const absl::Status status = request_body_parsed_.Parse(request_body_);
2643
2697
  !status.ok()) {
2644
- return {
2645
- absl::StrCat("bad request: ", status.message()),
2646
- skir::service::ResponseType::kBadRequest,
2647
- };
2698
+ return skir_internal::MakeBadRequestResponse(
2699
+ absl::StrCat("bad request: ", status.message()));
2648
2700
  }
2649
2701
 
2650
2702
  std::apply(
@@ -2655,19 +2707,16 @@ class HandleRequestOp {
2655
2707
  if (raw_response_.has_value()) {
2656
2708
  return std::move(*raw_response_);
2657
2709
  }
2658
- return {
2659
- absl::StrCat(
2660
- "bad request: method not found: ", request_body_parsed_.method_name,
2661
- "; number: ", request_body_parsed_.method_number.value_or(-1)),
2662
- skir::service::ResponseType::kBadRequest};
2710
+ return skir_internal::MakeBadRequestResponse(absl::StrCat(
2711
+ "bad request: method not found: ", request_body_parsed_.method_name,
2712
+ "; number: ", request_body_parsed_.method_number.value_or(-1)));
2663
2713
  }
2664
2714
 
2665
2715
  private:
2666
2716
  ServiceImpl& service_impl_;
2667
2717
  const absl::string_view request_body_;
2668
- const skir::UnrecognizedValuesPolicy unrecognized_values_;
2718
+ const skir::service::ServiceOptions& options_;
2669
2719
  const RequestMeta& request_meta_;
2670
- ResponseMeta& response_meta_;
2671
2720
 
2672
2721
  RequestBody request_body_parsed_;
2673
2722
 
@@ -2689,29 +2738,28 @@ class HandleRequestOp {
2689
2738
  // an error in this case.
2690
2739
  return;
2691
2740
  }
2692
- raw_response_.emplace();
2693
2741
  absl::StatusOr<RequestType> request = skir::Parse<RequestType>(
2694
- request_body_parsed_.request_data, unrecognized_values_);
2742
+ request_body_parsed_.request_data, options_.unrecognized_values);
2695
2743
  if (!request.ok()) {
2696
- raw_response_->data =
2697
- absl::StrCat("bad request: ", request.status().message());
2698
- raw_response_->type = skir::service::ResponseType::kBadRequest;
2744
+ raw_response_ = skir_internal::MakeBadRequestResponse(
2745
+ absl::StrCat("bad request: ", request.status().message()));
2699
2746
  return;
2700
2747
  }
2701
- absl::StatusOr<ResponseType> output = service_impl_(
2702
- method, std::move(*request), request_meta_, response_meta_);
2703
- if (!output.ok()) {
2704
- raw_response_->data =
2705
- absl::StrCat("server error: ", output.status().message());
2706
- raw_response_->type = skir::service::ResponseType::kServerError;
2748
+ skir::service::ErrorOr<ResponseType> response_or_error =
2749
+ service_impl_(method, std::move(*request), request_meta_);
2750
+ if (!response_or_error.ok()) {
2751
+ auto& error = std::get<skir::service::Error>(response_or_error.variant());
2752
+ raw_response_ = skir_internal::MakeServerErrorResponse(
2753
+ std::move(error.message), int(error.code));
2707
2754
  return;
2708
2755
  }
2756
+ const auto& response = std::get<ResponseType>(response_or_error.variant());
2709
2757
  if (request_body_parsed_.readable) {
2710
- raw_response_->data = skir::ToReadableJson(*output);
2711
- raw_response_->type = skir::service::ResponseType::kOkJson;
2758
+ raw_response_ =
2759
+ skir_internal::MakeOkJsonResponse(skir::ToReadableJson(response));
2712
2760
  } else {
2713
- raw_response_->data = skir::ToDenseJson(*output);
2714
- raw_response_->type = skir::service::ResponseType::kOkJson;
2761
+ raw_response_ =
2762
+ skir_internal::MakeOkJsonResponse(skir::ToDenseJson(response));
2715
2763
  }
2716
2764
  }
2717
2765
  };
@@ -2724,8 +2772,7 @@ class HttplibClient : public skir::service::Client {
2724
2772
 
2725
2773
  absl::StatusOr<std::string> operator()(
2726
2774
  absl::string_view request_data,
2727
- const skir::service::HttpHeaders& request_headers,
2728
- skir::service::HttpHeaders& response_headers) const {
2775
+ const skir::service::HttpHeaders& request_headers) const {
2729
2776
  auto headers =
2730
2777
  decltype(std::declval<HttplibClientPtr>()->Get("")->headers)();
2731
2778
  SkirToHttplibHeaders(request_headers, headers);
@@ -2733,7 +2780,6 @@ class HttplibClient : public skir::service::Client {
2733
2780
  client_->Post(query_path_, headers, request_data.data(),
2734
2781
  request_data.length(), "text/plain; charset=utf-8");
2735
2782
  if (result) {
2736
- response_headers = HttplibToSkirHeaders(result->headers);
2737
2783
  const int status_code = result->status;
2738
2784
  if (200 <= status_code && status_code <= 299) {
2739
2785
  // OK status.
@@ -2751,7 +2797,6 @@ class HttplibClient : public skir::service::Client {
2751
2797
  }
2752
2798
  } else {
2753
2799
  // HTTP error.
2754
- response_headers = {};
2755
2800
  std::stringstream ss;
2756
2801
  ss << "HTTP error: " << result.error();
2757
2802
  return {absl::UnknownError(ss.str())};
@@ -2775,11 +2820,15 @@ namespace service {
2775
2820
  // 1. It must have a public `methods` type alias which resolves to a tuple of
2776
2821
  // // method types.
2777
2822
  // 2. For each method, it must have a member function with this signature:
2823
+ //
2778
2824
  // absl::StatusOr<typename Method::response_type> operator()(
2779
2825
  // Method method,
2780
2826
  // typename Method::request_type request,
2781
- // const HttpHeaders& request_headers,
2782
- // HttpHeaders& response_headers);
2827
+ // const HttpHeaders& request_headers);
2828
+ //
2829
+ // Or, if you want to specify a specific HTTP status code other than 500
2830
+ // in case of an error, use ErrorOr<typename Method::response_type>
2831
+ // instead of absl::StatusOr<typename Method::response_type>.
2783
2832
  //
2784
2833
  // For example:
2785
2834
  //
@@ -2792,16 +2841,14 @@ namespace service {
2792
2841
  // absl::StatusOr<skirout_methods::ListUsersResponse> operator()(
2793
2842
  // skirout_methods::ListUsers,
2794
2843
  // skirout_methods::ListUsersRequest request,
2795
- // const HttpHeaders& request_headers,
2796
- // HttpHeaders& response_headers) const {
2844
+ // const HttpHeaders& request_headers) const {
2797
2845
  // ...
2798
2846
  // }
2799
2847
  //
2800
2848
  // absl::StatusOr<skirout_methods::GetUserResponse> operator()(
2801
2849
  // skirout_methods::GetUser,
2802
2850
  // skirout_methods::GetUserRequest request,
2803
- // const HttpHeaders& request_headers,
2804
- // HttpHeaders& response_headers) const {
2851
+ // const HttpHeaders& request_headers) const {
2805
2852
  // ...
2806
2853
  // }
2807
2854
  // };
@@ -2815,20 +2862,14 @@ namespace service {
2815
2862
  // If the request is a GET request, pass in the decoded query string as the
2816
2863
  // request's body. The query string is the part of the URL after '?', and it can
2817
2864
  // be decoded with DecodeUrlQueryString.
2818
- //
2819
- // Pass in UnrecognizedValuesPolicy::kKeep if the request is guaranteed to come
2820
- // from a trusted user.
2821
2865
  template <typename ServiceImpl>
2822
2866
  RawResponse HandleRequest(ServiceImpl& service_impl,
2823
2867
  absl::string_view request_body,
2824
2868
  const HttpHeaders& request_headers,
2825
- HttpHeaders& response_headers,
2826
- UnrecognizedValuesPolicy unrecognized_values =
2827
- UnrecognizedValuesPolicy::kDrop) {
2869
+ const ServiceOptions& options = {}) {
2828
2870
  skir_internal::assert_unique_method_numbers<typename ServiceImpl::methods>();
2829
- return skir_internal::HandleRequestOp(&service_impl, request_body,
2830
- unrecognized_values, &request_headers,
2831
- &response_headers)
2871
+ return skir_internal::HandleRequestOp(&service_impl, request_body, &options,
2872
+ &request_headers)
2832
2873
  .Run();
2833
2874
  }
2834
2875
 
@@ -2844,21 +2885,16 @@ absl::StatusOr<std::string> DecodeUrlQueryString(
2844
2885
  //
2845
2886
  // ServiceImpl must satisfy the requirements outlined in the documentation for
2846
2887
  // HandleRequest.
2847
- //
2848
- // Pass in UnrecognizedValuesPolicy::kKeep if the request is guaranteed to come
2849
- // from a trusted user.
2850
2888
  template <typename HttplibServer, typename ServiceImpl>
2851
- void InstallServiceOnHttplibServer(
2852
- HttplibServer& server, absl::string_view query_path,
2853
- std::shared_ptr<ServiceImpl> service_impl,
2854
- UnrecognizedValuesPolicy unrecognized_values =
2855
- UnrecognizedValuesPolicy::kDrop) {
2889
+ void InstallServiceOnHttplibServer(HttplibServer& server,
2890
+ absl::string_view query_path,
2891
+ std::shared_ptr<ServiceImpl> service_impl,
2892
+ const ServiceOptions& options = {}) {
2856
2893
  ABSL_CHECK_NE(service_impl, nullptr);
2857
2894
  const typename HttplibServer::Handler handler = //
2858
- [service_impl, unrecognized_values](const auto& req, auto& resp) {
2895
+ [service_impl, options](const auto& req, auto& resp) {
2859
2896
  const HttpHeaders request_headers =
2860
2897
  skir_internal::HttplibToSkirHeaders(req.headers);
2861
- HttpHeaders response_headers;
2862
2898
  absl::string_view request_body;
2863
2899
  std::string decoded_query_string;
2864
2900
  if (!req.body.empty()) {
@@ -2874,14 +2910,12 @@ void InstallServiceOnHttplibServer(
2874
2910
  DecodeUrlQueryString(query_string).value_or("");
2875
2911
  request_body = decoded_query_string;
2876
2912
  }
2877
- RawResponse raw_response =
2878
- HandleRequest(*service_impl, request_body, request_headers,
2879
- response_headers, unrecognized_values);
2880
- skir_internal::SkirToHttplibHeaders(response_headers, resp.headers);
2913
+ RawResponse raw_response = HandleRequest(*service_impl, request_body,
2914
+ request_headers, options);
2881
2915
 
2882
2916
  resp.set_content(std::move(raw_response.data),
2883
- std::string(raw_response.content_type()));
2884
- resp.status = raw_response.status_code();
2917
+ std::string(raw_response.content_type));
2918
+ resp.status = raw_response.status_code;
2885
2919
  };
2886
2920
  server.Get(std::string(query_path), handler);
2887
2921
  server.Post(std::string(query_path), handler);
@@ -2894,16 +2928,11 @@ template <typename Method>
2894
2928
  absl::StatusOr<typename Method::response_type> InvokeRemote(
2895
2929
  const Client& client, Method method,
2896
2930
  const typename Method::request_type& request,
2897
- const HttpHeaders& request_headers = {},
2898
- HttpHeaders* absl_nonnull response_headers = nullptr) {
2931
+ const HttpHeaders& request_headers = {}) {
2899
2932
  const std::string request_data = absl::StrCat(
2900
2933
  Method::kMethodName, ":", Method::kNumber, "::", ToDenseJson(request));
2901
- HttpHeaders response_headers_tmp;
2902
2934
  absl::StatusOr<std::string> response_data =
2903
- client(request_data, request_headers, response_headers_tmp);
2904
- if (response_headers != nullptr) {
2905
- *response_headers = std::move(response_headers_tmp);
2906
- }
2935
+ client(request_data, request_headers);
2907
2936
  if (!response_data.ok()) {
2908
2937
  return std::move(response_data).status();
2909
2938
  }
@@ -252,10 +252,9 @@ class ClientForTesting : public ::skir::service::Client {
252
252
 
253
253
  absl::StatusOr<std::string> operator()(
254
254
  absl::string_view request_data,
255
- const skir::service::HttpHeaders& request_headers,
256
- skir::service::HttpHeaders& response_headers) const override {
255
+ const skir::service::HttpHeaders& request_headers) const override {
257
256
  return ::skir::service::HandleRequest(api_impl_, request_data,
258
- request_headers, response_headers)
257
+ request_headers)
259
258
  .AsStatus();
260
259
  }
261
260
 
@@ -17,7 +17,7 @@ export function getEnumVariants(variants, typeSpeller) {
17
17
  }
18
18
  function makeUnknownVariant() {
19
19
  return {
20
- variantName: "?",
20
+ variantName: "UNKNOWN",
21
21
  valueType: "",
22
22
  valueTypeWithNamespace: "",
23
23
  variantNumber: 0,
@@ -74,7 +74,7 @@ function usePointer(type) {
74
74
  case "bool":
75
75
  case "int32":
76
76
  case "int64":
77
- case "uint64":
77
+ case "hash64":
78
78
  case "float32":
79
79
  case "float64":
80
80
  case "timestamp":
@@ -1 +1 @@
1
- {"version":3,"file":"enum_variant.js","sourceRoot":"","sources":["../src/enum_variant.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"enum_variant.js","sourceRoot":"","sources":["../src/enum_variant.ts"],"names":[],"mappings":"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"}
@@ -61,7 +61,7 @@ export class TypeSpeller {
61
61
  return "::int32_t";
62
62
  case "int64":
63
63
  return "::int64_t";
64
- case "uint64":
64
+ case "hash64":
65
65
  return "::uint64_t";
66
66
  case "float32":
67
67
  return "float";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skir-cc-gen",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "repository": {
@@ -39,7 +39,7 @@
39
39
  "lint:fix": "eslint src/**/*.ts --fix"
40
40
  },
41
41
  "dependencies": {
42
- "skir-internal": "^0.0.8",
42
+ "skir-internal": "^0.1.0",
43
43
  "zod": "^4.2.1"
44
44
  },
45
45
  "devDependencies": {
@@ -53,7 +53,7 @@
53
53
  "mocha": "^11.7.5",
54
54
  "prettier": "^3.2.4",
55
55
  "prettier-plugin-organize-imports": "^4.2.0",
56
- "skir": "^0.0.7",
56
+ "skir": "^1.0.11",
57
57
  "ts-node": "^10.9.2",
58
58
  "tsx": "^4.21.0",
59
59
  "typescript": "^5.2.2",
@@ -50,7 +50,7 @@ export function getEnumVariants(
50
50
 
51
51
  function makeUnknownVariant(): MutableEnumVariant {
52
52
  return {
53
- variantName: "?",
53
+ variantName: "UNKNOWN",
54
54
  valueType: "",
55
55
  valueTypeWithNamespace: "",
56
56
  variantNumber: 0,
@@ -116,7 +116,7 @@ function usePointer(type: ResolvedType): boolean {
116
116
  case "bool":
117
117
  case "int32":
118
118
  case "int64":
119
- case "uint64":
119
+ case "hash64":
120
120
  case "float32":
121
121
  case "float64":
122
122
  case "timestamp":
@@ -73,7 +73,7 @@ export class TypeSpeller {
73
73
  return "::int32_t";
74
74
  case "int64":
75
75
  return "::int64_t";
76
- case "uint64":
76
+ case "hash64":
77
77
  return "::uint64_t";
78
78
  case "float32":
79
79
  return "float";