//
// Copyright 2012 Francisco Jerez
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//

#include <type_traits>
#include <iostream>

#include "core/module.hpp"

using namespace clover;

namespace {
   template<typename T, typename = void>
   struct _serializer;

   /// Serialize the specified object.
   template<typename T>
   void
   _proc(std::ostream &os, const T &x) {
      _serializer<T>::proc(os, x);
   }

   /// Deserialize the specified object.
   template<typename T>
   void
   _proc(std::istream &is, T &x) {
      _serializer<T>::proc(is, x);
   }

   template<typename T>
   T
   _proc(std::istream &is) {
      T x;
      _serializer<T>::proc(is, x);
      return x;
   }

   /// Calculate the size of the specified object.
   template<typename T>
   void
   _proc(module::size_t &sz, const T &x) {
      _serializer<T>::proc(sz, x);
   }

   /// (De)serialize a scalar value.
   template<typename T>
   struct _serializer<T, typename std::enable_if<
                            std::is_scalar<T>::value>::type> {
      static void
      proc(std::ostream &os, const T &x) {
         os.write(reinterpret_cast<const char *>(&x), sizeof(x));
      }

      static void
      proc(std::istream &is, T &x) {
         is.read(reinterpret_cast<char *>(&x), sizeof(x));
      }

      static void
      proc(module::size_t &sz, const T &x) {
         sz += sizeof(x);
      }
   };

   /// (De)serialize a vector.
   template<typename T>
   struct _serializer<std::vector<T>,
                      typename std::enable_if<
                         !std::is_scalar<T>::value>::type> {
      static void
      proc(std::ostream &os, const std::vector<T> &v) {
         _proc<uint32_t>(os, v.size());

         for (size_t i = 0; i < v.size(); i++)
            _proc<T>(os, v[i]);
      }

      static void
      proc(std::istream &is, std::vector<T> &v) {
         v.resize(_proc<uint32_t>(is));

         for (size_t i = 0; i < v.size(); i++)
            new(&v[i]) T(_proc<T>(is));
      }

      static void
      proc(module::size_t &sz, const std::vector<T> &v) {
         sz += sizeof(uint32_t);

         for (size_t i = 0; i < v.size(); i++)
            _proc<T>(sz, v[i]);
      }
   };

   template<typename T>
   struct _serializer<std::vector<T>,
                      typename std::enable_if<
                         std::is_scalar<T>::value>::type> {
      static void
      proc(std::ostream &os, const std::vector<T> &v) {
         _proc<uint32_t>(os, v.size());
         os.write(reinterpret_cast<const char *>(&v[0]),
                  v.size() * sizeof(T));
      }

      static void
      proc(std::istream &is, std::vector<T> &v) {
         v.resize(_proc<uint32_t>(is));
         is.read(reinterpret_cast<char *>(&v[0]),
                 v.size() * sizeof(T));
      }

      static void
      proc(module::size_t &sz, const std::vector<T> &v) {
         sz += sizeof(uint32_t) + sizeof(T) * v.size();
      }
   };

   /// (De)serialize a string.
   template<>
   struct _serializer<std::string> {
      static void
      proc(std::ostream &os, const std::string &s) {
         _proc<uint32_t>(os, s.size());
         os.write(&s[0], s.size() * sizeof(std::string::value_type));
      }

      static void
      proc(std::istream &is, std::string &s) {
         s.resize(_proc<uint32_t>(is));
         is.read(&s[0], s.size() * sizeof(std::string::value_type));
      }

      static void
      proc(module::size_t &sz, const std::string &s) {
         sz += sizeof(uint32_t) + sizeof(std::string::value_type) * s.size();
      }
   };

   /// (De)serialize a module::section.
   template<>
   struct _serializer<module::section> {
      template<typename S, typename QT>
      static void
      proc(S &s, QT &x) {
         _proc(s, x.id);
         _proc(s, x.type);
         _proc(s, x.size);
         _proc(s, x.data);
      }
   };

   /// (De)serialize a module::argument.
   template<>
   struct _serializer<module::argument> {
      template<typename S, typename QT>
      static void
      proc(S &s, QT &x) {
         _proc(s, x.type);
         _proc(s, x.size);
         _proc(s, x.target_size);
         _proc(s, x.target_align);
         _proc(s, x.ext_type);
         _proc(s, x.semantic);
      }
   };

   /// (De)serialize a module::symbol.
   template<>
   struct _serializer<module::symbol> {
      template<typename S, typename QT>
      static void
      proc(S &s, QT &x) {
         _proc(s, x.name);
         _proc(s, x.attributes);
         _proc(s, x.reqd_work_group_size);
         _proc(s, x.section);
         _proc(s, x.offset);
         _proc(s, x.args);
      }
   };

   /// (De)serialize a module.
   template<>
   struct _serializer<module> {
      template<typename S, typename QT>
      static void
      proc(S &s, QT &x) {
         _proc(s, x.syms);
         _proc(s, x.secs);
      }
   };
};

namespace clover {
   void
   module::serialize(std::ostream &os) const {
      _proc(os, *this);
   }

   module
   module::deserialize(std::istream &is) {
      return _proc<module>(is);
   }

   module::size_t
   module::size() const {
      size_t sz = 0;
      _proc(sz, *this);
      return sz;
   }
}
