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;
5356using IntType = int ;
5457using FloatType = double ;
5558using 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
58118template <typename ValueType>
59119struct 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.
119170struct 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);
238298template <>
239299GRAPHQLRESPONSE_EXPORT void Value::set<ScalarType>(ScalarType&& value);
240300template <>
241- GRAPHQLRESPONSE_EXPORT void Value::set<IdType>(const IdType& value);
301+ GRAPHQLRESPONSE_EXPORT void Value::set<IdType>(IdType& & value);
242302template <>
243303GRAPHQLRESPONSE_EXPORT const MapType& Value::get<MapType>() const ;
244304template <>
@@ -254,7 +314,7 @@ GRAPHQLRESPONSE_EXPORT FloatType Value::get<FloatType>() const;
254314template <>
255315GRAPHQLRESPONSE_EXPORT const ScalarType& Value::get<ScalarType>() const ;
256316template <>
257- GRAPHQLRESPONSE_EXPORT IdType Value::get<IdType>() const ;
317+ GRAPHQLRESPONSE_EXPORT const IdType& Value::get<IdType>() const ;
258318template <>
259319GRAPHQLRESPONSE_EXPORT MapType Value::release<MapType>();
260320template <>
0 commit comments