#include <cereal/types/unordered_map.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/types/concepts/pair_associative_container.hpp>
#include <cereal/types/vector.hpp>

#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>

// https://github.com/USCiLab/cereal
// https://uscilab.github.io/cereal/stl_support.html
// https://stackoverflow.com/questions/47297648/using-cereal-to-deserialize-a-json-string

struct Foo
{
	// data types
	int n;
	double dd;
	char arr[128] = { 0 };
	std::string sss;
	short s;
	float f;

	// serialization/archive method
	template<class Archive>
	void serialize(Archive& ar)
	{
		ar(n, dd, arr, sss, s, f);
	}
};

int main(int argc, char* argv[])
{
	// construct our object
	Foo f;
	f.n = 5;
	f.dd = 6.891;
	memcpy(f.arr, "Hello World\0", 12);
	f.sss = "Suck it";
	f.s = 4;
	f.f = 3.12456f;

	// output first
	std::cout << f.n << std::endl;
	std::cout << f.dd << std::endl;
	std::cout << f.arr << std::endl;
	std::cout << f.sss.c_str() << std::endl;
	std::cout << f.s << std::endl;
	std::cout << f.f << std::endl;

	// Serialize to JSON
	std::stringstream os;
	{
		cereal::JSONOutputArchive archive_out(os);
		archive_out(CEREAL_NVP(f));
	}

	std::string json_str = os.str();
	std::cout << json_str << std::endl;

	// Deserialize from JSON
	std::stringstream is(json_str);
	Foo data_new;
	{
		cereal::JSONInputArchive archive_in(is);
		archive_in(data_new);
		std::cout << data_new.n << std::endl;
		std::cout << data_new.dd << std::endl;
		std::cout << data_new.arr << std::endl;
		std::cout << data_new.sss.c_str() << std::endl;
		std::cout << data_new.s << std::endl;
		std::cout << data_new.f << std::endl;
	}
	return 0;
}