]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.common/src/org/simantics/db/common/WriteBindings.java
e9ecce63c8ba0eac39b71e933edb801247f17b04
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / WriteBindings.java
1 package org.simantics.db.common;
2
3 import java.io.IOException;
4 import java.io.UTFDataFormatException;
5 import java.nio.charset.Charset;
6 import java.util.Arrays;
7
8 import org.simantics.databoard.Bindings;
9 import org.simantics.databoard.Datatypes;
10 import org.simantics.databoard.binding.Binding;
11 import org.simantics.databoard.binding.error.BindingConstructionException;
12 import org.simantics.databoard.binding.impl.LongBindingDefault;
13 import org.simantics.databoard.binding.impl.StringBindingDefault;
14 import org.simantics.databoard.binding.mutable.Variant;
15 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
16 import org.simantics.databoard.serialization.SerializationException;
17 import org.simantics.databoard.serialization.Serializer;
18 import org.simantics.databoard.serialization.impl.LongSerializer;
19 import org.simantics.databoard.serialization.impl.ModifiedUTF8StringSerializer;
20 import org.simantics.graph.representation.External;
21 import org.simantics.graph.representation.Identity;
22 import org.simantics.graph.representation.Internal;
23 import org.simantics.graph.representation.Optional;
24 import org.simantics.graph.representation.Root;
25 import org.simantics.graph.representation.TransferableGraph1;
26 import org.simantics.graph.representation.Value;
27
28 public class WriteBindings {
29
30         static class STRING_SERIALIZER extends ModifiedUTF8StringSerializer {
31
32                 public static final Charset UTF8 = Charset.forName("utf-8");
33
34                 public static STRING_SERIALIZER INSTANCE = new STRING_SERIALIZER();
35
36                 public STRING_SERIALIZER() {
37                         super(STRING_BINDING.INSTANCE);
38                 }
39
40                 static byte[] writeUTF(String str) throws IOException {
41
42                         int strlen = str.length();
43                         int utflen = 0;
44                         int c/*, count = 0*/;
45
46                         /* use charAt instead of copying String to char array */
47                         for (int i = 0; i < strlen; i++) {
48                                 c = str.charAt(i);
49                                 if ((c >= 0x0001) && (c <= 0x007F)) {
50                                         utflen++;
51                                 } else if (c > 0x07FF) {
52                                         utflen += 3;
53                                 } else {
54                                         utflen += 2;
55                                 }
56                         }
57
58                         if (utflen > 65535)
59                                 throw new UTFDataFormatException(
60                                                 "encoded string too long: " + utflen + " bytes");
61
62                         int byteIndex = 0;
63                         byte[] bytearr;
64                         
65                         int lengthTester = utflen;
66                         
67                         if(lengthTester < 0x80) {
68                                 bytearr = new byte[utflen+1];
69                                 bytearr[byteIndex++] = ((byte)utflen);
70                         }
71                         else {
72                                 lengthTester -= 0x80;
73                                 if(lengthTester < 0x4000) {
74                                         bytearr = new byte[utflen+2];
75                                         bytearr[byteIndex++] = (byte)( ((lengthTester&0x3f) | 0x80) );
76                                         bytearr[byteIndex++] = (byte)( (lengthTester>>>6) );
77                                 }
78                                 else {
79                                         lengthTester -= 0x4000;
80                                         if(lengthTester < 0x200000) {
81                                                 bytearr = new byte[utflen+3];
82                                                 bytearr[byteIndex++] = (byte)( ((lengthTester&0x1f) | 0xc0) );
83                                                 bytearr[byteIndex++] = (byte)( ((lengthTester>>>5)&0xff) );
84                                                 bytearr[byteIndex++] = (byte)( ((lengthTester>>>13)&0xff) );    
85                                         }
86                                         else {
87                                                 lengthTester -= 0x200000;
88                                                 if(lengthTester < 0x10000000) {
89                                                         bytearr = new byte[utflen+4];
90                                                         bytearr[byteIndex++] = (byte)( ((lengthTester&0x0f) | 0xe0) );
91                                                         bytearr[byteIndex++] = (byte)( ((lengthTester>>>4)&0xff) );
92                                                         bytearr[byteIndex++] = (byte)( ((lengthTester>>>12)&0xff) );    
93                                                         bytearr[byteIndex++] = (byte)( ((lengthTester>>>20)&0xff) );
94                                                 }
95                                                 else {
96                                                         lengthTester -= 0x10000000;
97                                                         bytearr = new byte[utflen+5];
98                                                         bytearr[byteIndex++] = (byte)( ((lengthTester&0x07) | 0xf0) );
99                                                         bytearr[byteIndex++] = (byte)( ((lengthTester>>>3)&0xff) );
100                                                         bytearr[byteIndex++] = (byte)( ((lengthTester>>>11)&0xff) );    
101                                                         bytearr[byteIndex++] = (byte)( ((lengthTester>>>19)&0xff) );
102                                                         bytearr[byteIndex++] = (byte)( ((lengthTester>>>27)&0xff) );
103                                                 }
104                                         }                               
105                                 }
106                         }       
107
108
109                         int i=0;
110                         for (i=0; i<strlen; i++) {
111                                 c = str.charAt(i);
112                                 if (!((c >= 0x0001) && (c <= 0x007F))) break;
113                                 bytearr[byteIndex++] = (byte)(c);
114                         }
115
116                         for (;i < strlen; i++){
117                                 c = str.charAt(i);
118                                 if ((c >= 0x0001) && (c <= 0x007F)) {
119                                         bytearr[byteIndex++] = (byte)( c );
120                                 } else if (c > 0x07FF) {
121                                         bytearr[byteIndex++] = (byte)(0xE0 | ((c >> 12) & 0x0F));
122                                         bytearr[byteIndex++] = (byte)(0x80 | ((c >>  6) & 0x3F));
123                                         bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));
124                                 } else {
125                                         bytearr[byteIndex++] = (byte)(0xC0 | ((c >>  6) & 0x1F));
126                                         bytearr[byteIndex++] = (byte)(0x80 | ((c >>  0) & 0x3F));
127                                 }
128                         }
129
130                         return bytearr;
131
132                 }
133
134                 @Override
135                 public byte[] serialize(Object obj) throws IOException {
136                         try {
137                                 return writeUTF((String)obj);
138                         } catch (IOException e) {
139                                 throw new SerializationException();
140                         }
141                         
142                 }
143                 
144         }
145
146         static class BYTE_ARRAY_SERIALIZER extends LongSerializer {
147
148                 public static BYTE_ARRAY_SERIALIZER INSTANCE = new BYTE_ARRAY_SERIALIZER();
149
150                 public BYTE_ARRAY_SERIALIZER() {
151                         super(BYTE_ARRAY_BINDING.INSTANCE);
152                 }
153                 
154                 @Override
155                 public byte[] serialize(Object obj) throws IOException {
156                         
157                         return (byte[])obj;
158
159                 }
160                 
161                 @Override
162                 public Object deserialize(byte[] data) throws IOException {
163                         return data;
164                 }
165                 
166         }
167
168         final static class LONG_ARRAY_SERIALIZER extends LongSerializer {
169
170                 public static LONG_ARRAY_SERIALIZER INSTANCE = new LONG_ARRAY_SERIALIZER();
171
172                 public LONG_ARRAY_SERIALIZER() {
173                         super(LONG_ARRAY_BINDING.INSTANCE);
174                 }
175                 
176                 final private void loop(byte[] result, int index, long l) {
177                         result[index+7] = (byte)l;l >>>= 8;
178                         result[index+6] = (byte)l;l >>>= 8;
179                         result[index+5] = (byte)l;l >>>= 8;
180                         result[index+4] = (byte)l;l >>>= 8;
181                         result[index+3] = (byte)l;l >>>= 8;
182                         result[index+2] = (byte)l;l >>>= 8;
183                         result[index+1] = (byte)l;l >>>= 8;
184                         result[index] = (byte)l;l >>>= 8;
185                         
186 //                      result[index+6] = (byte)(l & 0xFF);
187 //                      l >>>= 8;
188 //                      result[index+5] = (byte)(l & 0xFF);
189 //                      l >>>= 8;
190 //                      result[index+4] = (byte)(l & 0xFF);
191 //                      l >>>= 8;
192 //                      result[index+3] = (byte)(l & 0xFF);
193 //                      l >>>= 8;
194 //                      result[index+2] = (byte)(l & 0xFF);
195 //                      l >>>= 8;
196 //                      result[index+1] = (byte)(l & 0xFF);
197 //                      l >>>= 8;
198 //                      result[index] = (byte)(l & 0xFF);
199 //                      l >>>= 8;
200                 }
201                 
202                 @Override
203                 public byte[] serialize(Object obj) throws IOException {
204                         
205                         long[] data = (long[])obj;
206                         byte[] result = new byte[4+8*data.length];
207                         
208                         int len = data.length;
209                         
210                         result[3] = (byte)(len & 0xFF);
211                         len >>>= 8;
212                         result[2] = (byte)(len & 0xFF);
213                         len >>>= 8;
214                         result[1] = (byte)(len & 0xFF);
215                         len >>>= 8;
216                         result[0] = (byte)(len & 0xFF);
217
218                         int index = 4;
219
220                         for(int i=0;i<data.length;i++) {
221
222                                 loop(result, index, data[i]);
223
224 //                              long l = data[i];
225
226 //                              result[index+7] = (byte)(l & 0xFF);
227 //                              l >>>= 8;
228 //                              result[index+6] = (byte)(l & 0xFF);
229 //                              l >>>= 8;
230 //                              result[index+5] = (byte)(l & 0xFF);
231 //                              l >>>= 8;
232 //                              result[index+4] = (byte)(l & 0xFF);
233 //                              l >>>= 8;
234 //                              result[index+3] = (byte)(l & 0xFF);
235 //                              l >>>= 8;
236 //                              result[index+2] = (byte)(l & 0xFF);
237 //                              l >>>= 8;
238 //                              result[index+1] = (byte)(l & 0xFF);
239 //                              l >>>= 8;
240 //                              result[index] = (byte)(l & 0xFF);
241 //                              l >>>= 8;
242                                 
243                                 index += 8;
244
245                         }
246                         
247                         return result;
248
249                 }
250                 
251         }
252
253         static class TRANSFERABLE_GRAPH_SERIALIZER extends LongSerializer {
254
255                 public static TRANSFERABLE_GRAPH_SERIALIZER INSTANCE = new TRANSFERABLE_GRAPH_SERIALIZER();
256
257                 public TRANSFERABLE_GRAPH_SERIALIZER() {
258                         super(TRANSFERABLE_GRAPH_BINDING.INSTANCE);
259                 }
260                 
261                 static int writeUTF(String str, byte[] bytearr, int byteIndex) throws IOException {
262                         
263                         int strlen = str.length();
264                         int utflen = 0;
265                         int c;
266                         int count = byteIndex;
267
268                         /* use charAt instead of copying String to char array */
269                         for (int i = 0; i < strlen; i++) {
270                                 c = str.charAt(i);
271                                 if ((c >= 0x0001) && (c <= 0x007F)) {
272                                         utflen++;
273                                 } else if (c > 0x07FF) {
274                                         utflen += 3;
275                                 } else {
276                                         utflen += 2;
277                                 }
278                         }
279
280                         if (utflen > 65535)
281                                 throw new UTFDataFormatException(
282                                                 "encoded string too long: " + utflen + " bytes");
283
284 //                      byte[] bytearr = new byte[utflen+2];
285
286                         if(utflen < 0x80) {
287                                 bytearr[count++] = ((byte)utflen);
288                         }
289                         else {
290                                 utflen -= 0x80;
291                                 if(utflen < 0x4000) {
292                                         bytearr[count++] = (byte)( ((utflen&0x3f) | 0x80) );
293                                         bytearr[count++] = (byte)( (utflen>>>6) );
294                                 }
295                                 else {
296                                         utflen -= 0x4000;
297                                         if(utflen < 0x200000) {
298                                                 bytearr[count++] = (byte)( ((utflen&0x1f) | 0xc0) );
299                                                 bytearr[count++] = (byte)( ((utflen>>>5)&0xff) );
300                                                 bytearr[count++] = (byte)( ((utflen>>>13)&0xff) );      
301                                         }
302                                         else {
303                                                 utflen -= 0x200000;
304                                                 if(utflen < 0x10000000) {
305                                                         bytearr[count++] = (byte)( ((utflen&0x0f) | 0xe0) );
306                                                         bytearr[count++] = (byte)( ((utflen>>>4)&0xff) );
307                                                         bytearr[count++] = (byte)( ((utflen>>>12)&0xff) );      
308                                                         bytearr[count++] = (byte)( ((utflen>>>20)&0xff) );
309                                                 }
310                                                 else {
311                                                         utflen -= 0x10000000;
312                                                         bytearr[count++] = (byte)( ((utflen&0x07) | 0xf0) );
313                                                         bytearr[count++] = (byte)( ((utflen>>>3)&0xff) );
314                                                         bytearr[count++] = (byte)( ((utflen>>>11)&0xff) );      
315                                                         bytearr[count++] = (byte)( ((utflen>>>19)&0xff) );
316                                                         bytearr[count++] = (byte)( ((utflen>>>27)&0xff) );
317                                                 }
318                                         }                               
319                                 }
320                         }       
321
322                         int i=0;
323                         for (i=0; i<strlen; i++) {
324                                 c = str.charAt(i);
325                                 if (!((c >= 0x0001) && (c <= 0x007F))) break;
326                                 bytearr[count++] = (byte) c;
327                         }
328
329                         for (;i < strlen; i++){
330                                 c = str.charAt(i);
331                                 if ((c >= 0x0001) && (c <= 0x007F)) {
332                                         bytearr[count++] = (byte) c;
333
334                                 } else if (c > 0x07FF) {
335                                         bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
336                                         bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
337                                         bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
338                                 } else {
339                                         bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
340                                         bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
341                                 }
342                         }
343                         
344                         return count - byteIndex;
345                         
346                 }
347                 
348                 @Override
349                 public byte[] serialize(Object obj) throws IOException {
350                         
351                         TransferableGraph1 tg = (TransferableGraph1)obj;
352                         
353                         return Bindings
354                                         .getSerializerUnchecked(TransferableGraph1.class)
355                                         .serialize(tg);
356 /*
357                         // 16 = resourceCount + 3 arrays
358 //                      long start = System.nanoTime();
359                         int actualSize = 16 + 8*tg.values.length + 4*tg.statements.length + 5*tg.identities.length;
360                         for(Value v : tg.values) actualSize += v.value.length;
361                         for(Identity id : tg.identities) { 
362                                 if(id.definition instanceof Internal) actualSize += (4 + ((Internal)id.definition).name.length() + 5);
363                                 else if(id.definition instanceof External) actualSize += (4 + ((External)id.definition).name.length() + 5);
364                                 else if(id.definition instanceof Root) actualSize += (((Root)id.definition).name.length() + ((Root)id.definition).type.length() + 10);
365                                 else if(id.definition instanceof Optional) actualSize += (4 + ((Optional)id.definition).name.length() + 5);
366                         }
367 //                      long end = System.nanoTime() - start;
368 //                      System.err.println("size took " + 1e-9*end);
369                         
370 //                      long start2 = System.nanoTime();
371                         
372                         
373                         byte[] bytes = new byte[actualSize];
374                         int byteIndex = 0;
375
376                         int i = tg.resourceCount;
377                         
378                         bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
379                         bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
380                         bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
381                         bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
382                         byteIndex+=4;
383                         
384                         i = tg.identities.length;
385
386                         bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
387                         bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
388                         bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
389                         bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
390                         byteIndex+=4;
391                         
392                         for(Identity id : tg.identities) {
393
394                                 i = id.resource;
395                                 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
396                                 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
397                                 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
398                                 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
399                                 byteIndex+=4;
400                                 
401                                 if(id.definition instanceof Internal) {
402
403                                         Internal r = (Internal)id.definition;
404
405                                         bytes[byteIndex++] = 3;
406
407                                         i = r.parent;
408                                         bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
409                                         bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
410                                         bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
411                                         bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
412                                         byteIndex+=4;
413                                         
414                                         byteIndex += writeUTF(r.name, bytes, byteIndex);
415
416                                 } else if(id.definition instanceof External) {
417
418                                         External r = (External)id.definition;
419
420                                         bytes[byteIndex++] = 1;
421
422                                         i = r.parent;
423                                         bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
424                                         bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
425                                         bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
426                                         bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
427                                         byteIndex+=4;
428                                         
429                                         byteIndex += writeUTF(r.name, bytes, byteIndex);
430                                         
431                                 } else if(id.definition instanceof Root) {
432                                         
433                                         bytes[byteIndex++] = 0;
434                                         
435                                         Root r = (Root)id.definition;
436                                         byteIndex += writeUTF(r.name, bytes, byteIndex);
437                                         byteIndex += writeUTF(r.type, bytes, byteIndex);
438                                         
439                                 } else if(id.definition instanceof Optional) {
440
441                                         Optional r = (Optional)id.definition;
442
443                                         bytes[byteIndex++] = 2;
444
445                                         i = r.parent;
446                                         bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
447                                         bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
448                                         bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
449                                         bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
450                                         byteIndex+=4;
451                                         
452                                         byteIndex += writeUTF(r.name, bytes, byteIndex);
453                                         
454                                 }
455                                 
456                         }
457                         
458                         i = tg.statements.length;
459                         bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
460                         bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
461                         bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
462                         bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
463                         byteIndex+=4;
464                         
465                         for(int s : tg.statements) {
466                                 i = s;
467                                 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
468                                 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
469                                 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
470                                 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
471                                 byteIndex+=4;
472                         }
473
474                         i = tg.values.length;
475                         bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
476                         bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
477                         bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
478                         bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
479                         byteIndex+=4;
480
481                         for(Value v : tg.values) {
482                                 
483                                 i = v.resource;
484                                 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
485                                 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
486                                 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
487                                 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
488                                 byteIndex+=4;
489
490                                 i = v.value.length;
491                                 bytes[byteIndex+3] = (byte)(i & 0xFF);i >>>= 8;
492                                 bytes[byteIndex+2] = (byte)(i & 0xFF);i >>>= 8;
493                                 bytes[byteIndex+1] = (byte)(i & 0xFF);i >>>= 8;
494                                 bytes[byteIndex] = (byte)(i & 0xFF);i >>>= 8;
495                                 byteIndex+=4;
496                                 
497                                 System.arraycopy(v.value, 0, bytes, byteIndex, v.value.length);
498                                 byteIndex += v.value.length;
499                                 
500                         }
501
502 //                      return bytes;
503                         
504 //                      byte[] result = new byte[byteIndex];
505 //                      System.arraycopy(bytes, 0, result, 0, byteIndex);
506 //                      
507 //                      byte[] result = Arrays.copyOf(bytes, byteIndex); 
508                         
509 //                      long end2 = System.nanoTime() - start2;
510 //                      System.err.println("size2 took " + 1e-9*end2);
511
512                         return bytes; 
513                         
514 //                      long[] data = (long[])obj;
515 //                      byte[] result = new byte[4+8*data.length];
516 //                      
517 //                      int len = data.length;
518 //                      
519 //                      result[3] = (byte)(len & 0xFF);
520 //                      len >>>= 8;
521 //                      result[2] = (byte)(len & 0xFF);
522 //                      len >>>= 8;
523 //                      result[1] = (byte)(len & 0xFF);
524 //                      len >>>= 8;
525 //                      result[0] = (byte)(len & 0xFF);
526 //
527 //                      int index = 4;
528 //
529 //                      for(int i=0;i<data.length;i++) {
530 //                              
531 //                              long l = data[i];
532 //
533 //                              result[index+7] = (byte)(l & 0xFF);
534 //                              l >>>= 8;
535 //                              result[index+6] = (byte)(l & 0xFF);
536 //                              l >>>= 8;
537 //                              result[index+5] = (byte)(l & 0xFF);
538 //                              l >>>= 8;
539 //                              result[index+4] = (byte)(l & 0xFF);
540 //                              l >>>= 8;
541 //                              result[index+3] = (byte)(l & 0xFF);
542 //                              l >>>= 8;
543 //                              result[index+2] = (byte)(l & 0xFF);
544 //                              l >>>= 8;
545 //                              result[index+1] = (byte)(l & 0xFF);
546 //                              l >>>= 8;
547 //                              result[index] = (byte)(l & 0xFF);
548 //                              l >>>= 8;
549 //                              
550 //                              index += 8;
551 //
552 //                      }
553 //                      
554 //                      return result;
555 */
556                 }
557                 
558                 
559                 final private String utf(byte[] bytes) {
560                         
561                         char[] chars = new char[bytes.length];
562                         
563                         int index = 0;
564                         int length = bytes[index++]&0xff; 
565                         if(length >= 0x80) {
566                                 if(length >= 0xc0) {
567                                         if(length >= 0xe0) {
568                                                 if(length >= 0xf0) {
569                                                         length &= 0x0f;
570                                                         length += ((bytes[index++]&0xff)<<3);
571                                                         length += ((bytes[index++]&0xff)<<11);
572                                                         length += ((bytes[index++]&0xff)<<19);
573                                                         length += 0x10204080;
574                                                 }
575                                                 else {
576                                                         length &= 0x1f;
577                                                         length += ((bytes[index++]&0xff)<<4);
578                                                         length += ((bytes[index++]&0xff)<<12);
579                                                         length += ((bytes[index++]&0xff)<<20);
580                                                         length += 0x204080;
581                                                 }
582                                         }
583                                         else {
584                                                 length &= 0x3f;
585                                                 length += ((bytes[index++]&0xff)<<5);
586                                                 length += ((bytes[index++]&0xff)<<13);
587                                                 length += 0x4080;
588                                         }
589                                 }
590                                 else {
591                                         length &= 0x7f;
592                                         length += ((bytes[index++]&0xff)<<6);
593                                         length += 0x80;
594                                 }
595                         }
596                         
597                         int i = 0;
598                         int target = length+index;
599                         while(index < target) {
600                                 int c = bytes[index++]&0xff;
601                                 if(c <= 0x7F) {
602                                         chars[i++] = (char)(c&0x7F);
603                                 } else if (c > 0x07FF) {
604                                         int c2 = bytes[index++]&0xff;
605                                         int c3 = bytes[index++]&0xff;
606                                         chars[i++] = (char)(((c&0xf)<<12) + ((c2&0x3f)<<6) + (c3&0x3f)); 
607                                 } else {
608                                         int c2 = bytes[index++]&0xff;
609                                         chars[i++] = (char)(((c&0x1f)<<6) + (c2&0x3f)); 
610                                 }
611                                 
612                         }
613                         
614                         return new String(chars, 0, i);
615                         
616                 }
617
618                 
619                 @Override
620                 public Object deserialize(byte[] data) throws IOException {
621                         return utf(data);
622                 }
623                 
624         }
625
626         static class STRING_BINDING extends StringBindingDefault {
627                 
628                 public static STRING_BINDING INSTANCE = new STRING_BINDING();
629                 
630                 public STRING_BINDING() {
631                         super(Datatypes.STRING);
632                 }
633                 
634                 @Override
635                 public Serializer serializer() throws RuntimeSerializerConstructionException {
636                         
637                         return STRING_SERIALIZER.INSTANCE;
638                         
639                 }
640                 
641                 @Override
642                 public boolean isInstance(Object obj) {
643                         return obj instanceof String;
644                 }
645                 
646         }
647         
648         static class BYTE_ARRAY_BINDING extends LongBindingDefault {
649                 
650                 public static BYTE_ARRAY_BINDING INSTANCE = new BYTE_ARRAY_BINDING();
651                 
652                 public BYTE_ARRAY_BINDING() {
653                         super(Datatypes.LONG);
654                 }
655                 
656                 @Override
657                 public Serializer serializer() throws RuntimeSerializerConstructionException {
658                         
659                         return BYTE_ARRAY_SERIALIZER.INSTANCE;
660                         
661                 }
662                 
663                 @Override
664                 public boolean isInstance(Object obj) {
665                         return obj instanceof byte[];
666                 }
667                 
668         }
669
670         static class LONG_ARRAY_BINDING extends LongBindingDefault {
671                 
672                 public static LONG_ARRAY_BINDING INSTANCE = new LONG_ARRAY_BINDING();
673                 
674                 public LONG_ARRAY_BINDING() {
675                         super(Datatypes.LONG);
676                 }
677                 
678                 @Override
679                 public Serializer serializer() throws RuntimeSerializerConstructionException {
680                         
681                         return LONG_ARRAY_SERIALIZER.INSTANCE;
682                         
683                 }
684                 
685         }
686
687         
688         static class TRANSFERABLE_GRAPH_BINDING extends LongBindingDefault {
689                 
690                 public static TRANSFERABLE_GRAPH_BINDING INSTANCE = new TRANSFERABLE_GRAPH_BINDING();
691                 
692                 public TRANSFERABLE_GRAPH_BINDING() {
693                         super(Datatypes.LONG);
694                 }
695                 
696                 @Override
697                 public Serializer serializer() throws RuntimeSerializerConstructionException {
698                         
699                         return TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE;
700                         
701                 }
702                 
703         }
704
705         public static Binding STRING = STRING_BINDING.INSTANCE;
706         public static Binding BYTE_ARRAY = BYTE_ARRAY_BINDING.INSTANCE;
707         public static Binding LONG_ARRAY = LONG_ARRAY_BINDING.INSTANCE;
708         public static Binding TRANSFERABLE_GRAPH = TRANSFERABLE_GRAPH_BINDING.INSTANCE;
709
710         public static void main(String[] args) {
711
712                 TransferableGraph1 tg = new TransferableGraph1(123,new Identity[] { 
713                                 new Identity(11, new Root("foo", "bar1")), 
714                                 new Identity(12, new External(21, "bar2")), 
715                                 new Identity(13, new Internal(22, "bar3")), 
716                                 new Identity(14, new Optional(23, "bar4")) },
717                                 new int[] { 1, 2, 3 },
718                                 new Value[] { new Value(31, new Variant(Bindings.INTEGER, 123)) });
719
720                 try {
721                         System.err.println(Arrays.toString(Bindings.getSerializerUnchecked(Bindings.getBinding(TransferableGraph1.class)).serialize(tg)));
722                         System.err.println(Arrays.toString(WriteBindings.TRANSFERABLE_GRAPH_SERIALIZER.INSTANCE.serialize(tg)));
723                 } catch (RuntimeSerializerConstructionException e) {
724                         // TODO Auto-generated catch block
725                         e.printStackTrace();
726                 } catch (IOException e) {
727                         // TODO Auto-generated catch block
728                         e.printStackTrace();
729                 } catch (BindingConstructionException e) {
730                         // TODO Auto-generated catch block
731                         e.printStackTrace();
732                 }
733                 
734         }
735         
736 }