Public Class B4XSerializator
Private Const T_NULL As Byte = 0, T_STRING As Byte = 1, T_SHORT As Byte = 2, T_INT As Byte = 3, T_LONG As Byte = 4, T_FLOAT As Byte = 5, T_DOUBLE As Byte = 6, T_BOOLEAN As Byte = 7, T_BYTE As Byte = 10, T_CHAR As Byte = 14, T_MAP As Byte = 20, T_LIST As Byte = 21, T_NSARRAY As Byte = 22, T_NSDATA As Byte = 23, T_TYPE As Byte = 24
Private br As BinaryReader
Private bw As BinaryWriter
Private ReadOnly utf8 As UTF8Encoding
Public Sub New()
utf8 = New UTF8Encoding(False)
End Sub
Public Function ConvertBytesToObject(ByVal Bytes As Byte()) As Object
Using inf As InflaterInputStream = New InflaterInputStream(New MemoryStream(Bytes))
br = New BinaryReader(inf)
Dim ret As Object = readObject()
Return ret
End Using
End Function
Public Function ConvertObjectToBytes(ByVal Object As Object) As Byte()
Dim ms As MemoryStream = New MemoryStream()
Using def As DeflaterOutputStream = New DeflaterOutputStream(ms)
bw = New BinaryWriter(def)
writeObject(Object)
End Using
Return ms.ToArray()
End Function
Private Sub writeObject(ByVal o As Object)
If o Is Nothing Then
writeByte(T_NULL)
ElseIf TypeOf o Is Integer Then
writeByte(T_INT)
writeInt(CInt(o))
ElseIf TypeOf o Is Double Then
writeByte(T_DOUBLE)
bw.Write(CDbl(o))
ElseIf TypeOf o Is Single Then
writeByte(T_FLOAT)
bw.Write(CSng(o))
ElseIf TypeOf o Is Long Then
writeByte(T_LONG)
bw.Write(CLng(o))
ElseIf TypeOf o Is Byte Then
writeByte(T_BYTE)
bw.Write(CByte(o))
ElseIf TypeOf o Is Short Then
writeByte(T_SHORT)
bw.Write(CShort(o))
ElseIf TypeOf o Is Char Then
writeByte(T_CHAR)
bw.Write(CShort(CChar(o)))
ElseIf TypeOf o Is Boolean Then
writeByte(T_BOOLEAN)
writeByte(CByte((If(CBool(o), 1, 0))))
ElseIf TypeOf o Is String Then
Dim temp As Byte() = utf8.GetBytes(CStr(o))
writeByte(T_STRING)
writeInt(temp.Length)
bw.Write(temp, 0, temp.Length)
ElseIf TypeOf o Is List(Of Object) Then
writeByte(T_LIST)
writeList(CType(o, List(Of Object)))
ElseIf TypeOf o Is Dictionary(Of Object, Object) Then
writeByte(T_MAP)
writeMap(CType(o, Dictionary(Of Object, Object)))
ElseIf o.[GetType]().IsArray Then
If TypeOf o Is Byte() Then
writeByte(T_NSDATA)
Dim b As Byte() = CType(o, Byte())
writeInt(b.Length)
bw.Write(b, 0, b.Length)
ElseIf TypeOf o Is Object() Then
writeByte(T_NSARRAY)
writeList(New List(Of Object)(CType(o, Object())))
Else
Throw New Exception("Only arrays of bytes or objects are supported.")
End If
ElseIf TypeOf o Is B4XType Then
writeByte(T_TYPE)
writeType(CType(o, B4XType))
Else
Throw New Exception("Type not supported: " & o.[GetType]())
End If
End Sub
Private Sub writeMap(ByVal m As Dictionary(Of Object, Object))
writeInt(m.Count)
For Each kvp As KeyValuePair(Of Object, Object) In m
writeObject(kvp.Key)
writeObject(kvp.Value)
Next
End Sub
Private Sub writeList(ByVal list As List(Of Object))
writeInt(list.Count)
For Each o As Object In list
writeObject(o)
Next
End Sub
Private Function readObject() As Object
Dim t As Byte = br.ReadByte()
Dim len As Integer
Dim b As Byte()
Select Case t
Case T_NULL
Return Nothing
Case T_INT
Return readInt()
Case T_SHORT
Return readShort()
Case T_LONG
Return br.ReadInt64()
Case T_FLOAT
Return br.ReadSingle()
Case T_DOUBLE
Return br.ReadDouble()
Case T_BOOLEAN
Return br.ReadByte() = 1
Case T_BYTE
Return br.ReadByte()
Case T_STRING
len = readInt()
b = br.ReadBytes(len)
Return utf8.GetString(b)
Case T_CHAR
Return ChrW(readShort())
Case T_LIST
Return readList()
Case T_MAP
Return readMap()
Case T_NSDATA
len = readInt()
Return br.ReadBytes(len)
Case T_NSARRAY
Dim list As List(Of Object) = readList()
Return list.ToArray()
Case T_TYPE
Return readType()
Case Else
Throw New Exception("Unsupported type: " & t)
End Select
End Function
Private Sub writeByte(ByVal b As Byte)
bw.Write(b)
End Sub
Private Sub writeInt(ByVal i As Integer)
bw.Write(i)
End Sub
Private Function readList() As List(Of Object)
Dim len As Integer = readInt()
Dim arr As List(Of Object) = New List(Of Object)(len)
For i As Integer = 0 To len - 1
arr.Add(readObject())
Next
Return arr
End Function
Private Function readMap() As Dictionary(Of Object, Object)
Dim len As Integer = readInt()
Dim mm As Dictionary(Of Object, Object) = New Dictionary(Of Object, Object)()
For i As Integer = 0 To len - 1
mm(readObject()) = readObject()
Next
Return mm
End Function
Private Function readInt() As Integer
Return br.ReadInt32()
End Function
Private Function readShort() As Short
Return br.ReadInt16()
End Function
Private Function readType() As Object
Dim cls As String = CStr(readObject())
Dim data = readMap()
Return New B4XType(cls, data)
End Function
Private Sub writeType(ByVal t As B4XType)
writeObject("_" & t.ClassName)
writeMap(t.Fields)
End Sub
End Class