[3e74d4c7508130e47831eae2fcc5ee3e79113386] #keks 

choice в KEKS/Schema

KEKS я давно не трогаю. Использую KEKS/CM постоянно, но типа все форматы
текущие устаканились и не требуют доработки. Но, как часто бывает, нужно
чтобы всё это отлежалось.

Почему то вчера возникла мысль о CHOICE-ах (аналог из ASN.1). Пока
предполагалось что будет некое поле с типом, которое уже вне схемы будет
проверяться программой а дальше вызываться соответствующая валидация по
другой схеме.

А потом осенило: ведь choice это же по сути просто MAP, но с одним
единственным выбранным полем! В ASN.1 это не обязательно SEQUENCE,
конечно же, но в KEKS пускай выбор будет явно виден как поле в MAP. Даже
в ASN.1 он описывается как SEQUENCE визуально. И ведь мой текущий
KEKS/Schema не мешает никоим образом это провалидировать.

    some {
        {field . {map} len=1}
        {field foo {...} optional}
        {field bar {...} optional}
        {field baz {...} optional}
    }

Вот и choice из foo, bar, baz. Только один может быть выбран. Для
удобства я всё же добавил "choice" тип данных для корневого поля:

    some {
        {field . {choice}}
        {field foo {...}}
        {field bar {...}}
        {field baz {...}}
    }

исключительно синтаксический сахар, не влияющий на генерируемые команды
валидации.

Недавно я чуть-чуть менял схему для KEKS/RPC, где использовал MAP-ы
вместо LIST-ов, ибо нефиг экономить. Было поле "t", в котором указан тип
пакета (call, notify, reply), на основе которого предполагался вызов
нужной схемы валидации. Теперь же:

    pkt {
        {field . {choice}}
        {field call {with call}}
        {field notify {with notify}}
        {field reply {with reply}}
    }
    call {
        {field . {map}}
        {field id {bin} >0}
        {field fun {str} >0}
        {field args {map}}
    }
    notify {
        {field . {map}}
        {field id {bin} >0 optional}
        {field fun {str} >0}
        {field args {map}}
    }
    reply {
        {field . {map}}
        {field id {bin} >0}
        {field err {str} >0 optional}
        {field body {map}}
    }

и просто по наличию, гарантированно только одного, поля call, notify или
reply мы понимаем тип пакета. Код программы стал проще.

Вместо {"a": "algo", "v": bin(...)}, можно использовать MAP с одним
полем, являющимся идентификатором алгоритма. И код проще и кодирование
чуть более компактно.

    prv-algos {
        {field . {choice}}
        {field ed25519-blake2b {bin} len=32}
        {field gost3410-256A {bin} len=32}
        {field gost3410-512C {bin} len=64}
        {field mceliece6960119-x25519 {bin} len=13980}
        {field sntrup761-x25519 {bin} len=1795}
        {field slh-dsa-shake-256s {bin} len=128}
    }

Вообще про это не думая и не вспоминая, но полностью ушли все "t", "a",
"v" короткие названия полей в схемах. Это с самого начала было спорным
решением. С одной стороны я наезжаю на уродский CBOR, в котором люди
совершенно бесчеловечные структуры делают, которые декодировать можно,
но не понять физический смысл, но и сам при этом делаю исключение и
применяю короткие названия type, algo, value, так как они очень часто
используются.

В общем, всё ещё красивее, попроще и удобнее становится. Эх, все
структуры правда немного меняются и надо будет уже имеющиеся
зашифрованные/подписанные файлы и ключи менять. Не охота мне обратную
совместимость сейчас поддерживать. Благо, подправить вроде бы всё можно
просто сделав kekspp -tcl <data.keks >data.tcl, руками подправить в
редакторе несколько полей, а дальше keks.tcl <data.tcl >data.keks. Или
скрипт какой-нибудь написать. В общем, возня.

Плюс решил избавиться от HEXLET типа данных. С самого начала он был
исключительно для красоты и удобства отображения пользователю. Вот
различать бинарные и printable (UTF-8) данные -- необходимость. А UUID
тоже был под вопросом. Кода занимает не много, но всё же склоняюсь к
тому, что он точно излишен.

    [оставить комментарий]