Skip to content

Commit 9afda58

Browse files
authored
Merge pull request #232 from wravery/option-base64-ids
Accept either a Base64 encoded binary or an opaque string in response::IdType
2 parents 8327c4d + 2bb815f commit 9afda58

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+885
-261
lines changed

cmake/version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4.1.1
1+
4.2.0

include/graphqlservice/GraphQLClient.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,12 @@ struct ModifiedResponse
188188
};
189189

190190
// Parse a single value of the response document.
191-
static Type parse(response::Value response);
191+
static Type parse(response::Value&& response);
192192

193193
// Peel off the none modifier. If it's included, it should always be last in the list.
194194
template <TypeModifier Modifier = TypeModifier::None, TypeModifier... Other>
195195
static typename std::enable_if_t<TypeModifier::None == Modifier && sizeof...(Other) == 0, Type>
196-
parse(response::Value response)
196+
parse(response::Value&& response)
197197
{
198198
return parse(std::move(response));
199199
}
@@ -202,7 +202,7 @@ struct ModifiedResponse
202202
template <TypeModifier Modifier, TypeModifier... Other>
203203
static typename std::enable_if_t<TypeModifier::Nullable == Modifier,
204204
std::optional<typename ResponseTraits<Type, Other...>::type>>
205-
parse(response::Value response)
205+
parse(response::Value&& response)
206206
{
207207
if (response.type() == response::Type::Null)
208208
{
@@ -217,7 +217,7 @@ struct ModifiedResponse
217217
template <TypeModifier Modifier, TypeModifier... Other>
218218
static typename std::enable_if_t<TypeModifier::List == Modifier,
219219
std::vector<typename ResponseTraits<Type, Other...>::type>>
220-
parse(response::Value response)
220+
parse(response::Value&& response)
221221
{
222222
std::vector<typename ResponseTraits<Type, Other...>::type> result;
223223

@@ -251,19 +251,19 @@ using ScalarResponse = ModifiedResponse<response::Value>;
251251
#ifdef GRAPHQL_DLLEXPORTS
252252
// Export all of the built-in converters
253253
template <>
254-
GRAPHQLCLIENT_EXPORT int ModifiedResponse<int>::parse(response::Value response);
254+
GRAPHQLCLIENT_EXPORT int ModifiedResponse<int>::parse(response::Value&& response);
255255
template <>
256-
GRAPHQLCLIENT_EXPORT double ModifiedResponse<double>::parse(response::Value response);
256+
GRAPHQLCLIENT_EXPORT double ModifiedResponse<double>::parse(response::Value&& response);
257257
template <>
258-
GRAPHQLCLIENT_EXPORT std::string ModifiedResponse<std::string>::parse(response::Value response);
258+
GRAPHQLCLIENT_EXPORT std::string ModifiedResponse<std::string>::parse(response::Value&& response);
259259
template <>
260-
GRAPHQLCLIENT_EXPORT bool ModifiedResponse<bool>::parse(response::Value response);
260+
GRAPHQLCLIENT_EXPORT bool ModifiedResponse<bool>::parse(response::Value&& response);
261261
template <>
262262
GRAPHQLCLIENT_EXPORT response::IdType ModifiedResponse<response::IdType>::parse(
263-
response::Value response);
263+
response::Value&& response);
264264
template <>
265265
GRAPHQLCLIENT_EXPORT response::Value ModifiedResponse<response::Value>::parse(
266-
response::Value response);
266+
response::Value&& response);
267267
#endif // GRAPHQL_DLLEXPORTS
268268

269269
} // namespace graphql::client

include/graphqlservice/GraphQLResponse.h

Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "graphqlservice/internal/Awaitable.h"
2222

