-
Notifications
You must be signed in to change notification settings - Fork 1
Quickstart
This library exposes MessagePack utilities with OOP via a single module called messagepack
. This module relies upon iso_fortran_env
and ieee_arithmetic
. Interaction with the library is done with the msgpack
class.
program test
use messagepack
implicit none
class(msgpack), allocatable :: mp
mp = msgpack()
end program
An abstract base class called mp_value_type
is used to represent MessagePack data. A pointer type called mp_value_type_ptr
is used to support the "container-like" formats that contain other MessagePack values. The following derived types are exposed to the user:
Derived Type | MessagePack Format Family | Associated Fortran Types |
---|---|---|
mp_nil_type | nil | - |
mp_bool_type | bool | logical |
mp_int_type | int | integer(kind=int64) |
mp_float_type | float | real(kind=real32), real(kind=real64) |
mp_str_type | str | character(:) |
mp_bin_type | bin | byte, dimension(:) |
mp_arr_type | array | mp_value_type_ptr |
mp_map_type | map | mp_value_type_ptr, mp_value_type_ptr |
mp_ext_type | ext | byte, dimension(:) |
mp_timestamp_type | ext built-in | - |
Data that is unpacked with be stored with these classes, and data that is to be packed must be assembled with these classes.
msgpack
expects that serialized data will be passed into it as a byte
array. There is one note here that users need to keep in mind: fortran does not support unsigned integers, and large portions of the MessagePack spec utilize unsigned integers. We'll get back to that later, but when printing serialized messagepack data to the console, use the provided print_bytes_as_hex
function to print the data as unsigned hex values.
subroutine print_bytes_as_hex(bytes, addhexmark)
! prints a buffer of bytes as the unsigned hex version
! @param[in] bytes - byte buffer to print
! @param[in] addhexmark - If true, print with 0x prepended
byte, dimension(:), allocatable, intent(in) :: bytes
logical, intent(in) :: addhexmark
Produces something like this:
[ 0x85 0xA3 0x72 0x61 0x74 0x05 ...
msgpack
attemps to handle this under the hood, but in certain cases requires the user to intervene.
Unpacking messagepack from a known set of data and print it to the console.
program test
use messagepack
intrinsic none
class(msgpack), allocatable :: mp
class(mp_value_type), allocatable :: mpv
bytes, dimension(:), allocatable :: buffer
! known messagepack
allocate(buffer(19))
buffer = (/-127,-93,109,115,103,-109,-91,104,101,108,108,111,-91,119,111,114,108,100,3/)
call print_bytes_as_hex(buffer, .true.)
mp = msgpack()
call mp%unpack(buffer, mpv)
if (mp%failed()) then
print *, mp%error_message
stop 1
endif()
call mp%print_value(mpv) ! pretty print the messagepack object to console
end program
this will output to the console:
[ 0x81 0xA3 0x6D 0x73 0x67 0x93 0xA5 0x68 0x65 0x6C 0x6C 0x6F 0xA5 0x77 0x6F 0x72 0x6C 0x64 0x03 ]
{
"msg" => ["hello", "world", 3, ] ,
},
Example: assemble an array of various values and serialize it. The class used to support this is mp_arr_type
:
type, extends(mp_value_type) :: mp_arr_type
class(mp_value_type_ptr), allocatable, dimension(:) :: value
...
This class uses the mp_value_type_ptr
class, which is defined as so:
type :: mp_value_type_ptr
class(mp_value_type), allocatable :: obj
end type
The constructor for mp_arr_type
takes in an integer parameter representing the number of values that it needs to contain. To see this in action, follow the example program below:
program test
use iso_fortran_env
use messagepack
intrinsic none
class(msgpack), allocatable :: mp
class(mp_arr_type), allocatable :: mp_arr
bytes, dimension(:), allocatable :: buffer
mp = msgpack()
mp_arr = mp_arr_type(5) ! an array of 5 elements
mp_arr%value(1)%obj = mp_bool_type(.true.)
mp_arr%value(2)%obj = mp_str_type("hello world")
mp_arr%value(3)%obj = mp_int_type(3500)
mp_arr%value(4)%obj = mp_nil_type()
mp_arr%value(5)%obj = mp_int_type(-4)
call mp%pack_alloc(mp_arr, buffer)
if (mp%failed()) then
print *, mp%error_message
stop 1
end if
call print_bytes_as_hex(buffer, .true.)
end program
This program will (should) output the following to the console:
[ 0x95 0xC3 0xAB 0x68 0x65 0x6C 0x6C 0x6F 0x20 0x77 0x6F 0x72 0x6C 0x64 0xCD 0x0D 0xAC 0xC0 0xF5 ]
Pass this into a free messagepack to json convert (like this one to try this out yourself!
Fortran does not natively support unsigned integers. The library has utilities to deal with this and make the conversion largely transparent, TODO
...