Serializable::inspect
to show more useful information
serialization :: serialization_core
Abstract services to serialize Nit objects to different formatscore :: union_find
union–find algorithm using an efficient disjoint-set data structure
# Low-level read MessagePack format from `Reader` streams
module read
import serialization
private import binary
import ext
redef class Reader
# Read the next MessagePack object and return it as a simple Nit object
#
# The return value is composed of:
# * the simple types `null`, `Bool`, `Int`, `Float`, `String` and `Bytes`,
# * collections of simple Nit objects `Array[nullable Serializable]`
# and `Map[nullable Serializable, nullable Serializable]`,
# * and `MsgPackExt` for custom MessagePack *ext* data.
#
# This method reads plain MessagePack data, as written by `MsgPackSerializer`
# when `plain_msgpack == true`. To deserialize full Nit objects from
# MessagePack with metadata use `Reader::deserialize_msgpack`.
fun read_msgpack: nullable Serializable
do
if last_error != null then return 0
var typ = read_byte
if typ < 0 then
# Error, return default `null`
return null
else if typ & 0b1000_0000 == 0 or typ & 0b1110_0000 == 0b1110_0000 then
# fixint
var bytes = new Bytes.with_capacity(1)
bytes.add typ
return bytes.to_i(signed=true)
else if typ & 0b1111_0000 == 0b1000_0000 then
# fixmap
var len = typ & 0b0000_1111
return read_msgpack_map_data(len.to_i)
else if typ & 0b1111_0000 == 0b1001_0000 then
# fixarray
var len = typ & 0b0000_1111
return read_msgpack_array_data(len.to_i)
else if typ & 0b1110_0000 == 0b1010_0000 then
# fixstr
var len = typ & 0b0001_1111
return read_bytes(len.to_i).to_s
else if typ == 0xC0 then
return null
else if typ == 0xC2 then
return false
else if typ == 0xC3 then
return true
else if typ >= 0xCC and typ <= 0xCF then
# uint8, 16, 32 and 64
var len = 1 << (typ - 0xCC)
return read_bytes(len).to_i
else if typ >= 0xD0 and typ <= 0xD3 then
# int8, 16, 32 and 64
var len = 1 << (typ - 0xD0)
return read_bytes(len).to_i(true)
else if typ == 0xCA then
return read_float
else if typ == 0xCB then
return read_double
else if typ >= 0xD9 and typ <= 0xDB then
# str8, 16 and 32
var len_ln = 1 << (typ - 0xD9)
var bf = read_bytes(len_ln)
var len = bf.to_i
if len < 0 then return null
var rd_buf = read_bytes(len)
if rd_buf.length != len then
# Bad formatted message.
return null
end
return rd_buf.to_s
else if typ >= 0xC4 and typ <= 0xC6 then
# bin8, 16 or 32
var len_ln = 1 << (typ - 0xC4)
var bf = read_bytes(len_ln)
var len = bf.to_i
if len < 0 then return null
var rd_buf = read_bytes(len)
if rd_buf.length != len then
# Bad formatted message.
return null
end
return rd_buf
else if typ == 0xDC or typ == 0xDD then
# array16 and array32
var len_ln = 2 << (typ - 0xDC)
var lenbuf = read_bytes(len_ln)
return read_msgpack_array_data(lenbuf.to_i)
else if typ == 0xDE or typ == 0xDF then
# map16 and map32
var len_ln = 2 << (typ - 0xDE)
var lenbuf = read_bytes(len_ln)
return read_msgpack_map_data(lenbuf.to_i)
else if typ == 0xD4 then
# fixext1
return read_msgpack_fixext_data(1)
else if typ == 0xD5 then
# fixext2
return read_msgpack_fixext_data(2)
else if typ == 0xD6 then
# fixext4
return read_msgpack_fixext_data(4)
else if typ == 0xD7 then
# fixext8
return read_msgpack_fixext_data(8)
else if typ == 0xD8 then
# fixext16
return read_msgpack_fixext_data(16)
else if typ == 0xC7 then
# ext1
return read_msgpack_ext_data(1)
else if typ == 0xC8 then
# ext2
return read_msgpack_ext_data(2)
else if typ == 0xC9 then
# ext4
return read_msgpack_ext_data(4)
end
print_error "MessagePack Warning: Found no match for typ {typ.to_base(16)} / 0b{typ.to_base(2)}"
return null
end
# Read the content of a map, `len` keys and values
private fun read_msgpack_map_data(len: Int): Map[nullable Serializable, nullable Serializable]
do
var map = new Map[nullable Serializable, nullable Serializable]
for i in [0..len.to_i[ do map[read_msgpack] = read_msgpack
return map
end
# Read the content of an array of `len` items
private fun read_msgpack_array_data(len: Int): Array[nullable Serializable]
do
return [for i in [0..len[ do read_msgpack]
end
# Read the content of a *fixext* of `len` bytes
#
# ~~~
# var reader = new BytesReader(b"\xC7\x03\x0A\x0B\x0C\x0D")
# var ext = reader.read_msgpack
# assert ext isa MsgPackExt
# assert ext.typ == 0x0a
# assert ext.data == b"\x0B\x0C\x0D"
# ~~~
private fun read_msgpack_fixext_data(len: Int): MsgPackExt
do
var exttyp = read_byte
if exttyp < 0 then exttyp = 0
var data = read_bytes(len)
return new MsgPackExt(exttyp, data)
end
# Read the content of a dynamic *ext* including the length on `len_len` bytes
private fun read_msgpack_ext_data(len_len: Int): MsgPackExt
do
var len = read_bytes(len_len).to_i
return read_msgpack_fixext_data(len)
end
end
lib/msgpack/read.nit:15,1--194,3