23+
#include <cstdint>
24+
#include <initializer_list>
2325
#include <memory>
2426
#include <string>
2527
#include <string_view>
@@ -31,7 +33,7 @@ namespace graphql::response {
3133
// GraphQL responses are not technically JSON-specific, although that is probably the most common
3234
// way of representing them. These are the primitive types that may be represented in GraphQL, as
3335
// of the [October 2021 spec](https://spec.graphql.org/October2021/#sec-Serialization-Format).
34-
enum class Type : uint8_t
36+
enum class Type : std::uint8_t
3537
{
3638
Map, // JSON Object
3739
List, // JSON Array
@@ -41,6 +43,7 @@ enum class Type : uint8_t
4143
Int, // JSON Number
4244
Float, // JSON Number
4345
EnumValue, // JSON String
46+
ID, // JSON String
4447
Scalar, // JSON any type
4548
};
4649

@@ -53,13 +56,70 @@ using BooleanType = bool;
5356
using IntType = int;
5457
using FloatType = double;
5558
using ScalarType = Value;
56-
using IdType = std::vector<uint8_t>;
59+
60+
struct IdType
61+
{
62+
using ByteData = std::vector<std::uint8_t>;
63+
using OpaqueString = std::string;
64+
65+
GRAPHQLRESPONSE_EXPORT IdType(IdType&& other = IdType { ByteData {} }) noexcept;
66+
GRAPHQLRESPONSE_EXPORT IdType(const IdType& other);
67+
GRAPHQLRESPONSE_EXPORT ~IdType();
68+
69+
// Implicit ByteData constructors
70+
GRAPHQLRESPONSE_EXPORT IdType(size_t count, typename ByteData::value_type value = 0);
71+
GRAPHQLRESPONSE_EXPORT IdType(std::initializer_list<typename ByteData::value_type> values);
72+
GRAPHQLRESPONSE_EXPORT IdType(
73+
typename ByteData::const_iterator begin, typename ByteData::const_iterator end);
74+
75+
// Assignment
76+
GRAPHQLRESPONSE_EXPORT IdType& operator=(IdType&& rhs) noexcept;
77+
IdType& operator=(const IdType& rhs) = delete;
78+
79+
// Conversion
80+
GRAPHQLRESPONSE_EXPORT IdType(ByteData&& data) noexcept;
81+
GRAPHQLRESPONSE_EXPORT IdType& operator=(ByteData&& data) noexcept;
82+
83+
GRAPHQLRESPONSE_EXPORT IdType(OpaqueString&& opaque) noexcept;
84+
GRAPHQLRESPONSE_EXPORT IdType& operator=(OpaqueString&& opaque) noexcept;
85+
86+
template <typename ValueType>
87+
const ValueType& get() const;
88+
89+
template <typename ValueType>
90+
ValueType release();
91+
92+
// Comparison
93+
GRAPHQLRESPONSE_EXPORT bool operator==(const IdType& rhs) const noexcept;
94+
GRAPHQLRESPONSE_EXPORT bool operator==(const ByteData& rhs) const noexcept;
95+
GRAPHQLRESPONSE_EXPORT bool operator==(const OpaqueString& rhs) const noexcept;
96+
97+
GRAPHQLRESPONSE_EXPORT bool operator<(const IdType& rhs) const noexcept;
98+
99+
// Check the Type
100+
GRAPHQLRESPONSE_EXPORT bool isBase64() const noexcept;
101+
102+
private:
103+
std::variant<ByteData, OpaqueString> _data;
104+
};
105+
106+
#ifdef GRAPHQL_DLLEXPORTS
107+
// Export all of the specialized template methods
108+
template <>
109+
GRAPHQLRESPONSE_EXPORT const IdType::ByteData& IdType::get<IdType::ByteData>() const;
110+
template <>
111+
GRAPHQLRESPONSE_EXPORT const IdType::OpaqueString& IdType::get<IdType::OpaqueString>() const;
112+
template <>
113+
GRAPHQLRESPONSE_EXPORT IdType::ByteData IdType::release<IdType::ByteData>();
114+
template <>
115+
GRAPHQLRESPONSE_EXPORT IdType::OpaqueString IdType::release<IdType::OpaqueString>();
116+
#endif // GRAPHQL_DLLEXPORTS
57117

58118
template <typename ValueType>
59119
struct ValueTypeTraits
60120
{
61-
// Set by r-value reference, get by const reference, and release by value. The only types
62-
// that actually support all 3 methods are StringType and ScalarType, everything else
121+
// Set by r-value reference, get by const reference, and release by value. The only types that
122+
// actually support all 3 methods are StringType, IdType, and ScalarType, everything else
63123
// overrides some subset of these types with a template specialization.
64124
using set_type = ValueType&&;
65125
using get_type = const ValueType&;
@@ -106,15 +166,6 @@ struct ValueTypeTraits<FloatType>
106166
using get_type = FloatType;
107167
};
108168

109-
template <>
110-
struct ValueTypeTraits<IdType>
111-
{
112-
// ID values are represented as a Base64 String, so they require conversion.
113-
using set_type = const IdType&;
114-
using get_type = IdType;
115-
using release_type = IdType;
116-
};
117-
118169
// Represent a discriminated union of GraphQL response value types.
119170
struct Value
120171
{
@@ -126,7 +177,7 @@ struct Value
126177
GRAPHQLRESPONSE_EXPORT explicit Value(BooleanType value);
127178
GRAPHQLRESPONSE_EXPORT explicit Value(IntType value);
128179
GRAPHQLRESPONSE_EXPORT explicit Value(FloatType value);
129-
GRAPHQLRESPONSE_EXPORT explicit Value(const IdType& value);
180+
GRAPHQLRESPONSE_EXPORT explicit Value(IdType&& value);
130181

131182
GRAPHQLRESPONSE_EXPORT Value(Value&& other) noexcept;
132183
GRAPHQLRESPONSE_EXPORT explicit Value(const Value& other);
@@ -138,16 +189,22 @@ struct Value
138189

139190
// Comparison
140191
GRAPHQLRESPONSE_EXPORT bool operator==(const Value& rhs) const noexcept;
141-
GRAPHQLRESPONSE_EXPORT bool operator!=(const Value& rhs) const noexcept;
142192

143193
// Check the Type
144194
GRAPHQLRESPONSE_EXPORT Type type() const noexcept;
145195

146-
// JSON doesn't distinguish between Type::String and Type::EnumValue, so if this value comes
147-
// from JSON and it's a string we need to track the fact that it can be interpreted as either.
196+
// JSON doesn't distinguish between Type::String, Type::EnumValue, and Type::ID, so if this
197+
// value comes from JSON and it's a string we need to track the fact that it can be interpreted
198+
// as any of those types.
148199
GRAPHQLRESPONSE_EXPORT Value&& from_json() noexcept;
149200
GRAPHQLRESPONSE_EXPORT bool maybe_enum() const noexcept;
150201

202+
// Input values don't distinguish between Type::String and Type::ID, so if this value comes from
203+
// a string literal input value we need to track that fact that it can be interpreted as either
204+
// of those types.
205+
GRAPHQLRESPONSE_EXPORT Value&& from_input() noexcept;
206+
GRAPHQLRESPONSE_EXPORT bool maybe_id() const noexcept;
207+
151208
// Valid for Type::Map or Type::List
152209
GRAPHQLRESPONSE_EXPORT void reserve(size_t count);
153210
GRAPHQLRESPONSE_EXPORT size_t size() const;
@@ -196,6 +253,7 @@ struct Value
196253

197254
StringType string;
198255
bool from_json = false;
256+
bool from_input = false;
199257
};
200258

201259
// Type::Null
@@ -218,10 +276,12 @@ struct Value
218276
using SharedData = std::shared_ptr<const Value>;
219277

220278
using TypeData = std::variant<MapData, ListType, StringData, NullData, BooleanType, IntType,
221-
FloatType, EnumData, ScalarData, SharedData>;
279+
FloatType, EnumData, IdType, ScalarData, SharedData>;
222280

223281
const TypeData& data() const noexcept;
224282

283+
static Type typeOf(const TypeData& data) noexcept;
284+
225285
TypeData _data;
226286
};
227287

