exports.BufferWriter = BufferWriter;
exports.BufferReader = BufferReader;
function BufferWriter(size){
	this.buf_ = new Buffer(size);
	this.wr_ = 0;
}
 var ByteAnd = function(a,b){
	var tmpa = a/2;
	var tmpb = b/2;
	var badd = false;
	if( (tmpa > Math.floor(tmpa)) && (tmpb > Math.floor(tmpb)) ){
		badd = true;
	}
	tmpa = Math.floor(tmpa);
	tmpb = Math.floor(tmpb);
	var res =  (tmpa & tmpb) * 2;
	return badd?res+1:res;
}
BufferWriter.prototype.WriteUInt64 = function(val){
	var val1 = ByteAnd(val,0xffffffff);
	var val2 = (val - val1)/(0x100000000);//2^32
	this.WriteUInt32(val2);
	this.WriteUInt32(val1);
}
BufferWriter.prototype.WriteUInt32 = function(val){
	this.buf_.writeUInt32BE(val,this.wr_);
	this.wr_+=4;
}
BufferWriter.prototype.WriteUInt16 = function(val){
	this.buf_.writeUInt16BE(val,this.wr_);
	this.wr_+=2;
}
BufferWriter.prototype.WriteUInt8 = function(val){
	this.buf_.writeUInt8(val,this.wr_);
	this.wr_+=1;
}
BufferWriter.prototype.WriteStringAscii = function(str){
	var len = Buffer.byteLength(str);
	this.buf_.write(str,this.wr_,len,"ascii");
	this.wr_+= len;
	this.buf_[this.wr_] = 0;
	this.wr_ += 1;
}
BufferWriter.prototype.WriteBool = function(val){
	this.buf_.writeUInt8(val?1:0,this.wr_);
	this.wr_+=1;
}
BufferWriter.prototype.GetBuffer = function(){
	var buf =  this.buf_.slice(0,this.wr_);
	return buf;
}
BufferWriter.prototype.WriteBuffer = function(buf){
	buf.copy(this.buf_,this.wr_);
	this.wr_ += buf.length;
}
function BufferReader(buf){
	this.buf_ = buf;
	this.rd_ = 0;
}

BufferReader.prototype.Grow = function(sz){
	this.rd_ += sz;
	if(this.rd_ > this.buf_.length){
		this.rd_ = this.buf_.length;
	}
}
BufferReader.prototype.GetDataBuffer = function(){
	return this.buf_.slice(this.rd_);
}
BufferReader.prototype.DataSize = function(){
	return this.buf_.length - this.rd_;
}
BufferReader.prototype.ReadUInt32 = function(){
	var val = this.buf_.readUInt32BE(this.rd_);
	this.rd_+=4;
	return val;
}
BufferReader.prototype.ReadUInt16 = function(){
	var val = this.buf_.readUInt16BE(this.rd_);
	this.rd_+=2;
	return val;
}
BufferReader.prototype.ReadUInt64 = function(){
	var val1 = this.ReadUInt32();
	var val2 = this.ReadUInt32();
	val2 += val1;
	val1 = val1 * 0xffffffff
    return val2 + val1;
}
BufferReader.prototype.ReadUInt8 = function(){
	var val = this.buf_.readUInt8(this.rd_);
	this.rd_+=1;
	return val;
}
BufferReader.prototype.ReadStringAscii = function(){
	var strbuf = new Buffer(1024);
	var index = 0;
	var start_index = this.rd_;
	while(start_index < this.buf_.length){
		var ch = this.buf_[start_index];
		if(ch == 0){
			break;
		}
		start_index++;
		strbuf[index] = ch;
		index++;
	}
	this.rd_ += index+1;
	var str = strbuf.toString("ascii",0,index);
	return str;
}
BufferReader.prototype.ReadBool = function(){
	var val = this.buf_.readUInt8(this.rd_);
	this.rd_+=1;
	return val == 1;
}