// Copyright (c) 2013-2020, SIB - Swiss Institute of Bioinformatics and
//                          Biozentrum - University of Basel
// 
// 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.


/// \brief Defines a portable binary data source.
/// This works with files dumped by PortableBinaryDataSink.
/// The interface is compatible with ost-like data sources.
/// (see portable_binary_serializer for example)

#ifndef PROMOD3_PORTABLE_BINARY_DATA_SOURCE_HH
#define PROMOD3_PORTABLE_BINARY_DATA_SOURCE_HH

#include <iostream>
#include <fstream>
#include <ost/base.hh>
#include <ost/stdint.hh>
#include <ost/io/convert.hh>

namespace promod3 { namespace core {

class PortableBinaryDataSource {
public:
  /// \brief Initialize source to work with given stream.
  PortableBinaryDataSource(std::ifstream& stream): stream_(stream) { }

  //////////////////////////////////////////////////////////
  // OST-interface
  //////////////////////////////////////////////////////////
  /// \brief Serialize structures and fixed-width types with no conversion.
  /// When a structure/class is serialized, it calls object.Serialize(*this).
  /// Behavior for objects of type T can be overloaded by defining:
  /// void Serialize(PortableBinaryDataSource& source, T& value)
  template <typename SERIALIZABLE>
  PortableBinaryDataSource& operator >> (SERIALIZABLE& object) {
    Serialize(*this, object);
    return *this;
  }
  /// \brief Synonymous for operator >>.
  /// Works for both sources and sinks and not for C++-streams.
  template <typename SERIALIZABLE>
  PortableBinaryDataSource& operator & (SERIALIZABLE& object) {
    return this->operator>>(object);
  }

  /// \brief Get internal file stream
  std::ifstream& Stream() {
    return stream_;
  }
  
  /// \brief Check if this is a source (true) or a sink (false)
  bool IsSource() { return true; }
  //////////////////////////////////////////////////////////
private:
  std::ifstream& stream_;
};

}} // ns

#endif
