F # различимые объединения пользовательских типов; уважая пользовательские атрибуты - PullRequest
0 голосов
/ 07 мая 2018

Я пытаюсь использовать различающееся объединение для представления некоторых пользовательских типов; однако типы, которые составляют случаи DU, содержат пользовательские атрибуты, которые не соблюдаются DU. Например, я выполняю маршалинг заголовка файла, который содержит несколько необязательных полей в расширении заголовка, в зависимости от программы, написавшей файл. Поля структуры также имеют собственный атрибут, который позволяет маршалировать поля структуры с правильным порядком байтов, заданным [<endian>]. Учитывая общую базовую структуру заголовка,

[<Struct; StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)>]
type generic_header = {
    [<endian>] header_size: int16
    [<MarshalAs(UnmanagedType.ByValTStr, SizeConst = 55)>]
    file_version: string
    [<endian>] file_size: int16
    header_extension: bool
    }

и расширение заголовка с полями +/- в зависимости от программы, с помощью которой был создан заголовок,

[<Struct; StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)>]
    type header_extension = {
    [<endian>] extended_field_1: int16
    [<endian>] extended_field_2: float32
    [<MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)>]
    extended_array: byte[]
    [<endian>] extended_field_3: int16
    ...
    }

возможно ли иметь распознаваемое объединение (или даже другую структуру), которое может содержать эти типы, и использовать тип DU для объединения потока в содержащиеся структуры? Если я марширую каждый тип отдельно, тогда атрибут endian будет соблюдаться, и я получу правильные данные.

Что я пробовал до сих пор:

[<Struct>]
type file_header =
    | Header of Header: generic_header
    | Extension of Extension: header_extension

или

[<Struct>] type file_header = | Header of generic_header * header_extension

или некоторая логика регистра для выполнения одного из следующих действий на основе значения первого поля generic_header:

[<Struct>] type file_header_from_prog_1 = | Header of generic_header * prog_1_header_extension
[<Struct>] type file_header_from_prog_2 = | Header of generic_header * prog_2_header_extension
[<Struct>] type file_header_from_prog_3 = | Header of generic_header * prog_3_header_extension

Однако, когда я использую тип file_header для маршалинга, он правильно маршалирует правильное число байтов в структуре, но это происходит без учета тега endian на полях.

Моя цель - создать «супертип», который будет содержать все возможные расширения и типы, которые могут составлять заголовок файла, который я маршалирую, чтобы мне не приходилось маршалировать каждый тип по отдельности. Есть ли способ сделать это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...