@@ -238,7 +298,7 @@ GRAPHQLRESPONSE_EXPORT void Value::set<FloatType>(FloatType value);
238298
template <>
239299
GRAPHQLRESPONSE_EXPORT void Value::set<ScalarType>(ScalarType&& value);
240300
template <>
241-
GRAPHQLRESPONSE_EXPORT void Value::set<IdType>(const IdType& value);
301+
GRAPHQLRESPONSE_EXPORT void Value::set<IdType>(IdType&& value);
242302
template <>
243303
GRAPHQLRESPONSE_EXPORT const MapType& Value::get<MapType>() const;
244304
template <>
@@ -254,7 +314,7 @@ GRAPHQLRESPONSE_EXPORT FloatType Value::get<FloatType>() const;
254314
template <>
255315
GRAPHQLRESPONSE_EXPORT const ScalarType& Value::get<ScalarType>() const;
256316
template <>
257-
GRAPHQLRESPONSE_EXPORT IdType Value::get<IdType>() const;
317+
GRAPHQLRESPONSE_EXPORT const IdType& Value::get<IdType>() const;
258318
template <>
259319
GRAPHQLRESPONSE_EXPORT MapType Value::release<MapType>();
260320
template <>

include/graphqlservice/internal/Base64.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ class Base64
5656
// Convert a set of bytes to Base64.
5757
GRAPHQLRESPONSE_EXPORT static std::string toBase64(const std::vector<std::uint8_t>& bytes);
5858

59+
enum class Comparison
60+
{
61+
LessThan = -1,
62+
EqualTo = 0,
63+
GreaterThan = 1,
64+
65+
InvalidBase64 = 2,
66+
};
67+
68+
// Compare a set of bytes to a possible Base64 string without performing any heap allocations.
69+
GRAPHQLRESPONSE_EXPORT static Comparison compareBase64(
70+
const std::vector<std::uint8_t>& bytes, std::string_view maybeEncoded) noexcept;
71+
72+
// Validate whether or not a string is valid Base64 without performing any heap allocations.
73+
GRAPHQLRESPONSE_EXPORT static bool validateBase64(std::string_view maybeEncoded) noexcept;
74+
5975
private:
6076
static constexpr char padding = '=';
6177

