1 /*
2  * hunt-proton: AMQP Protocol library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 module hunt.proton.codec.CompositeWritableBuffer;
12 
13 import hunt.io.ByteBuffer;
14 
15 import hunt.proton.codec.ReadableBuffer;
16 import hunt.io.BufferUtils;
17 import hunt.proton.codec.WritableBuffer;
18 import hunt.Float;
19 import hunt.Double;
20 import hunt.String;
21 
22 class CompositeWritableBuffer : WritableBuffer
23 {
24     private WritableBuffer _first;
25     private WritableBuffer _second;
26 
27     this(WritableBuffer first, WritableBuffer second)
28     {
29         _first = first;
30         _second = second;
31     }
32 
33     override
34     public void put(byte b)
35     {
36         (_first.hasRemaining() ? _first : _second).put(b);
37     }
38 
39     override
40     public void putFloat(float f)
41     {
42         putInt(Float.floatToRawIntBits(f));
43     }
44 
45     override
46     public void putDouble(double d)
47     {
48         putLong(Double.doubleToRawLongBits(d));
49     }
50 
51     override
52     public void putShort(short s)
53     {
54         int remaining = _first.remaining();
55         if(remaining >= 2)
56         {
57             _first.putShort(s);
58         }
59         else if(remaining ==0 )
60         {
61             _second.putShort(s);
62         }
63         else
64         {
65             ByteBuffer wrap = BufferUtils.toBuffer(new byte[2]);
66             wrap.putShort(s);
67             wrap.flip();
68             put(wrap);
69         }
70     }
71 
72     override
73     public void putInt(int i)
74     {
75         int remaining = _first.remaining();
76         if(remaining >= 4)
77         {
78             _first.putInt(i);
79         }
80         else if(remaining ==0 )
81         {
82             _second.putInt(i);
83         }
84         else
85         {
86             ByteBuffer wrap = BufferUtils.toBuffer(new byte[4]);
87             wrap.putInt(i);
88             wrap.flip();
89             put(wrap);
90         }
91     }
92 
93     override
94     public void putLong(long l)
95     {
96         int remaining = _first.remaining();
97         if(remaining >= 8)
98         {
99             _first.putLong(l);
100         }
101         else if(remaining ==0 )
102         {
103             _second.putLong(l);
104         }
105         else
106         {
107             ByteBuffer wrap = BufferUtils.toBuffer(new byte[8]);
108             wrap.putLong(l);
109             wrap.flip();
110             put(wrap);
111         }
112     }
113 
114     override
115     public bool hasRemaining()
116     {
117         return _first.hasRemaining() || _second.hasRemaining();
118     }
119 
120     override
121     public int remaining()
122     {
123         return _first.remaining()+_second.remaining();
124     }
125 
126     override
127     public int position()
128     {
129         return _first.position()+_second.position();
130     }
131 
132     override
133     public int limit()
134     {
135         return _first.limit() + _second.limit();
136     }
137 
138     override
139     public void position(int position)
140     {
141         int first_limit = _first.limit();
142         if( position <= first_limit )
143         {
144             _first.position(position);
145             _second.position(0);
146         }
147         else
148         {
149             _first.position(first_limit);
150             _second.position(position - first_limit);
151         }
152     }
153 
154     override
155     public void put(byte[] src, int offset, int length)
156     {
157         int firstRemaining = _first.remaining();
158         if(firstRemaining > 0)
159         {
160             if(firstRemaining >= length)
161             {
162                 _first.put(src, offset, length);
163                 return;
164             }
165             else
166             {
167                 _first.put(src,offset, firstRemaining);
168             }
169         }
170         _second.put(src, offset+firstRemaining, length-firstRemaining);
171     }
172 
173     override
174     public void put(ByteBuffer payload)
175     {
176         int firstRemaining = _first.remaining();
177         if(firstRemaining > 0)
178         {
179             if(firstRemaining >= payload.remaining())
180             {
181                 _first.put(payload);
182                 return;
183             }
184             else
185             {
186                 int limit = payload.limit();
187                 payload.limit(payload.position()+firstRemaining);
188                 _first.put(payload);
189                 payload.limit(limit);
190             }
191         }
192         _second.put(payload);
193     }
194 
195     //override
196     //public String toString()
197     //{
198     //    return _first.toString() ~ " ~ "+_second.toString();
199     //}
200 
201     override
202     public void put(ReadableBuffer payload) {
203         int firstRemaining = _first.remaining();
204         if(firstRemaining > 0)
205         {
206             if(firstRemaining >= payload.remaining())
207             {
208                 _first.put(payload);
209                 return;
210             }
211             else
212             {
213                 int limit = payload.limit();
214                 payload.limit(payload.position()+firstRemaining);
215                 _first.put(payload);
216                 payload.limit(limit);
217             }
218         }
219         _second.put(payload);
220     }
221 
222     public void put(String value)
223     {
224         if (_first.hasRemaining())
225         {
226             byte[] utf8Bytes = value.getBytes();
227             put(utf8Bytes, 0, cast(int)utf8Bytes.length);
228         }
229         else
230         {
231             _second.put(cast(string)value.getBytes());
232         }
233     }
234 }