Streaming serialization of values, debugger for corrupted values
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / streaming / DataSerializationDebugger.java
1 package org.simantics.databoard.streaming;
2
3 import java.io.IOException;
4 import java.io.PrintStream;
5
6 import org.simantics.databoard.Bindings;
7 import org.simantics.databoard.serialization.Serializer;
8 import org.simantics.databoard.type.ArrayType;
9 import org.simantics.databoard.type.BooleanType;
10 import org.simantics.databoard.type.ByteType;
11 import org.simantics.databoard.type.Component;
12 import org.simantics.databoard.type.Datatype;
13 import org.simantics.databoard.type.Datatype.Visitor;
14 import org.simantics.databoard.type.DoubleType;
15 import org.simantics.databoard.type.FloatType;
16 import org.simantics.databoard.type.IntegerType;
17 import org.simantics.databoard.type.LongType;
18 import org.simantics.databoard.type.MapType;
19 import org.simantics.databoard.type.OptionalType;
20 import org.simantics.databoard.type.RecordType;
21 import org.simantics.databoard.type.StringType;
22 import org.simantics.databoard.type.UnionType;
23 import org.simantics.databoard.type.VariantType;
24 import org.simantics.databoard.util.Range;
25 import org.simantics.databoard.util.binary.Endian;
26
27 /**
28  * Utility for debugging corrupted values.
29  */
30 public class DataSerializationDebugger {
31     DataReader in;
32     PrintStream out;
33     int indentation;
34     
35     private void indentation() {
36         for(int i=0;i<indentation;++i)
37             out.print("  ");
38     }
39     
40     /**
41      * Constructs the debugger that reads the given stream and prints the value
42      * content to given print stream.
43      */
44     public DataSerializationDebugger(DataReader in, PrintStream out) {
45         this.in = in;
46         this.out = out;
47     }
48     
49     /**
50      * Expects value of given datatype in the input stream.
51      */
52     public void expect(Datatype datatype) throws IOException {
53         if(datatype instanceof BooleanType)
54             expectBoolean();
55         else if(datatype instanceof ByteType)
56             expectByte();
57         else if(datatype instanceof IntegerType)
58             expectInteger();
59         else if(datatype instanceof LongType)
60             expectLong();
61         else if(datatype instanceof FloatType)
62             expectFloat();
63         else if(datatype instanceof DoubleType)
64             expectDouble();
65         else if(datatype instanceof StringType)
66             expectString();
67         else if(datatype instanceof RecordType)
68             expectRecord((RecordType)datatype);
69         else if(datatype instanceof ArrayType)
70             expectArray((ArrayType)datatype);
71         else if(datatype instanceof MapType)
72             expectMap((MapType)datatype);
73         else if(datatype instanceof OptionalType)
74             expectOptional((OptionalType)datatype);
75         else if(datatype instanceof UnionType)
76             expectUnion((UnionType)datatype);
77         else if(datatype instanceof VariantType)
78             expectVariant();        
79     }
80     
81     private void expectVariant() throws IOException {
82         out.print("Variant:");
83         Datatype datatype = in.readDatatype();
84         out.println(" " + datatype);
85         ++indentation;
86         indentation();
87         expect(datatype);
88         --indentation;        
89     }
90
91     private void expectUnion(UnionType datatype) throws IOException {
92         out.print("Union");
93         int tag = in.readUnionTag(datatype.getComponentCount());
94         Component component = datatype.getComponent(tag);
95         out.print("(" + component.name + "): ");
96         expect(component.type);
97     }
98
99     private void expectOptional(OptionalType datatype) throws IOException {
100         out.print("Optional: ");
101         if(in.beginOptional()) {
102             expect(datatype.componentType);
103         }
104         else
105             out.println("null");
106     }
107
108     private void expectMap(MapType datatype) throws IOException {
109         out.print("Map");
110         int length = in.beginMap();
111         out.println("(" + length + "):");
112         ++indentation;
113         for(int i=0;i<length;++i) {
114             indentation();
115             out.print(i+"-key: ");
116             expect(datatype.keyType);
117             indentation();
118             out.print(i+"-value: ");
119             expect(datatype.valueType);
120         }
121         --indentation;
122     }
123     
124     private static final Integer I1 = 1;
125     private static final Integer I4 = 4;
126     private static final Integer I8 = 8;
127     
128     private static int getFixedLength(ArrayType b) {
129         Range length = b.getLength();
130         return length.getLower().getValue().intValue();
131     }
132     
133     private static Visitor<Integer> FIXED_SIZE = new Visitor<Integer>() {
134
135         @Override
136         public Integer visit(ArrayType b) {
137             Range length = b.getLength();
138             if(length == null
139                     || length.getLower().getValue()==null
140                     || !length.getLower().equals(length.getUpper()))
141                 return null;
142             
143             int fixedLength = length.getLower().getValue().intValue();
144             
145             Integer componentLength = b.componentType.accept(this);
146             if(componentLength == null)
147                 return null;
148             
149             return fixedLength * componentLength;
150         }
151
152         @Override
153         public Integer visit(BooleanType b) {
154             return I1;
155         }
156
157         @Override
158         public Integer visit(DoubleType b) {
159             return I8;
160         }
161
162         @Override
163         public Integer visit(FloatType b) {
164             return I4;
165         }
166
167         @Override
168         public Integer visit(IntegerType b) {
169             return I4;
170         }
171
172         @Override
173         public Integer visit(ByteType b) {
174             return I1;
175         }
176
177         @Override
178         public Integer visit(LongType b) {
179             return I8;
180         }
181
182         @Override
183         public Integer visit(OptionalType b) {
184             return null;
185         }
186
187         @Override
188         public Integer visit(RecordType b) {
189             if(b.isReferable())
190                 return null;
191             int sum = 0;
192             for(Component component : b.getComponents()) {
193                 Integer componentSize = component.type.accept(this);
194                 if(componentSize == null)
195                     return null;
196                 sum += componentSize;
197             }
198             return sum;
199         }
200
201         @Override
202         public Integer visit(StringType b) {
203             return null;
204         }
205
206         @Override
207         public Integer visit(UnionType b) {
208             Integer commonComponentSize = null;
209             for(Component component : b.components) {
210                 Integer componentSize = component.type.accept(this);
211                 if(componentSize == null)
212                     return null;
213                 if(commonComponentSize == null)
214                     commonComponentSize = componentSize;
215                 else if(!commonComponentSize.equals(componentSize))
216                     return null;
217             }
218             if(commonComponentSize == null)
219                 return 0;
220             return commonComponentSize + Endian.getUIntLength(b.components.length-1);
221         }
222
223         @Override
224         public Integer visit(VariantType b) {
225             return null;
226         }
227
228         @Override
229         public Integer visit(MapType b) {
230             return null;
231         }
232         
233     };
234
235     private void expectArray(ArrayType datatype) throws IOException {
236         out.print("Array");
237         int length;
238         if(datatype.accept(FIXED_SIZE) == null)
239             length = in.beginVariableLengthArray();
240         else
241             length = getFixedLength(datatype);
242         out.println("(" + length + "):");
243         ++indentation;
244         for(int i=0;i<length;++i) {
245             indentation();
246             out.print(i);
247             out.print(": ");
248             expect(datatype.componentType);
249         }
250         --indentation;
251     }
252
253     private void expectRecord(RecordType datatype) throws IOException {
254         out.print("Record:");
255         if(datatype.isReferable()) {
256             int ref = in.readReferableRecordReference();
257             if(ref != 0) {
258                 out.println(" old " + ref);
259                 return;
260             }
261             else {
262                 out.println(" new");
263             }
264         }
265         else
266             out.println();
267         ++indentation;
268         for(Component component : datatype.getComponents()) {
269             indentation();
270             out.print(component.name);
271             out.print(": ");
272             expect(component.type);
273         }
274         --indentation;
275     }
276
277     private void expectString() throws IOException {
278         out.print("String");
279         int length = in.readStringLength();
280         out.print("(" + length + "): ");
281         out.println(in.readStringContent(length));
282     }
283
284     private void expectDouble() throws IOException {
285         out.print("Double: ");
286         out.println(in.readDouble());
287     }
288
289     private void expectFloat() throws IOException {
290         out.print("Float: ");
291         out.println(in.readFloat());
292     }
293
294     private void expectLong() throws IOException {
295         out.print("Long: ");
296         out.println(in.readLong());
297     }
298
299     private void expectInteger() throws IOException {
300         out.print("Integer: ");
301         out.println(in.readInteger());
302     }
303
304     private void expectByte() throws IOException {
305         out.print("Byte: ");
306         out.println(in.readByte());
307     }
308
309     private void expectBoolean() throws IOException {
310         out.print("Boolean: ");
311         out.println(in.readBoolean());
312     }
313 }