annotate osx/include/capnp/compat/json.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 0994c39f1e94
children
rev   line source
cannam@62 1 // Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
cannam@62 2 // Licensed under the MIT License:
cannam@62 3 //
cannam@62 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@62 5 // of this software and associated documentation files (the "Software"), to deal
cannam@62 6 // in the Software without restriction, including without limitation the rights
cannam@62 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@62 8 // copies of the Software, and to permit persons to whom the Software is
cannam@62 9 // furnished to do so, subject to the following conditions:
cannam@62 10 //
cannam@62 11 // The above copyright notice and this permission notice shall be included in
cannam@62 12 // all copies or substantial portions of the Software.
cannam@62 13 //
cannam@62 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@62 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@62 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@62 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@62 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@62 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@62 20 // THE SOFTWARE.
cannam@62 21
cannam@62 22 #ifndef CAPNP_COMPAT_JSON_H_
cannam@62 23 #define CAPNP_COMPAT_JSON_H_
cannam@62 24
cannam@62 25 #include <capnp/schema.h>
cannam@62 26 #include <capnp/dynamic.h>
cannam@62 27 #include <capnp/compat/json.capnp.h>
cannam@62 28
cannam@62 29 namespace capnp {
cannam@62 30
cannam@62 31 class JsonCodec {
cannam@62 32 // Flexible class for encoding Cap'n Proto types as JSON, and decoding JSON back to Cap'n Proto.
cannam@62 33 //
cannam@62 34 // Typical usage:
cannam@62 35 //
cannam@62 36 // JsonCodec json;
cannam@62 37 //
cannam@62 38 // // encode
cannam@62 39 // kj::String encoded = json.encode(someStructReader);
cannam@62 40 //
cannam@62 41 // // decode
cannam@62 42 // json.decode(encoded, someStructBuilder);
cannam@62 43 //
cannam@62 44 // Advanced users can do fancy things like override the way certain types or fields are
cannam@62 45 // represented in JSON by registering handlers. See the unit test for an example.
cannam@62 46 //
cannam@62 47 // Notes:
cannam@62 48 // - When encoding, all primitive fields are always encoded, even if default-valued. Pointer
cannam@62 49 // fields are only encoded if they are non-null.
cannam@62 50 // - 64-bit integers are encoded as strings, since JSON "numbers" are double-precision floating
cannam@62 51 // points which cannot store a 64-bit integer without losing data.
cannam@62 52 // - NaNs and infinite floating point numbers are not allowed by the JSON spec, and so are encoded
cannam@62 53 // as null. This matches the behavior of `JSON.stringify` in at least Firefox and Chrome.
cannam@62 54 // - Data is encoded as an array of numbers in the range [0,255]. You probably want to register
cannam@62 55 // a handler that does something better, like maybe base64 encoding, but there are a zillion
cannam@62 56 // different ways people do this.
cannam@62 57 // - Encoding/decoding capabilities and AnyPointers requires registering a Handler, since there's
cannam@62 58 // no obvious default behavior.
cannam@62 59 // - When decoding, unrecognized field names are ignored. Note: This means that JSON is NOT a
cannam@62 60 // good format for receiving input from a human. Consider `capnp eval` or the SchemaParser
cannam@62 61 // library for human input.
cannam@62 62
cannam@62 63 public:
cannam@62 64 JsonCodec();
cannam@62 65 ~JsonCodec() noexcept(false);
cannam@62 66
cannam@62 67 // ---------------------------------------------------------------------------
cannam@62 68 // standard API
cannam@62 69
cannam@62 70 void setPrettyPrint(bool enabled);
cannam@62 71 // Enable to insert newlines, indentation, and other extra spacing into the output. The default
cannam@62 72 // is to use minimal whitespace.
cannam@62 73
cannam@62 74 void setMaxNestingDepth(size_t maxNestingDepth);
cannam@62 75 // Set maximum nesting depth when decoding JSON to prevent highly nested input from overflowing
cannam@62 76 // the call stack. The default is 64.
cannam@62 77
cannam@62 78 template <typename T>
cannam@62 79 kj::String encode(T&& value);
cannam@62 80 // Encode any Cap'n Proto value to JSON, including primitives and
cannam@62 81 // Dynamic{Enum,Struct,List,Capability}, but not DynamicValue (see below).
cannam@62 82
cannam@62 83 kj::String encode(DynamicValue::Reader value, Type type) const;
cannam@62 84 // Encode a DynamicValue to JSON. `type` is needed because `DynamicValue` itself does
cannam@62 85 // not distinguish between e.g. int32 and int64, which in JSON are handled differently. Most
cannam@62 86 // of the time, though, you can use the single-argument templated version of `encode()` instead.
cannam@62 87
cannam@62 88 void decode(kj::ArrayPtr<const char> input, DynamicStruct::Builder output) const;
cannam@62 89 // Decode JSON text directly into a struct builder. This only works for structs since lists
cannam@62 90 // need to be allocated with the correct size in advance.
cannam@62 91 //
cannam@62 92 // (Remember that any Cap'n Proto struct reader type can be implicitly cast to
cannam@62 93 // DynamicStruct::Reader.)
cannam@62 94
cannam@62 95 template <typename T>
cannam@62 96 Orphan<T> decode(kj::ArrayPtr<const char> input, Orphanage orphanage) const;
cannam@62 97 // Decode JSON text to any Cap'n Proto object (pointer value), allocated using the given
cannam@62 98 // orphanage. T must be specified explicitly and cannot be dynamic, e.g.:
cannam@62 99 //
cannam@62 100 // Orphan<MyType> orphan = json.decode<MyType>(text, orphanage);
cannam@62 101
cannam@62 102 template <typename T>
cannam@62 103 ReaderFor<T> decode(kj::ArrayPtr<const char> input) const;
cannam@62 104 // Decode JSON text into a primitive or capability value. T must be specified explicitly and
cannam@62 105 // cannot be dynamic, e.g.:
cannam@62 106 //
cannam@62 107 // uint32_t n = json.decode<uint32_t>(text);
cannam@62 108
cannam@62 109 Orphan<DynamicValue> decode(kj::ArrayPtr<const char> input, Type type, Orphanage orphanage) const;
cannam@62 110 Orphan<DynamicList> decode(
cannam@62 111 kj::ArrayPtr<const char> input, ListSchema type, Orphanage orphanage) const;
cannam@62 112 Orphan<DynamicStruct> decode(
cannam@62 113 kj::ArrayPtr<const char> input, StructSchema type, Orphanage orphanage) const;
cannam@62 114 DynamicCapability::Client decode(kj::ArrayPtr<const char> input, InterfaceSchema type) const;
cannam@62 115 DynamicEnum decode(kj::ArrayPtr<const char> input, EnumSchema type) const;
cannam@62 116 // Decode to a dynamic value, specifying the type schema.
cannam@62 117
cannam@62 118 // ---------------------------------------------------------------------------
cannam@62 119 // layered API
cannam@62 120 //
cannam@62 121 // You can separate text <-> JsonValue from JsonValue <-> T. These are particularly useful
cannam@62 122 // for calling from Handler implementations.
cannam@62 123
cannam@62 124 kj::String encodeRaw(JsonValue::Reader value) const;
cannam@62 125 void decodeRaw(kj::ArrayPtr<const char> input, JsonValue::Builder output) const;
cannam@62 126 // Translate JsonValue <-> text.
cannam@62 127
cannam@62 128 template <typename T>
cannam@62 129 void encode(T&& value, JsonValue::Builder output);
cannam@62 130 void encode(DynamicValue::Reader input, Type type, JsonValue::Builder output) const;
cannam@62 131 void decode(JsonValue::Reader input, DynamicStruct::Builder output) const;
cannam@62 132 template <typename T>
cannam@62 133 Orphan<T> decode(JsonValue::Reader input, Orphanage orphanage) const;
cannam@62 134 template <typename T>
cannam@62 135 ReaderFor<T> decode(JsonValue::Reader input) const;
cannam@62 136
cannam@62 137 Orphan<DynamicValue> decode(JsonValue::Reader input, Type type, Orphanage orphanage) const;
cannam@62 138 Orphan<DynamicList> decode(JsonValue::Reader input, ListSchema type, Orphanage orphanage) const;
cannam@62 139 Orphan<DynamicStruct> decode(
cannam@62 140 JsonValue::Reader input, StructSchema type, Orphanage orphanage) const;
cannam@62 141 DynamicCapability::Client decode(JsonValue::Reader input, InterfaceSchema type) const;
cannam@62 142 DynamicEnum decode(JsonValue::Reader input, EnumSchema type) const;
cannam@62 143
cannam@62 144 // ---------------------------------------------------------------------------
cannam@62 145 // specializing particular types
cannam@62 146
cannam@62 147 template <typename T, Style s = style<T>()>
cannam@62 148 class Handler;
cannam@62 149 // Implement this interface to specify a special encoding for a particular type or field.
cannam@62 150 //
cannam@62 151 // The templates are a bit ugly, but subclasses of this type essentially implement two methods,
cannam@62 152 // one to encode values of this type and one to decode values of this type. `encode()` is simple:
cannam@62 153 //
cannam@62 154 // void encode(const JsonCodec& codec, ReaderFor<T> input, JsonValue::Builder output) const;
cannam@62 155 //
cannam@62 156 // `decode()` is a bit trickier. When T is a struct (including DynamicStruct), it is:
cannam@62 157 //
cannam@62 158 // void decode(const JsonCodec& codec, JsonValue::Reader input, BuilderFor<T> output) const;
cannam@62 159 //
cannam@62 160 // However, when T is a primitive, decode() is:
cannam@62 161 //
cannam@62 162 // T decode(const JsonCodec& codec, JsonValue::Reader input) const;
cannam@62 163 //
cannam@62 164 // Or when T is any non-struct object (list, blob), decode() is:
cannam@62 165 //
cannam@62 166 // Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const;
cannam@62 167 //
cannam@62 168 // Or when T is an interface:
cannam@62 169 //
cannam@62 170 // T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const;
cannam@62 171 //
cannam@62 172 // Additionally, when T is a struct you can *optionally* also implement the orphan-returning form
cannam@62 173 // of decode(), but it will only be called when the struct would be allocated as an individual
cannam@62 174 // object, not as part of a list. This allows you to return "nullptr" in these cases to say that
cannam@62 175 // the pointer value should be null. This does not apply to list elements because struct list
cannam@62 176 // elements cannot ever be null (since Cap'n Proto encodes struct lists as a flat list rather
cannam@62 177 // than list-of-pointers).
cannam@62 178
cannam@62 179 template <typename T>
cannam@62 180 void addTypeHandler(Handler<T>& handler);
cannam@62 181 void addTypeHandler(Type type, Handler<DynamicValue>& handler);
cannam@62 182 void addTypeHandler(EnumSchema type, Handler<DynamicEnum>& handler);
cannam@62 183 void addTypeHandler(StructSchema type, Handler<DynamicStruct>& handler);
cannam@62 184 void addTypeHandler(ListSchema type, Handler<DynamicList>& handler);
cannam@62 185 void addTypeHandler(InterfaceSchema type, Handler<DynamicCapability>& handler);
cannam@62 186 // Arrange that whenever the type T appears in the message, your handler will be used to
cannam@62 187 // encode/decode it.
cannam@62 188 //
cannam@62 189 // Note that if you register a handler for a capability type, it will also apply to subtypes.
cannam@62 190 // Thus Handler<Capability> handles all capabilities.
cannam@62 191
cannam@62 192 template <typename T>
cannam@62 193 void addFieldHandler(StructSchema::Field field, Handler<T>& handler);
cannam@62 194 // Matches only the specific field. T can be a dynamic type. T must match the field's type.
cannam@62 195
cannam@62 196 private:
cannam@62 197 class HandlerBase;
cannam@62 198 struct Impl;
cannam@62 199
cannam@62 200 kj::Own<Impl> impl;
cannam@62 201
cannam@62 202 void encodeField(StructSchema::Field field, DynamicValue::Reader input,
cannam@62 203 JsonValue::Builder output) const;
cannam@62 204 void decodeArray(List<JsonValue>::Reader input, DynamicList::Builder output) const;
cannam@62 205 void decodeObject(List<JsonValue::Field>::Reader input, DynamicStruct::Builder output) const;
cannam@62 206 void addTypeHandlerImpl(Type type, HandlerBase& handler);
cannam@62 207 void addFieldHandlerImpl(StructSchema::Field field, Type type, HandlerBase& handler);
cannam@62 208 };
cannam@62 209
cannam@62 210 // =======================================================================================
cannam@62 211 // inline implementation details
cannam@62 212
cannam@62 213 template <typename T>
cannam@62 214 kj::String JsonCodec::encode(T&& value) {
cannam@62 215 typedef FromAny<kj::Decay<T>> Base;
cannam@62 216 return encode(DynamicValue::Reader(ReaderFor<Base>(kj::fwd<T>(value))), Type::from<Base>());
cannam@62 217 }
cannam@62 218
cannam@62 219 template <typename T>
cannam@62 220 inline Orphan<T> JsonCodec::decode(kj::ArrayPtr<const char> input, Orphanage orphanage) const {
cannam@62 221 return decode(input, Type::from<T>(), orphanage).template releaseAs<T>();
cannam@62 222 }
cannam@62 223
cannam@62 224 template <typename T>
cannam@62 225 inline ReaderFor<T> JsonCodec::decode(kj::ArrayPtr<const char> input) const {
cannam@62 226 static_assert(style<T>() == Style::PRIMITIVE || style<T>() == Style::CAPABILITY,
cannam@62 227 "must specify an orphanage to decode an object type");
cannam@62 228 return decode(input, Type::from<T>(), Orphanage()).getReader().template as<T>();
cannam@62 229 }
cannam@62 230
cannam@62 231 inline Orphan<DynamicList> JsonCodec::decode(
cannam@62 232 kj::ArrayPtr<const char> input, ListSchema type, Orphanage orphanage) const {
cannam@62 233 return decode(input, Type(type), orphanage).releaseAs<DynamicList>();
cannam@62 234 }
cannam@62 235 inline Orphan<DynamicStruct> JsonCodec::decode(
cannam@62 236 kj::ArrayPtr<const char> input, StructSchema type, Orphanage orphanage) const {
cannam@62 237 return decode(input, Type(type), orphanage).releaseAs<DynamicStruct>();
cannam@62 238 }
cannam@62 239 inline DynamicCapability::Client JsonCodec::decode(
cannam@62 240 kj::ArrayPtr<const char> input, InterfaceSchema type) const {
cannam@62 241 return decode(input, Type(type), Orphanage()).getReader().as<DynamicCapability>();
cannam@62 242 }
cannam@62 243 inline DynamicEnum JsonCodec::decode(kj::ArrayPtr<const char> input, EnumSchema type) const {
cannam@62 244 return decode(input, Type(type), Orphanage()).getReader().as<DynamicEnum>();
cannam@62 245 }
cannam@62 246
cannam@62 247 // -----------------------------------------------------------------------------
cannam@62 248
cannam@62 249 template <typename T>
cannam@62 250 void JsonCodec::encode(T&& value, JsonValue::Builder output) {
cannam@62 251 typedef FromAny<kj::Decay<T>> Base;
cannam@62 252 encode(DynamicValue::Reader(ReaderFor<Base>(kj::fwd<T>(value))), Type::from<Base>(), output);
cannam@62 253 }
cannam@62 254
cannam@62 255 template <typename T>
cannam@62 256 inline Orphan<T> JsonCodec::decode(JsonValue::Reader input, Orphanage orphanage) const {
cannam@62 257 return decode(input, Type::from<T>(), orphanage).template releaseAs<T>();
cannam@62 258 }
cannam@62 259
cannam@62 260 template <typename T>
cannam@62 261 inline ReaderFor<T> JsonCodec::decode(JsonValue::Reader input) const {
cannam@62 262 static_assert(style<T>() == Style::PRIMITIVE || style<T>() == Style::CAPABILITY,
cannam@62 263 "must specify an orphanage to decode an object type");
cannam@62 264 return decode(input, Type::from<T>(), Orphanage()).getReader().template as<T>();
cannam@62 265 }
cannam@62 266
cannam@62 267 inline Orphan<DynamicList> JsonCodec::decode(
cannam@62 268 JsonValue::Reader input, ListSchema type, Orphanage orphanage) const {
cannam@62 269 return decode(input, Type(type), orphanage).releaseAs<DynamicList>();
cannam@62 270 }
cannam@62 271 inline Orphan<DynamicStruct> JsonCodec::decode(
cannam@62 272 JsonValue::Reader input, StructSchema type, Orphanage orphanage) const {
cannam@62 273 return decode(input, Type(type), orphanage).releaseAs<DynamicStruct>();
cannam@62 274 }
cannam@62 275 inline DynamicCapability::Client JsonCodec::decode(
cannam@62 276 JsonValue::Reader input, InterfaceSchema type) const {
cannam@62 277 return decode(input, Type(type), Orphanage()).getReader().as<DynamicCapability>();
cannam@62 278 }
cannam@62 279 inline DynamicEnum JsonCodec::decode(JsonValue::Reader input, EnumSchema type) const {
cannam@62 280 return decode(input, Type(type), Orphanage()).getReader().as<DynamicEnum>();
cannam@62 281 }
cannam@62 282
cannam@62 283 // -----------------------------------------------------------------------------
cannam@62 284
cannam@62 285 class JsonCodec::HandlerBase {
cannam@62 286 // Internal helper; ignore.
cannam@62 287 public:
cannam@62 288 virtual void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
cannam@62 289 JsonValue::Builder output) const = 0;
cannam@62 290 virtual Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 291 Type type, Orphanage orphanage) const;
cannam@62 292 virtual void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 293 DynamicStruct::Builder output) const;
cannam@62 294 };
cannam@62 295
cannam@62 296 template <typename T>
cannam@62 297 class JsonCodec::Handler<T, Style::POINTER>: private JsonCodec::HandlerBase {
cannam@62 298 public:
cannam@62 299 virtual void encode(const JsonCodec& codec, ReaderFor<T> input,
cannam@62 300 JsonValue::Builder output) const = 0;
cannam@62 301 virtual Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 302 Orphanage orphanage) const = 0;
cannam@62 303
cannam@62 304 private:
cannam@62 305 void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
cannam@62 306 JsonValue::Builder output) const override final {
cannam@62 307 encode(codec, input.as<T>(), output);
cannam@62 308 }
cannam@62 309 Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 310 Type type, Orphanage orphanage) const override final {
cannam@62 311 return decode(codec, input, orphanage);
cannam@62 312 }
cannam@62 313 friend class JsonCodec;
cannam@62 314 };
cannam@62 315
cannam@62 316 template <typename T>
cannam@62 317 class JsonCodec::Handler<T, Style::STRUCT>: private JsonCodec::HandlerBase {
cannam@62 318 public:
cannam@62 319 virtual void encode(const JsonCodec& codec, ReaderFor<T> input,
cannam@62 320 JsonValue::Builder output) const = 0;
cannam@62 321 virtual void decode(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 322 BuilderFor<T> output) const = 0;
cannam@62 323 virtual Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 324 Orphanage orphanage) const {
cannam@62 325 // If subclass does not override, fall back to regular version.
cannam@62 326 auto result = orphanage.newOrphan<T>();
cannam@62 327 decode(codec, input, result.get());
cannam@62 328 return result;
cannam@62 329 }
cannam@62 330
cannam@62 331 private:
cannam@62 332 void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
cannam@62 333 JsonValue::Builder output) const override final {
cannam@62 334 encode(codec, input.as<T>(), output);
cannam@62 335 }
cannam@62 336 Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 337 Type type, Orphanage orphanage) const override final {
cannam@62 338 return decode(codec, input, orphanage);
cannam@62 339 }
cannam@62 340 void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 341 DynamicStruct::Builder output) const override final {
cannam@62 342 decode(codec, input, output.as<T>());
cannam@62 343 }
cannam@62 344 friend class JsonCodec;
cannam@62 345 };
cannam@62 346
cannam@62 347 template <>
cannam@62 348 class JsonCodec::Handler<DynamicStruct>: private JsonCodec::HandlerBase {
cannam@62 349 // Almost identical to Style::STRUCT except that we pass the struct type to decode().
cannam@62 350
cannam@62 351 public:
cannam@62 352 virtual void encode(const JsonCodec& codec, DynamicStruct::Reader input,
cannam@62 353 JsonValue::Builder output) const = 0;
cannam@62 354 virtual void decode(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 355 DynamicStruct::Builder output) const = 0;
cannam@62 356 virtual Orphan<DynamicStruct> decode(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 357 StructSchema type, Orphanage orphanage) const {
cannam@62 358 // If subclass does not override, fall back to regular version.
cannam@62 359 auto result = orphanage.newOrphan(type);
cannam@62 360 decode(codec, input, result.get());
cannam@62 361 return result;
cannam@62 362 }
cannam@62 363
cannam@62 364 private:
cannam@62 365 void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
cannam@62 366 JsonValue::Builder output) const override final {
cannam@62 367 encode(codec, input.as<DynamicStruct>(), output);
cannam@62 368 }
cannam@62 369 Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 370 Type type, Orphanage orphanage) const override final {
cannam@62 371 return decode(codec, input, type.asStruct(), orphanage);
cannam@62 372 }
cannam@62 373 void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 374 DynamicStruct::Builder output) const override final {
cannam@62 375 decode(codec, input, output.as<DynamicStruct>());
cannam@62 376 }
cannam@62 377 friend class JsonCodec;
cannam@62 378 };
cannam@62 379
cannam@62 380 template <typename T>
cannam@62 381 class JsonCodec::Handler<T, Style::PRIMITIVE>: private JsonCodec::HandlerBase {
cannam@62 382 public:
cannam@62 383 virtual void encode(const JsonCodec& codec, T input, JsonValue::Builder output) const = 0;
cannam@62 384 virtual T decode(const JsonCodec& codec, JsonValue::Reader input) const = 0;
cannam@62 385
cannam@62 386 private:
cannam@62 387 void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
cannam@62 388 JsonValue::Builder output) const override final {
cannam@62 389 encode(codec, input.as<T>(), output);
cannam@62 390 }
cannam@62 391 Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 392 Type type, Orphanage orphanage) const override final {
cannam@62 393 return decode(codec, input);
cannam@62 394 }
cannam@62 395 friend class JsonCodec;
cannam@62 396 };
cannam@62 397
cannam@62 398 template <typename T>
cannam@62 399 class JsonCodec::Handler<T, Style::CAPABILITY>: private JsonCodec::HandlerBase {
cannam@62 400 public:
cannam@62 401 virtual void encode(const JsonCodec& codec, typename T::Client input,
cannam@62 402 JsonValue::Builder output) const = 0;
cannam@62 403 virtual typename T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const = 0;
cannam@62 404
cannam@62 405 private:
cannam@62 406 void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
cannam@62 407 JsonValue::Builder output) const override final {
cannam@62 408 encode(codec, input.as<T>(), output);
cannam@62 409 }
cannam@62 410 Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
cannam@62 411 Type type, Orphanage orphanage) const override final {
cannam@62 412 return orphanage.newOrphanCopy(decode(codec, input));
cannam@62 413 }
cannam@62 414 friend class JsonCodec;
cannam@62 415 };
cannam@62 416
cannam@62 417 template <typename T>
cannam@62 418 inline void JsonCodec::addTypeHandler(Handler<T>& handler) {
cannam@62 419 addTypeHandlerImpl(Type::from<T>(), handler);
cannam@62 420 }
cannam@62 421 inline void JsonCodec::addTypeHandler(Type type, Handler<DynamicValue>& handler) {
cannam@62 422 addTypeHandlerImpl(type, handler);
cannam@62 423 }
cannam@62 424 inline void JsonCodec::addTypeHandler(EnumSchema type, Handler<DynamicEnum>& handler) {
cannam@62 425 addTypeHandlerImpl(type, handler);
cannam@62 426 }
cannam@62 427 inline void JsonCodec::addTypeHandler(StructSchema type, Handler<DynamicStruct>& handler) {
cannam@62 428 addTypeHandlerImpl(type, handler);
cannam@62 429 }
cannam@62 430 inline void JsonCodec::addTypeHandler(ListSchema type, Handler<DynamicList>& handler) {
cannam@62 431 addTypeHandlerImpl(type, handler);
cannam@62 432 }
cannam@62 433 inline void JsonCodec::addTypeHandler(InterfaceSchema type, Handler<DynamicCapability>& handler) {
cannam@62 434 addTypeHandlerImpl(type, handler);
cannam@62 435 }
cannam@62 436
cannam@62 437 template <typename T>
cannam@62 438 inline void JsonCodec::addFieldHandler(StructSchema::Field field, Handler<T>& handler) {
cannam@62 439 addFieldHandlerImpl(field, Type::from<T>(), handler);
cannam@62 440 }
cannam@62 441
cannam@62 442 template <> void JsonCodec::addTypeHandler(Handler<DynamicValue>& handler)
cannam@62 443 KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
cannam@62 444 "try specifying a specific type schema as the first parameter");
cannam@62 445 template <> void JsonCodec::addTypeHandler(Handler<DynamicEnum>& handler)
cannam@62 446 KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
cannam@62 447 "try specifying a specific type schema as the first parameter");
cannam@62 448 template <> void JsonCodec::addTypeHandler(Handler<DynamicStruct>& handler)
cannam@62 449 KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
cannam@62 450 "try specifying a specific type schema as the first parameter");
cannam@62 451 template <> void JsonCodec::addTypeHandler(Handler<DynamicList>& handler)
cannam@62 452 KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
cannam@62 453 "try specifying a specific type schema as the first parameter");
cannam@62 454 template <> void JsonCodec::addTypeHandler(Handler<DynamicCapability>& handler)
cannam@62 455 KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
cannam@62 456 "try specifying a specific type schema as the first parameter");
cannam@62 457 // TODO(someday): Implement support for registering handlers that cover thinsg like "all structs"
cannam@62 458 // or "all lists". Currently you can only target a specific struct or list type.
cannam@62 459
cannam@62 460 } // namespace capnp
cannam@62 461
cannam@62 462 #endif // CAPNP_COMPAT_JSON_H_