I've created a Kaitai Struct .ksy
for two very similar Digilent log file formats. The second format (openlogger
) is an extension of the first (openscope
) with two additional fields in the struct. The scope is basically a single-channel logger; the additional logger fields describe the number of active channels (a u1
, max 8) and the channel to sample order map (a u1 x 8
).
I'm attempting to harmonise the interface for the two formats by synthesising always-present fields for the num_channels
and channel_map
; this has worked fine for the num_channels
instance. However I can't figure out how to create a suitable value for the channel map, the .ksy
below reports an error:
/types/body/types/header/instances/channel_order/value: can't combine output types: ArrayType(Int1Type(false)) vs CalcBytesType
I can't figure out how I can represent the if_false
part ([0]
) as an ArrayType.
Is there a better way to approach this?
meta:
id: dlog
file-extension: dlog
seq:
- id: endianness
type: u1
doc: 0 - little endian 1 - big endian
- id: body
type: body
types:
body:
meta:
endian:
switch-on: _root.endianness
cases:
0: le
1: be
seq:
- id: header
type: header
instances:
data:
pos: header.start_of_data
type: data
types:
header:
seq:
- id: sample_size
type: u1
- id: header_size
type: u2
- id: start_of_data
type: u2
- id: dlog_format
type: u2
enum: dlog_formats
- id: dlog_version
type: u4
- id: voltage_units
type: u8
- id: stop_reason
type: u4
enum: stop_reasons
#...
- id: num_openlogger_channels
type: u4
if: dlog_format == dlog_formats::openlogger
doc: number of channels per sample
- id: openlogger_channel_map
type: u1
repeat: expr
repeat-expr: 8
if: dlog_format == dlog_formats::openlogger
doc: channel order
instances:
num_channels:
value: 'dlog_format == dlog_formats::openlogger ? num_openlogger_channels : 1'
channel_map:
value: 'dlog_format == dlog_formats::openlogger ? openlogger_channel_map : [0]'
data:
seq:
- id: samples
type: sample
repeat: eos
types:
sample:
seq:
- id: channel
type:
switch-on: _root.body.header.sample_size
cases:
1: s1
2: s2
4: s4
repeat: expr
repeat-expr: _root.body.header.num_channels
enums:
dlog_formats:
1: openscope
3: openlogger
stop_reasons:
0: normal
1: forced
2: error
3: overflow
4: unknown
Literal [0]
gets parsed as byte array: this is default behavior that people typically depend on, so heuristic array literal parser treats all arrays where values fit the pattern of being 0..255 as byte arrays, not true arrays.
You can still do a true array literal if you want to by forcing it so with a typecast:
[0].as<u1[]>
Note that it will likely cause problems with C++98, which lacks one-line initializers for true arrays (std::vector).