module coneneko.serializer;
import std.stream, coneneko.math;

///
interface Serializer
{
	void serialize(Stream writer); ///
	void deserialize(Stream reader); ///
}

void writeFile(string fileName, Serializer a) ///
{
	auto s = new BufferedFile(fileName, FileMode.OutNew);
	scope (exit) s.close();
	a.serialize(s);
}

void readFile(string fileName, Serializer a) ///
{
	auto s = new BufferedFile(fileName, FileMode.In);
	scope (exit) s.close();
	a.deserialize(s);
}

class SerializeStream : FilterStream
{
	this(Stream source)
	{
		super(source);
		nestClose = false;
	}
	
	void throwIfHeaderError(string header)
	{
		char[] h;
		read(h);
		if (h != header) throw new Error(header ~ ".deserialize: " ~ cast(string)h); // d2
	}
	
	size_t readSizeT()
	{
		size_t result;
		read(result);
		return result;
	}
	
	Vector readVector()
	{
		Vector result;
		readExact(&result, Vector.sizeof);
		return result;
	}
	
	Vector[] readVectors()
	{
		auto result = new Vector[readSizeT()];
		read(cast(ubyte[])result);
		return result;
	}
	
	uint[] readUints()
	{
		auto result = new uint[readSizeT()];
		read(cast(ubyte[])result);
		return result;
	}
	
	alias FilterStream.write write;
	
	void write(bool a)
	{
		write(cast(ubyte)a);
	}
	
	void write(Vector[] a)
	{
		write(a.length);
		write(cast(ubyte[])a);
	}
	
	bool readBool()
	{
		ubyte result;
		read(result);
		return cast(bool)result;
	}
	
	void write(Vector a)
	{
		writeExact(&a, Vector.sizeof);
	}
	
	void write(uint[] a)
	{
		write(a.length);
		write(cast(ubyte[])a);
	}
}
