]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/streaming/DataSerializationDebugger.java
Streaming serialization of values, debugger for corrupted values
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / streaming / DataSerializationDebugger.java
diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/streaming/DataSerializationDebugger.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/streaming/DataSerializationDebugger.java
new file mode 100644 (file)
index 0000000..df64db2
--- /dev/null
@@ -0,0 +1,313 @@
+package org.simantics.databoard.streaming;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.type.ArrayType;
+import org.simantics.databoard.type.BooleanType;
+import org.simantics.databoard.type.ByteType;
+import org.simantics.databoard.type.Component;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.type.Datatype.Visitor;
+import org.simantics.databoard.type.DoubleType;
+import org.simantics.databoard.type.FloatType;
+import org.simantics.databoard.type.IntegerType;
+import org.simantics.databoard.type.LongType;
+import org.simantics.databoard.type.MapType;
+import org.simantics.databoard.type.OptionalType;
+import org.simantics.databoard.type.RecordType;
+import org.simantics.databoard.type.StringType;
+import org.simantics.databoard.type.UnionType;
+import org.simantics.databoard.type.VariantType;
+import org.simantics.databoard.util.Range;
+import org.simantics.databoard.util.binary.Endian;
+
+/**
+ * Utility for debugging corrupted values.
+ */
+public class DataSerializationDebugger {
+    DataReader in;
+    PrintStream out;
+    int indentation;
+    
+    private void indentation() {
+        for(int i=0;i<indentation;++i)
+            out.print("  ");
+    }
+    
+    /**
+     * Constructs the debugger that reads the given stream and prints the value
+     * content to given print stream.
+     */
+    public DataSerializationDebugger(DataReader in, PrintStream out) {
+        this.in = in;
+        this.out = out;
+    }
+    
+    /**
+     * Expects value of given datatype in the input stream.
+     */
+    public void expect(Datatype datatype) throws IOException {
+        if(datatype instanceof BooleanType)
+            expectBoolean();
+        else if(datatype instanceof ByteType)
+            expectByte();
+        else if(datatype instanceof IntegerType)
+            expectInteger();
+        else if(datatype instanceof LongType)
+            expectLong();
+        else if(datatype instanceof FloatType)
+            expectFloat();
+        else if(datatype instanceof DoubleType)
+            expectDouble();
+        else if(datatype instanceof StringType)
+            expectString();
+        else if(datatype instanceof RecordType)
+            expectRecord((RecordType)datatype);
+        else if(datatype instanceof ArrayType)
+            expectArray((ArrayType)datatype);
+        else if(datatype instanceof MapType)
+            expectMap((MapType)datatype);
+        else if(datatype instanceof OptionalType)
+            expectOptional((OptionalType)datatype);
+        else if(datatype instanceof UnionType)
+            expectUnion((UnionType)datatype);
+        else if(datatype instanceof VariantType)
+            expectVariant();        
+    }
+    
+    private void expectVariant() throws IOException {
+        out.print("Variant:");
+        Datatype datatype = in.readDatatype();
+        out.println(" " + datatype);
+        ++indentation;
+        indentation();
+        expect(datatype);
+        --indentation;        
+    }
+
+    private void expectUnion(UnionType datatype) throws IOException {
+        out.print("Union");
+        int tag = in.readUnionTag(datatype.getComponentCount());
+        Component component = datatype.getComponent(tag);
+        out.print("(" + component.name + "): ");
+        expect(component.type);
+    }
+
+    private void expectOptional(OptionalType datatype) throws IOException {
+        out.print("Optional: ");
+        if(in.beginOptional()) {
+            expect(datatype.componentType);
+        }
+        else
+            out.println("null");
+    }
+
+    private void expectMap(MapType datatype) throws IOException {
+        out.print("Map");
+        int length = in.beginMap();
+        out.println("(" + length + "):");
+        ++indentation;
+        for(int i=0;i<length;++i) {
+            indentation();
+            out.print(i+"-key: ");
+            expect(datatype.keyType);
+            indentation();
+            out.print(i+"-value: ");
+            expect(datatype.valueType);
+        }
+        --indentation;
+    }
+    
+    private static final Integer I1 = 1;
+    private static final Integer I4 = 4;
+    private static final Integer I8 = 8;
+    
+    private static int getFixedLength(ArrayType b) {
+        Range length = b.getLength();
+        return length.getLower().getValue().intValue();
+    }
+    
+    private static Visitor<Integer> FIXED_SIZE = new Visitor<Integer>() {
+
+        @Override
+        public Integer visit(ArrayType b) {
+            Range length = b.getLength();
+            if(length == null
+                    || length.getLower().getValue()==null
+                    || !length.getLower().equals(length.getUpper()))
+                return null;
+            
+            int fixedLength = length.getLower().getValue().intValue();
+            
+            Integer componentLength = b.componentType.accept(this);
+            if(componentLength == null)
+                return null;
+            
+            return fixedLength * componentLength;
+        }
+
+        @Override
+        public Integer visit(BooleanType b) {
+            return I1;
+        }
+
+        @Override
+        public Integer visit(DoubleType b) {
+            return I8;
+        }
+
+        @Override
+        public Integer visit(FloatType b) {
+            return I4;
+        }
+
+        @Override
+        public Integer visit(IntegerType b) {
+            return I4;
+        }
+
+        @Override
+        public Integer visit(ByteType b) {
+            return I1;
+        }
+
+        @Override
+        public Integer visit(LongType b) {
+            return I8;
+        }
+
+        @Override
+        public Integer visit(OptionalType b) {
+            return null;
+        }
+
+        @Override
+        public Integer visit(RecordType b) {
+            if(b.isReferable())
+                return null;
+            int sum = 0;
+            for(Component component : b.getComponents()) {
+                Integer componentSize = component.type.accept(this);
+                if(componentSize == null)
+                    return null;
+                sum += componentSize;
+            }
+            return sum;
+        }
+
+        @Override
+        public Integer visit(StringType b) {
+            return null;
+        }
+
+        @Override
+        public Integer visit(UnionType b) {
+            Integer commonComponentSize = null;
+            for(Component component : b.components) {
+                Integer componentSize = component.type.accept(this);
+                if(componentSize == null)
+                    return null;
+                if(commonComponentSize == null)
+                    commonComponentSize = componentSize;
+                else if(!commonComponentSize.equals(componentSize))
+                    return null;
+            }
+            if(commonComponentSize == null)
+                return 0;
+            return commonComponentSize + Endian.getUIntLength(b.components.length-1);
+        }
+
+        @Override
+        public Integer visit(VariantType b) {
+            return null;
+        }
+
+        @Override
+        public Integer visit(MapType b) {
+            return null;
+        }
+        
+    };
+
+    private void expectArray(ArrayType datatype) throws IOException {
+        out.print("Array");
+        int length;
+        if(datatype.accept(FIXED_SIZE) == null)
+            length = in.beginVariableLengthArray();
+        else
+            length = getFixedLength(datatype);
+        out.println("(" + length + "):");
+        ++indentation;
+        for(int i=0;i<length;++i) {
+            indentation();
+            out.print(i);
+            out.print(": ");
+            expect(datatype.componentType);
+        }
+        --indentation;
+    }
+
+    private void expectRecord(RecordType datatype) throws IOException {
+        out.print("Record:");
+        if(datatype.isReferable()) {
+            int ref = in.readReferableRecordReference();
+            if(ref != 0) {
+                out.println(" old " + ref);
+                return;
+            }
+            else {
+                out.println(" new");
+            }
+        }
+        else
+            out.println();
+        ++indentation;
+        for(Component component : datatype.getComponents()) {
+            indentation();
+            out.print(component.name);
+            out.print(": ");
+            expect(component.type);
+        }
+        --indentation;
+    }
+
+    private void expectString() throws IOException {
+        out.print("String");
+        int length = in.readStringLength();
+        out.print("(" + length + "): ");
+        out.println(in.readStringContent(length));
+    }
+
+    private void expectDouble() throws IOException {
+        out.print("Double: ");
+        out.println(in.readDouble());
+    }
+
+    private void expectFloat() throws IOException {
+        out.print("Float: ");
+        out.println(in.readFloat());
+    }
+
+    private void expectLong() throws IOException {
+        out.print("Long: ");
+        out.println(in.readLong());
+    }
+
+    private void expectInteger() throws IOException {
+        out.print("Integer: ");
+        out.println(in.readInteger());
+    }
+
+    private void expectByte() throws IOException {
+        out.print("Byte: ");
+        out.println(in.readByte());
+    }
+
+    private void expectBoolean() throws IOException {
+        out.print("Boolean: ");
+        out.println(in.readBoolean());
+    }
+}