include/graphqlservice/internal/Version.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
namespace graphql::internal {
1212

13-
constexpr std::string_view FullVersion { "4.1.1" };
13+
constexpr std::string_view FullVersion { "4.2.0" };
1414

1515
constexpr size_t MajorVersion = 4;
16-
constexpr size_t MinorVersion = 1;
17-
constexpr size_t PatchVersion = 1;
16+
constexpr size_t MinorVersion = 2;
17+
constexpr size_t PatchVersion = 0;
1818

1919
} // namespace graphql::internal
2020

include/graphqlservice/introspection/IntrospectionSchema.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
#include "graphqlservice/internal/Schema.h"
1212

13-
// Check if the library version is compatible with schemagen 4.1.0
13+
// Check if the library version is compatible with schemagen 4.2.0
1414
static_assert(graphql::internal::MajorVersion == 4, "regenerate with schemagen: major version mismatch");
15-
static_assert(graphql::internal::MinorVersion == 1, "regenerate with schemagen: minor version mismatch");
15+
static_assert(graphql::internal::MinorVersion == 2, "regenerate with schemagen: minor version mismatch");
1616

1717
#include <memory>
1818
#include <string>

res/ClientGen.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#include <winver.h>
55

6-
#define GRAPHQL_RC_VERSION 4,1,1,0
7-
#define GRAPHQL_RC_VERSION_STR "4.1.1"
6+
#define GRAPHQL_RC_VERSION 4,2,0,0
7+
#define GRAPHQL_RC_VERSION_STR "4.2.0"
88

99
#ifndef DEBUG
1010
#define VER_DEBUG 0

res/SchemaGen.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#include <winver.h>
55

6-
#define GRAPHQL_RC_VERSION 4,1,1,0
7-
#define GRAPHQL_RC_VERSION_STR "4.1.1"
6+
#define GRAPHQL_RC_VERSION 4,2,0,0
7+
#define GRAPHQL_RC_VERSION_STR "4.2.0"
88

99
#ifndef DEBUG
1010
#define VER_DEBUG 0

res/graphqlclient_version.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#include <winver.h>
55

6-
#define GRAPHQL_RC_VERSION 4,1,1,0
7-
#define GRAPHQL_RC_VERSION_STR "4.1.1"
6+
#define GRAPHQL_RC_VERSION 4,2,0,0
7+
#define GRAPHQL_RC_VERSION_STR "4.2.0"
88

99
#ifndef DEBUG
1010
#define VER_DEBUG 0

res/graphqljson_version.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#include <winver.h>
55

6-
#define GRAPHQL_RC_VERSION 4,1,1,0
7-
#define GRAPHQL_RC_VERSION_STR "4.1.1"
6+
#define GRAPHQL_RC_VERSION 4,2,0,0
7+
#define GRAPHQL_RC_VERSION_STR "4.2.0"
88

99
#ifndef DEBUG
1010
#define VER_DEBUG 0

res/graphqlpeg_version.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#include <winver.h>
55

6-
#define GRAPHQL_RC_VERSION 4,1,1,0
7-
#define GRAPHQL_RC_VERSION_STR "4.1.1"
6+
#define GRAPHQL_RC_VERSION 4,2,0,0
7+
#define GRAPHQL_RC_VERSION_STR "4.2.0"
88

99
#ifndef DEBUG
1010
#define VER_DEBUG 0

res/graphqlresponse_version.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#include <winver.h>
55

6-
#define GRAPHQL_RC_VERSION 4,1,1,0
7-
#define GRAPHQL_RC_VERSION_STR "4.1.1"
6+
#define GRAPHQL_RC_VERSION 4,2,0,0
7+
#define GRAPHQL_RC_VERSION_STR "4.2.0"
88

99
#ifndef DEBUG
1010
#define VER_DEBUG 0

res/graphqlservice_version.rc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#include <winver.h>
55

6-
#define GRAPHQL_RC_VERSION 4,1,1,0
7-
#define GRAPHQL_RC_VERSION_STR "4.1.1"
6+
#define GRAPHQL_RC_VERSION 4,2,0,0
7+
#define GRAPHQL_RC_VERSION_STR "4.2.0"
88

99
#ifndef DEBUG
1010
#define VER_DEBUG 0

0 commit comments

Comments
 (0)