/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include namespace thrift { namespace test { /** * We serialize the first four bytes of the data_ string into the intData * field and the rest into the stringData field of the thrift struct. */ class MyCustomStruct { public: MyCustomStruct() : data_(4, '\0') {} /* implicit */ MyCustomStruct(const std::string& data) : data_(data) {} void __fbthrift_clear() { data_.clear(); } bool operator==(const MyCustomStruct& other) const { return data_ == other.data_; } bool operator<(const MyCustomStruct& other) const { return data_ < other.data_; } std::string data_; }; /** * If data_ is parseable into an int, we serialize it as the intData field of * the thrift union; otherwise as the stringData field. */ class MyCustomUnion { public: MyCustomUnion() {} /* implicit */ MyCustomUnion(const std::string& data) : data_(data) {} void __fbthrift_clear() { data_.clear(); } bool operator==(const MyCustomUnion& other) const { return data_ == other.data_; } bool operator<(const MyCustomUnion& other) const { return data_ < other.data_; } std::string data_; }; } // namespace test } // namespace thrift //////////////////////////////////////////////////////////////////////////////// namespace apache { namespace thrift { template <> class Cpp2Ops<::thrift::test::MyCustomStruct> { public: template static uint32_t write( Protocol* p, const ::thrift::test::MyCustomStruct* obj) { uint32_t xfer = 0; assert(obj->data_.size() >= sizeof(int)); const int prefix = *reinterpret_cast(&obj->data_[0]); std::string suffix = obj->data_.substr(sizeof(int)); xfer += p->writeStructBegin("MyStruct"); xfer += p->writeFieldBegin("stringData", protocol::T_STRING, 1); xfer += p->writeString(suffix); xfer += p->writeFieldEnd(); xfer += p->writeFieldBegin("intData", protocol::T_I32, 2); xfer += p->writeI32(prefix); xfer += p->writeFieldEnd(); xfer += p->writeFieldStop(); xfer += p->writeStructEnd(); return xfer; } template static uint32_t serializedSize( const Protocol* p, const ::thrift::test::MyCustomStruct* obj) { uint32_t xfer = 0; assert(obj->data_.size() >= sizeof(int)); const int prefix = *reinterpret_cast(&obj->data_[0]); std::string suffix = obj->data_.substr(sizeof(int)); xfer += p->serializedStructSize("MyStruct"); xfer += p->serializedFieldSize("stringData", protocol::T_STRING, 1); xfer += p->serializedSizeString(suffix); xfer += p->serializedFieldSize("intData", apache::thrift::protocol::T_I32, 2); xfer += p->serializedSizeI32(prefix); xfer += p->serializedSizeStop(); return xfer; } template static uint32_t serializedSizeZC( const Protocol* p, const ::thrift::test::MyCustomStruct* obj) { return serializedSize(p, obj); } template static void read(Protocol* iprot, ::thrift::test::MyCustomStruct* obj) { std::string fname; protocol::TType ftype; int16_t fid; std::string suffix; int prefix; iprot->readStructBegin(fname); while (true) { iprot->readFieldBegin(fname, ftype, fid); if (ftype == apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: if (ftype == apache::thrift::protocol::T_STRING) { iprot->readString(suffix); } else { iprot->skip(ftype); } break; case 2: if (ftype == apache::thrift::protocol::T_I32) { iprot->readI32(prefix); } else { iprot->skip(ftype); } break; default: iprot->skip(ftype); break; } iprot->readFieldEnd(); } iprot->readStructEnd(); obj->data_ = std::string(reinterpret_cast(&prefix), sizeof(int)) + suffix; } static constexpr apache::thrift::protocol::TType thriftType() { return apache::thrift::protocol::T_STRUCT; } }; //////////////////////////////////////////////////////////////////////////////// template <> class Cpp2Ops<::thrift::test::MyCustomUnion> { public: template static uint32_t write(Protocol* p, const ::thrift::test::MyCustomUnion* obj) { uint32_t xfer = 0; xfer += p->writeStructBegin("MyStruct"); try { int i = folly::to(obj->data_); xfer += p->writeFieldBegin("intData", protocol::T_I32, 2); xfer += p->writeI32(i); xfer += p->writeFieldEnd(); } catch (const std::range_error&) { xfer += p->writeFieldBegin("stringData", protocol::T_STRING, 1); xfer += p->writeString(obj->data_); xfer += p->writeFieldEnd(); } xfer += p->writeFieldStop(); xfer += p->writeStructEnd(); return xfer; } template static uint32_t serializedSize( const Protocol* p, const ::thrift::test::MyCustomUnion* obj) { uint32_t xfer = 0; xfer += p->serializedStructSize("MyStruct"); try { int i = folly::to(obj->data_); xfer += p->serializedFieldSize("intData", protocol::T_I32, 2); xfer += p->serializedSizeI32(i); } catch (const std::range_error&) { xfer += p->serializedFieldSize("stringData", protocol::T_STRING, 1); xfer += p->serializedSizeString(obj->data_); } xfer += p->serializedSizeStop(); return xfer; } template static uint32_t serializedSizeZC( const Protocol* p, const ::thrift::test::MyCustomUnion* obj) { return serializedSize(p, obj); } template static void read(Protocol* iprot, ::thrift::test::MyCustomUnion* obj) { std::string fname; protocol::TType ftype; int16_t fid; iprot->readStructBegin(fname); iprot->readFieldBegin(fname, ftype, fid); if (ftype != apache::thrift::protocol::T_STOP) { switch (fid) { case 1: if (ftype == apache::thrift::protocol::T_STRING) { iprot->readString(obj->data_); } else { iprot->skip(ftype); } break; case 2: if (ftype == apache::thrift::protocol::T_I32) { int i; iprot->readI32(i); obj->data_ = folly::to(i); } else { iprot->skip(ftype); } break; default: iprot->skip(ftype); break; } iprot->readFieldEnd(); iprot->readFieldBegin(fname, ftype, fid); iprot->readFieldEnd(); } iprot->readStructEnd(); } static constexpr apache::thrift::protocol::TType thriftType() { return apache::thrift::protocol::T_STRUCT; } }; } // namespace thrift } // namespace apache