Проект Kaitai представил (http://kaitai.io/news/2016-11-09.html) новый релиз Kaitai Struct версии 0.5 (http://kaitai.io/news/2016-11-09.html), декларативного языка описания бинарных форматов и структур данных. Как и прежде, основная идея проекта заключается в том, что практически любой формат файла или структуру сетевого протокола можно описать на Kaitai Struct, составив исходный файл .ksy, который затем компилируется (с помощью прилагаемого компилятора ksc) в готовый парсер на любом из поддерживаемых языков программирования.
Основная сфера применения подобного решения - разбор всевозможных существующих (зачастую закрытых и проприетарных) форматов (офисных, мультимедийных и т.д.) и протоколов. Благодаря наличию продвинутых инструментов отладки и визуализации, Kaitai Struct нашел свое применение и в быстром реверс-инжиниринге неизвестных форматов, а также в digital forensics. Ряд организаций, занимающийся хранением исторических цифровых архивов, взяли Kaitai Struct на вооружение как стандарт описания форматов данных. Компилятор Kaitai Struct распространяется под лицензией GPLv3, большинство runtime - под MIT. Для желающих попробовать компилятор без установки подготовлен JavaScript-вариант (http://kaitai.io/repl/) компилятора KS с примерами.
Наиболее заметные изменения:- Поддержка новых целевых языков
- Полная поддержка целевого языка C++ (на базе STL), а также новые целевые языки PHP и Perl:
- Вывод описаний форматов в виде наглядных человеко-читаемых схем (через GraphViz). Подборка примеров визуализаций доступна в галерее (http://imgur.com/a/LWOGq);- Многочисленные доработки и проверки для полноценной поддержки как Python 2, так и Python 3.
- Как и раньше, кроме новых языков, все еще поддерживаются C#, Java, JavaScript, Python, Ruby.
- Новые инструменты для разработки, отладки и визуализации
- Консольный визуализатор ksv обновлен и теперь работает не только на UNIX-консолях (Linux, *BSD, OS X), но и под Windows:
- Появился экспериментальный GUI-визуализатор (https://github.com/kaitai-io/kaitai_struct_gui) на Java/Swing:- Начата разработка интегрированной среды на основе web-технологий, работающей в браузере и совмещающей в себе редактор для создания .ksy-файлов, компилятор, визуализатор дерева объектов, hex viewer и менеджер библиотеки ksy-форматов. Среда реализована на HTML/JavaScript, но благодаря технологии ScalaJS, внутри у нее использоваться абсолютно такой же компилятор, как и в большой, "десктопной" версии Kaitai Struct. Доступна онлайн демо-версия (https://kt.pe/kaitai_struct_webide/).
- Новые возможности языка .ksy
- Switch-подобный механизм определения типов данных на основе условия позволяет отказаться от кучи однотипных if'ов:
- Цикл repeat-until позволяет объявить массив элементов, повторяющихся до достижения определенного условия. Для ссылки на текущий элемент следует использовать специальную переменную `_`. Например, следующее объявление задает массив целых знаковых 4-байтовых чисел, заканчивающийся -1:
- id: elements
type: s4
repeat: until
repeat-until: _ == -1Более сложный пример — массив сегментов (тип segment - пользовательский, объявлен отдельно), заканчивающийся чтением сегмента с кодом "segment_code::end":
- id: segments
type: segment
repeat: until
repeat-until: _.code == segment_code::end
- Каждое поле теперь может аннотироваться строчкой человеко-читаемой документации. Кроме видимости в .ksy-файле, эта документация будет выгружаться в doc-систему целевого языка (JavaDoc, JSDoc, YARD/RDoc и т.п.):
- В язык выражений добавлены операции над потоком (`_io`). С их помощью можно, например, адресовать структуры относительно конца потока (а не только относительно начала):
instances:
from_start: # 0x10 байт, начиная с 0x40 байта от начала
pos: 0x40
size: 0x10
from_end: # 0x10 байт, начиная с 0x40 байта с конца
pos: _io.size - 0x40
size: 0x10Или, например, удобно делать условные структуры, которые будут парситься, только если что-то еще осталось в потоке:
seq:
# основной элемент, присутствует всегда
- id: main_element
type: ...
# дополнительный элемент, будет зачитан, только в потоке еще что-то есть
- id: aux_element
type: ...
if: not _io.eof
- Важные мелочи
- Существенно улучшена диагностика ошибок, усилена строгость проверки исходных .ksy. При обнаружении ошибки компилятор теперь генерирует понятные ссылки на конкретные элементы, в которых проблема и предлагает варианты решения. При обнаружении ошибки с данными в runtime в debug-режиме теперь производится попытка оставить как можно больше данных в структуре (включая не полностью заполненные классы), чтобы легче было понять, где именно произошел сбой парсинга.- Стандартизация сборки: в дополнение к ранее собираемым (https://rubygems.org/gems/kaitai-struct) runtime-модулям для Ruby в виде gem, появились доступные для инсталляции из соответствующих репозитариев пакеты для Python в PyPI (https://pypi.python.org/pypi?:action=display&name=kaitaistru...) и для Java-платформы (https://search.maven.org/#artifactdetails%7Cio.kaitai...). Авторы призывают помочь с упаковкой runtime-библиотек и для других языков.
URL: http://kaitai.io/news/2016-11-09.html
Новость: http://www.opennet.me/opennews/art.shtml?num=45470
Нужно!Предлагаю всем собраться и решить вопрос с генератором, ибо это тоже нужно, но сложнее
Генератор декларативных языков описания бинарных форматов и структур данных нужен, однозначно!
Ура! Да здравствует тысяча первый язык описания бинарных форматов!
Назовите хотя бы 3 предыдущих живых языка, если не сложно? Чтобы им можно было описать структуру файловой системы или там какого-нибудь JPEG- или PNG-файла.
https://github.com/kaitai-io/kaitai_struct/wiki/FAQ#how-does...-
Что самое смешное - там сейчас ни одного из языков описания бинарных форматов не затронуто. Речь про DFDL, BinPAC, PacketTypes, DataScript, PADS, PEG и т.п.
интересно, может ли эта вещь выполнять роль компилятора/кросскомпилятора, в последствии заменив собой гцц/шланг?
> интересно, может ли эта вещь выполнять роль компилятора/кросскомпилятора, в последствии
> заменив собой гцц/шланг?Столица переезжает в Нью-Васюки!
Даже не надейся: домашние задания всё равно будут задавать.
Подскажите в какой программе сделана схема в первом изображении?
Вот эта - http://kaitai.io/img/code1.png ? Это HTML, написанный в первом попавшемся текстовом редакторе и отрендеренный в первом попавшемся браузере.
подскажите плиз, что за шрифт на скриншоте?
На каком из и какой из шрифтов - их тут как бы много?..
> На каком из и какой из шрифтов - их тут как бы
> много?..http://kaitai.io/img/code1.png
>> На каком из и какой из шрифтов - их тут как бы
>> много?..
> http://kaitai.io/img/code1.pngЭто те же шрифты, что и на сайте kaitai.io. Exo и Share Tech Mono.
Однозначно нужно.Что там с поддержкой регулярных выражений?
> Что там с поддержкой регулярных выражений?Ничего. А зачем?
Насколько можно судить, грамматика Kaitai Struct мощнее, или, как минимум, не уже регулярных выражений.
> Насколько можно судить, грамматика Kaitai Struct мощнее, или, как минимум, не уже
> регулярных выражений.Нет, здесь просто область применения радикально другая. Регулярные языки (да и вообще традиционные задачи парсинга) упираются в разрешение неоднозначности: всякие там ^(a*)(aaa)$ - очередная "a" - это еще первая группа или уже вторая? И, соответственно, приносятся всякие бэктрекинги, DFA, LL/LR/LALR, lookup'ы и т.д.
Бинарные форматы в массе своей куда проще. Здесь нет неоднозначности - они специально так проектируются, чтобы их было легко читать алгоритмом. Соответственно, и нет почти никакой необходимости в механиках неоднозначности.
Ну, регулярные выражения в классическом понимании не требуют сложных механизмов разбора. В прагматичных применениях нет смысла замедлять разборщик, позволяя делать откат при разборе текста по приведённому Вами выражению и достаточно жадной стратегии, так как такие выражения не имеют практического смысла, и легко могут быть заменены на нормальные.P.S Обратил внимание на недостатки:
1. В документации отсутсвует грамматика самого Katai Struct, это усложняет ознакомление.
2. Входной документ не проверяется на корректность и генератор легко делает некомпилируемый код
> Ну, регулярные выражения в классическом понимании не требуют сложных механизмов разбора.Ну, как минимум DFA-то требуют. Хотя что считать сложным.
> P.S Обратил внимание на недостатки:
> 1. В документации отсутсвует грамматика самого Katai Struct, это усложняет ознакомление.По-моему, в документации как раз ничего, кроме грамматики и нет :( Для упрощения ознакомления надо по идее писать какие-то туториалы, quick start и человеческие гайды, но мне все некогда, а кто-то еще никак не сподвигнется. Единственный гайд, который до сих пор написали - та самая статья в двух частях про реверсинг VN - но ее сложно назвать "гайдом по инструментарию".
> 2. Входной документ не проверяется на корректность
Ох. Как раз вроде бы теперь сильно больше проверяется. Можно больше конкретных примеров?
> и генератор легко делает некомпилируемый код
Это довольно многогранный вопрос, не совсем связанный с корректностью входного ksy. Например, если мы компилируем два ksy по отдельности: FormatA и FormatB, и FormatA ссылается на FormatB. На момент компиляции FormatA компилятор ничего не знает о структуре (и даже существовании) FormatB, поэтому лучшее, что он может сделать, встретив неописанный тип - просто вывести его названием, как есть, в предположении, что это тип верхнего уровня. По отдельности FormatA не скомпилируется. А вот FormatA + FormatB в одном проекте уже дадут искомую работающую связку.
> Ох. Как раз вроде бы теперь сильно больше проверяется. Можно больше конкретных
> примеров?Я не экспериментировал много, просто ввёл такое:
meta:
id: Операция Ы
что разборщик съел и не поморщился, выдав:...
public class Операция Ы extends KaitaiStruct {
public static Операция Ы fromFile(String fileName) throws IOException {
return new Операция Ы(new KaitaiStream(fileName));
}
...
>> Ох. Как раз вроде бы теперь сильно больше проверяется. Можно больше конкретных
>> примеров?
> Я не экспериментировал много, просто ввёл такое:
> meta:
> id: Операция ЫДа, факт. Не должно. Вообще все идентификаторы как раз проверяются, кроме, как оказалось, этого ;) Сейчас починю.
Хотя вообще само по себе это наталкивает на забавную дилемму. "Операция Ы", может, и невалидный идентификатор, а вот "операция_ы" (который станет в Java "ОперацияЫ") - вполне себе. Может, разрешить non-ASCII?..
Если разрешать, тогда, наверное, для целевых языков, не поддерживающих такие символы нужно делать преобразование имён. Короче говоря, проще запретить.
> Если разрешать, тогда, наверное, для целевых языков, не поддерживающих такие символы нужно
> делать преобразование имён. Короче говоря, проще запретить.Проще -- не всегда лучше. Предлагаю ограничиться предупреждением. А то в начале вводят в языки UTF8, а потом ограничивают его использование.
О, разработчик! Очень приятно.С регулярными выражениями позицию понял. Хотел спросить еще, что на счет юзерских функций? Заметил, что есть process. Можно задавать собственные функции обработки? Бывает, попадаются извращенцы, которые упаковывают так, что одними xor/rol/ror/zlib не обойтись. Если да, то как?
> Хотел спросить еще, что на счет юзерских
> функций? Заметил, что есть process. Можно задавать собственные функции обработки? Бывает,
> попадаются извращенцы, которые упаковывают так, что одними xor/rol/ror/zlib не обойтись.
> Если да, то как?Пока - вручную. То есть один формат, в котором все заканчивается на
meta:
id: Format1
seq:
# ...
- id: buf
size: somethingдальше в целевом языке:
Format1 foo = Format1.fromFile("...");
byte[] buf = foo.buf();
// как-то распаковали, отталкиваясь от buf
byte[] unpacked = ...;
// и запускаем парсить то, что внутри по второму формату:
Format2 bar = new Format2(new KaitaiStream(unpacked));и дальше уже отдельный тип Format2 в ksy описывает все, что внутри.
В целом уже обсуждалась идея выдать наружу интерфейс, на котором можно реализовывать произвольные функции распаковки (туда - поток байт, оттуда - поток). Тогда все будет сводиться к чему-то типа:
- id: buf
size: something
process: user(some_unpacker)И тогда внутри будет генерироваться вызов чего-то типа
buf = new SomeUnpacker().unpack(raw)
А от пользователя, соответственно, будет предполагаться, что у него где-то неподалеку в окружении найдется класс SomeUnpacker, который implements такой интерфейс.
Ок. Если реализуете идею с интерфейсом наружу, то не забудьте про передачу параметров. Иногда нужно передать в распаковщик ранее распарсенную структуру.
> Ок. Если реализуете идею с интерфейсом наружу, то не забудьте про передачу
> параметров. Иногда нужно передать в распаковщик ранее распарсенную структуру.Например? Распаковщик, если что, инициализируется вручную на том же уровне, на котором класс формата. И никто не мешает там использовать хоть весь класс формата целиком. Когда и что может потребоваться еще передавать?
> По-моему, в документации как раз ничего, кроме грамматики и нет :(Я имел ввиду формальное определение в РБНФ или что-то подобное. Такое описание позволяет быстрей ухватить суть за счёт компактности определения - синтаксис серьёзных языков умещается в несколько страниц, простых предметно ориентированных может влезть и в несколько строк. Зависит, конечно, от навороченности языка.
>> По-моему, в документации как раз ничего, кроме грамматики и нет :(
> Я имел ввиду формальное определение в РБНФ или что-то подобное. Такое описание
> позволяет быстрей ухватить суть за счёт компактности определения - синтаксис серьёзных
> языков умещается в несколько страниц, простых предметно ориентированных может влезть и
> в несколько строк. Зависит, конечно, от навороченности языка.Тогда нужно придумать какую-то очередную вариацию БНФ для YAML-based форматов. Или можно по идее сделать YAML-схему...
Если сам YAML вписывается в БНФ, то проблем быть не должно, но всё же РБНФ лучше для восприятия человеком.Нашёл БНФ для YAML https://gist.github.com/tociyuki/3936873 - выглядит удручающе, но вполне возможно, что грамматика Kaitai Struct, являясь подмножеством, будет попроще.
> Если сам YAML вписывается в БНФ, то проблем быть не должно, но
> всё же РБНФ лучше для восприятия человеком.
> Нашёл БНФ для YAML https://gist.github.com/tociyuki/3936873 - выглядит удручающе, но
> вполне возможно, что грамматика Kaitai Struct, являясь подмножеством, будет попроще.Писать самому парсер YAML - это да, мягко говоря, удручающее занятие. Вообще весь смысл использования YAML (XML, JSON, или чего-то такого высокоуровневого) был ровно в том, чтобы *не* заморачиваться с любыми описаниями грамматик и Бэкусом-Науром, а использовать какие-то инструменты более высокого уровня для описания того, что дозволено иметь в формате.
Как правило - такие инструменты начинаются со схем. Для YAML это, например, Kwalify - http://www.kuwata-lab.com/kwalify/ruby/users-guide.01.html#s....
Если хочется именно грамматику и BNF / ENBF / RNBF / ANTLR / yacc / etc - то тогда имеет смысл ее просто придумать и описать, в терминах, формализуемых проще, чем языки разметки. В свое время на LOR народ предлагал вместо:
meta:
id: foo
seq:
- id: len
type: u1
- id: my_str
type: str
encoding: UTF-8
size: lenделать что-то C-подобное, а ля
type foo {
u1 len;
str(len, UTF-8) my_str;
}
> type foo {
> u1 len;
> str(len, UTF-8) my_str;
> }Конечно, нечто подобное и хотелось бы видеть в качестве входного языка вместо монотонно многословного YAML. Если такой вариант рассматривался, что стало преградой для воплощения?
>> type foo {
>> u1 len;
>> str(len, UTF-8) my_str;
>> }
> Конечно, нечто подобное и хотелось бы видеть в качестве входного языка вместо
> монотонно многословного YAML. Если такой вариант рассматривался, что стало преградой для
> воплощения?И тот, и другой выбор - в любом случае спорные с многих точек зрения. Кому-то нравится одно, кому-то - другое. С точки зрения написания вручную - кому-то проще выучить синтаксис-скобочки-всякие []{}(), кому-то - держать в голове ключевые слова "size", "type", "id" и т.д.
С точки зрения программной обработки - конечно, любой язык разметки (YAML, JSON, XML) сильно выигрывает в плане того, что можно сделать красивый GUI, где показывать всю эту штуку в виде дерева с менюшками добавления элементов. Да и если надо сделать что-то простое с ksy-описанием - например, написать скрипт автоматического переименования типов - добавлять префикс - на любом скриптовом языке сейчас это делается в 2 строчки. Решать аналогичную задачу с полноценным языком с грамматикой - задача на два порядка более сложная.
Поддерживать параллельно два-три альтернативных представления формата (YAML/JSON, XML, C-подобный) мне на данном этапе развития проекта кажется не очень актуальным - хотя, в теории, дописать такую поддержку - задача на один-два вечера. Благо парсер с грамматиками у нас все равно уже есть. Дольше, скорее, это C-подобное представление придумывать.
необходимо!
Вот бы кто скрестил с Orcc (http://orcc.sourceforge.net/), там у них в библиотечке https://github.com/orcc/orc-apps есть много интересный форматов, вроде HEVC...
> Вот бы кто скрестил с Orcc (http://orcc.sourceforge.net/), там у них в библиотечке
> https://github.com/orcc/orc-apps есть много интересный форматов, вроде HEVC...Интересная ссылка, спасибо. Попробую может быть с ними связаться и пообщаться.
Прекрасно оформленная новость и очень крутой апдейт с кучей полезностей!
Увы, пока очень слабо. Но потенциал для развития есть. Автор, откройте драфт какого-нибудь стандарта, например, H.264 и сами все поймете.
А драфт-то зачем? ;)
А как можно начать считывание типов со смещением от конца потока?
> А как можно начать считывание типов со смещением от конца потока?instances:
foo:
pos: _io.size - смещение_от_конца
Как ни странно, но именно это я и попробовал сделать в первую очередь...
Не работает оно(
> Как ни странно, но именно это я и попробовал сделать в первую
> очередь...
> Не работает оно(Можно чуть более развернуто - что именно не работает? Не компилируется ksc, не компилируется целевым языком, компилируется, но зачитывает не то, что ожидалось?
А теперь до меня дошло, что в ksv не подсвечиваются секции указанные в instances...
Печально. Я думал, что оно тоже должно подсвечиваться.
> А теперь до меня дошло, что в ksv не подсвечиваются секции указанные
> в instances...
> Печально. Я думал, что оно тоже должно подсвечиваться.Вообще должно. Сейчас проверю. Можно какой-нибудь пример?
meta:
id: test
endian: le
seq:
- id: header
type: u4
instances:
offset:
pos: _io.size - 6
type: u2
Да, факт, так не определяется. Вообще, в реальной жизни это практически не заметить, т.к. почти всегда у instance в type идет какая-то подструктура, внутри которой все как раз подсвечиваться будет.Спасибо за багрепорт, сейчас попробую подумать, как исправить.
Спасибо за исправление.
Теперь все работает как надо.
Еще я хотел узнать, а можно ли как-то получить значение итератора repeat-expr внутри цикла?
> Спасибо за исправление.
> Теперь все работает как надо.Эм, я вроде бы пока ничего не исправлял ;)
> Еще я хотел узнать, а можно ли как-то получить значение итератора repeat-expr
> внутри цикла?А в каком выражении его хочется получать?
> Эм, я вроде бы пока ничего не исправлял ;)Как так? Я обновил ksv до версии 0.5 и проблема исчезла
> А в каком выражении его хочется получать?
instances:
test:
pos: rows[{вот здесь хочется получить}].section_start
size: rows[{ну и здесь}].section_size
repeat: expr
repeat-expr: rows_count
>> Эм, я вроде бы пока ничего не исправлял ;)
> Как так? Я обновил ksv до версии 0.5 и проблема исчезла0.5 выпустилась в более-менее штатном режиме по итогам последних нескольких месяцев. Проблему с отображением instances я там до сих пор наблюдаю.
>> А в каком выражении его хочется получать?
> instances:
> test:
> pos: rows[{вот здесь хочется получить}].section_start
> size: rows[{ну и здесь}].section_size
> repeat: expr
> repeat-expr: rows_countЭто не так делается. Think OOP. Если есть rows, у которых есть section_start и section_size, то логично у них же завести
instances:
body:
pos: section_start
size: section_sizeи обращаться к их содержимому, как к row[42].body.
> 0.5 выпустилась в более-менее штатном режиме по итогам последних нескольких месяцев. Проблему
> с отображением instances я там до сих пор наблюдаю.А вот я уже не наблюдаю.
> Это не так делается.
Зато значительно компактнее.
>> Это не так делается.
> Зато значительно компактнее.Какой из вариантов компактнее?
> Какой из вариантов компактнее?Тут дело в другом. Какой из вариантов рабочий...
Я не совсем понял, как заставить ваш вариант итерировать таблицу...
>> Какой из вариантов компактнее?
> Тут дело в другом. Какой из вариантов рабочий...
> Я не совсем понял, как заставить ваш вариант итерировать таблицу...Вам что нужно получить-то в итоге?
У вас есть что-то типа:
types:
main:
seq:
- id: rows_count
type: u4
- id: rows
type: row
repeat: expr
repeat-expr: rows_count
row:
seq:
- id: section_start
type: u4
- id: section_size
type: u4Вы уже можете обращаться к main.rows[42].section_start и main.rows[42].section_size. Теперь вы хотите к main дописать что-то, чтобы иметь возможность обращаться к телу секции как-то типа main.test[42]. А я предлагаю дописать не к main, а к row - что логичнее, т.к. объект row как раз посвящен одной конкретной секции. И обращаться к телу секции, как main.rows[42].body.
> Вы уже можете обращаться к main.rows[42].section_start и main.rows[42].section_size.
> Теперь вы хотите к main дописать что-то, чтобы иметь возможность обращаться
> к телу секции как-то типа main.test[42]. А я предлагаю дописать не
> к main, а к row - что логичнее, т.к. объект row
> как раз посвящен одной конкретной секции. И обращаться к телу секции,
> как main.rows[42].body.Да. Именно то, что мне нужно.
Просто не привык я к таком OOP)
Спасибо.
> И обращаться к телу секции, как main.rows[42].body.Кстати, в данном случае надо сбросить подсветку родительской секции. В данном случае она отображается неверно.
> А драфт-то зачем? ;)Драфты бесплатные, скачать можно.
Нужная штука. Как бы так ее скрестить с Thrift/Avro....
> Нужная штука. Как бы так ее скрестить с Thrift/Avro....А зачем? Разбирать Thrift или Avro в KS?
Битовые поля поддерживаются? Или можно ли таким инструментом описывать регистры аппаратуры, где далеко не все поля кратны байтам?
> Битовые поля поддерживаются? Или можно ли таким инструментом описывать регистры аппаратуры,
> где далеко не все поля кратны байтам?Пока нет, но, надеюсь, скоро сделаем. Пока все побитовые операции делаются через битмаски.
Здравствуйте. Мне попался бинарный файл, который содержит в качестве дескриптора таблицу вида: тип элемента+конец смещения относительно начала файла.
Размер элемента определяется разностью между концом и началом, но началом служит конец блока дескрипторов, а эту информацию внутри instances никак не получить...
Нужно все-таки научить этот язык итерировать списки.
И я так и не нашел как создавать предусловия для цикла.
Очень мало что понял без более конкретных примеров, но попробую ответить.> Размер элемента определяется разностью между концом и началом, но началом служит конец > блока дескрипторов, а эту информацию внутри instances никак не получить...
Если нужно получить "начало" через конец блока дескрипторов - то, вероятно, нужно создать отдельный элемент в seq, который бы начинался сразу после этого самого блока дескриптора - он создаст поток, в этом потоке размечать уже instances. Индексация при этом уже будет с 0, получать ничего не нужно.
Альтернативный (но относительно хаковый) вариант - каким-то образом сделать так, чтобы после блока дескрипторов вызвался _io.pos и сохранился где-то (в вычислимом instance, например). А затем уже отчитывать вручную от него.
> Нужно все-таки научить этот язык итерировать списки.
Зачем?
> И я так и не нашел как создавать предусловия для цикла.
Никак.
> Если нужно получить "начало" через конец блока дескрипторов - то, вероятно, нужно
> создать отдельный элемент в seq, который бы начинался сразу после этого
> самого блока дескриптора - он создаст поток, в этом потоке размечать
> уже instances. Индексация при этом уже будет с 0, получать ничего
> не нужно.Вот именно, что нужно не просто получить "начало", а использовать блок дескрипторов для разбора этих элементов. Нужно как-то итерировать блок дескрипторов внутри instances после блока...
>> Если нужно получить "начало" через конец блока дескрипторов - то, вероятно, нужно
>> создать отдельный элемент в seq, который бы начинался сразу после этого
>> самого блока дескриптора - он создаст поток, в этом потоке размечать
>> уже instances. Индексация при этом уже будет с 0, получать ничего
>> не нужно.
> Вот именно, что нужно не просто получить "начало", а использовать блок дескрипторов
> для разбора этих элементов. Нужно как-то итерировать блок дескрипторов внутри instances
> после блока...Можно какой-то чуть более конкретный пример? Я пока понял, что вроде бы речь идет о случае, когда есть два отдельных массива (прямо совсем отдельных, чуть ли не в разных объектах на разных уровнях лежащих), и надо итерироваться сразу по обоим одновременно?
Ну почти так.
Нужно сначала получить все дескрипторы, а потом уже получить второй массив.
Могу скинуть пример позже.