1 module collie.codec.http.httpwritebuffer;
2 
3 import kiss.buffer;
4 import kiss.net.struct_;
5 import kiss.event.task;
6 
7 @trusted abstract class HttpWriteBuffer : StreamWriteBuffer, WriteBuffer
8 {
9 	override abstract size_t write(in ubyte[] data);
10 
11 	override abstract size_t set(size_t pos, in ubyte[] data);
12 
13 	override abstract @property size_t length() const;
14 
15     void setFinalTask(AbstractTask task){
16         _task = task;
17     }
18 
19     override void doFinish() nothrow{
20 		if(_task !is null)
21         	_task.job();
22     }
23 private:
24     AbstractTask _task;
25 }
26 
27 class HTTPByteBuffer(Alloc) : HttpWriteBuffer
28 {
29     import kiss.bytes;
30     import kiss.container.Vector;
31     import std.experimental.allocator.common;
32 
33     alias BufferStore = Vector!(ubyte,Alloc); 
34 
35     static if (stateSize!(Alloc) != 0)
36 	{
37 		this(Alloc alloc)
38 		{
39 			_store = BufferStore(1024,alloc);
40 		}
41 		
42 		@property allocator(){return _store.allocator;}
43 		
44 	} else {
45 		this()
46 		{
47 			_store = BufferStore(1024);
48 		}
49 	}
50 
51 	~this(){
52 		destroy(_store);
53 	}
54 
55     override size_t write(in ubyte[] data)
56 	{
57 		size_t len = _store.length;
58 		()@trusted{_store.insertBack(cast(ubyte[])data);}();
59 		return _store.length - len;
60 	}
61 
62 	override size_t set(size_t pos, in ubyte[] data)
63 	{
64 		import core.stdc..string : memcpy;
65 		if(pos >= _store.length || data.length == 0) return 0;
66 		size_t len = _store.length - pos;
67 		len = len > data.length ? data.length : len;
68 		()@trusted{
69 			ubyte *	ptr = cast(ubyte *)(_store.ptr + pos);
70 			memcpy(ptr, data.ptr, len);
71 		}();
72 		
73 		return len;
74 	}
75 
76     void rest(size_t size){
77 		_rsize = size;
78 	}
79 
80     override const(ubyte)[] sendData() nothrow 
81     {
82         size_t len = _rsize + 4096;// 一次最大发送4K
83 		len = _store.length < len ? _store.length : len;
84 		auto _data = _store.data();
85 		return _data[_rsize .. len];
86     }
87 
88     override bool popSize(size_t size) nothrow
89     {
90         _rsize += size;
91         return _rsize >= _store.length;
92     }
93 
94     override void doFinish() nothrow{
95         _store.clear();
96         super.doFinish();
97     }
98 
99 	override size_t length() const{
100 		return _store.length;
101 	}
102 private:
103 	BufferStore _store;
104 	size_t _rsize = 0;
105 }