Giter VIP home page Giter VIP logo

Comments (2)

lifflander avatar lifflander commented on July 29, 2024

Implementation sketch:

namespace serdes {


using AutoHandlerType = int;

template <typename T, typename SerializerT>
using RegistryType = std::vector<
  std::tuple<
    int,
    std::function<void(T*, SerializerT&)>,
    std::function<T*(void)>
  >
>;

template <typename T, typename SerializerT>
inline RegistryType<T, SerializerT>& getRegistry();

template <typename ObjT, typename SerializerT>
struct Registrar {
  Registrar();
  AutoHandlerType index;
};

template <typename ObjT, typename SerializerT>
struct Type {
  static AutoHandlerType const idx;
};

inline AutoHandlerType getObjIdx(AutoHandlerType han);

template <typename ObjT, typename SerializerT>
inline AutoHandlerType makeObjIdx();


template <typename T, typename SerializerT>
inline RegistryType<T,SerializerT>& getRegistry() {
  static RegistryType<T,SerializerT> reg;
  return reg;
}

template <typename ObjT, typename SerializerT>
Registrar<ObjT, SerializerT>::Registrar() {
  using BaseType = typename ObjT::BaseType;

  auto& reg = getRegistry<BaseType, SerializerT>();
  index = reg.size();

  printf("registrar: %ld, %s %s\n", reg.size(), typeid(ObjT).name(), typeid(SerializerT).name());

  reg.emplace_back(
    std::make_tuple(
      index,
      [](BaseType* t, SerializerT& s) -> void { static_cast<ObjT*>(t)->serialize(s); },
      []() -> BaseType* { return new ObjT; }
    )
  );
}

template <typename ObjT, typename SerializerT>
AutoHandlerType const Type<ObjT, SerializerT>::idx = Registrar<ObjT, SerializerT>().index;

template <typename T, typename SerializerT>
inline auto getObjIdx(AutoHandlerType han) {
  printf("getObjIdx: han=%d, size=%ld\n", han, getRegistry<T, SerializerT>().size());
  return getRegistry<T, SerializerT>().at(han);
}

template <typename ObjT, typename SerializerT>
inline AutoHandlerType makeObjIdx() {
  return Type<ObjT, SerializerT>::idx;
}

template <typename DerivedT, typename BaseT>
struct SerializableDerived : BaseT {
  using BaseType = BaseT;

  SerializableDerived() {
    // Must pretend to call this as so so it gets instantiated
    if (false) {
      neverRun();
    }
  }

  template <typename SerializerT>
  void serialize(SerializerT& s) {
    printf("SerializableDerived:: serialize\n");
    if (!s.isUnpacking()) {
      auto val = makeObjIdx<DerivedT, SerializerT>();
      s | val;
      printf("Derived: packing in %d\n", val);
      BaseT::serialize(s);
    }
  }

  void doSerialize(serdes::Serializer* s) override {
    if (s->isSizing()) {
      *static_cast<serdes::Sizer*>(s) | (*static_cast<DerivedT*>(this));
    } else if (s->isPacking()) {
      *static_cast<serdes::Packer*>(s) | (*static_cast<DerivedT*>(this));
    } else if (s->isUnpacking()) {
      *static_cast<serdes::Unpacker*>(s) | (*static_cast<DerivedT*>(this));
    }
  }

  void neverRun() {
    assert(0);
    DerivedT mo;
    serdes::serializeType<DerivedT>(mo);
    serdes::deserializeType<DerivedT>(0,0);
  }

};

template <typename BaseT>
struct SerializableBase {

  template <typename SerializerT>
  void serialize(SerializerT& s) {
    printf("SerializableBase:: serialize\n");
    if (s.isUnpacking()) {
      AutoHandlerType concrete = 0;
      s | concrete;
      printf("base: concrete=%d\n", concrete);
      auto lam = getObjIdx<BaseT, SerializerT>(concrete);
      // When unpacking, dispatch to concrete serializer lambda
      std::get<1>(lam)(static_cast<BaseT*>(this), s);
    }
  }

  virtual void doSerialize(serdes::Serializer*)  = 0;
};

template <typename BaseT, typename SerializerT>
void virtualSerialize(BaseT*& base, SerializerT& s) {
  if (!s.isUnpacking()) {
    base->doSerialize(&s);
  } else {
    // Peek to see the type of the next element, get the right constructor
    int entry = *reinterpret_cast<int*>(s.getSpotIncrement(0));
    printf("entry=%d\n", entry);
    auto lam = getObjIdx<BaseT, serdes::Unpacker>(entry);
    auto ptr = std::get<2>(lam)();
    s | *ptr;
  }
}



/////////////////////////////////////////////////////////////////////////////
// Begin user code
////////////////////////////////////////////////////////////////////////////

namespace examples {

struct MyBase : serdes::SerializableBase<MyBase> {
  MyBase() { printf("MyBase cons\n"); abc=100; }

  int abc;

  template <typename S>
  void serialize(S& s) {
    serdes::SerializableBase<MyBase>::serialize(s);
    printf("MyBase: serialize\n");
    s | abc;
  }
};

struct MyObj : serdes::SerializableDerived<MyObj, MyBase> {
  MyObj() { printf("MyObj cons\n"); }

  template <typename SerializerT>
  void serialize(SerializerT& s) {
    serdes::SerializableDerived<MyObj, MyBase>::serialize(s);
  }
};

struct MyObj2 : serdes::SerializableDerived<MyObj2, MyBase> {
  MyObj2() { printf("MyObj2 cons\n"); }

  template <typename SerializerT>
  void serialize(SerializerT& s) {
    serdes::SerializableDerived<MyObj2, MyBase>::serialize(s);
  }
};

struct MyObj3 : serdes::SerializableDerived<MyObj3, MyBase> {
  int a, b, c;
  MyObj3() { printf("MyObj3 cons\n"); a= 10; b=20; c=100; }

  template <typename SerializerT>
  void serialize(SerializerT& s) {
    printf("MyObj3: serialize\n");
    serdes::SerializableDerived<MyObj3, MyBase>::serialize(s);
    s|a|b|c;
  }

};

/*
 * Example vector that holds virtual elements. User calls
 * `serdes::virtualSerialize(elm, s)` instead of `s | elm`
 */

struct ExampleVector {

  template <typename SerializerT>
  void serialize(SerializerT& s) {
    std::size_t size = vec.size();
    s | size;
    vec.resize(size);

    for (auto& elm : vec) {
      serdes::virtualSerialize(elm, s);
    }
  }

  std::vector<MyBase*> vec;
};

void test() {

  ExampleVector v;
  v.vec.push_back(new MyObj3);
  v.vec.push_back(new MyObj2);
  v.vec.push_back(new MyObj);

  auto ret = serdes::serializeType<ExampleVector>(v);

  auto const& buf = std::get<0>(ret);
  auto const& buf_size = std::get<1>(ret);

  printf("ptr=%p, size=%ld\n", static_cast<void*>(buf->getBuffer()), buf_size);

  auto tptr = serdes::deserializeType<ExampleVector>(buf->getBuffer(), buf_size);
  auto& t = *tptr;
}

}} // end namespace serdes::examples

int main(int, char**) {
  using namespace serdes::examples;

  test();

  return 0;
}

from magistrate.

PhilMiller avatar PhilMiller commented on July 29, 2024

I'm looking for the issues you've encountered, whenever you post the code

from magistrate.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.