Clause
← Уся документація

Перекладено з англійського оригіналу · 1e3a39c8-dirty · 2026-10-26 · Читати англійською

Специфікації ASN.1

Clau компілює специфікації ASN.1 (.asn, .asn1 і списки модулів .set.asn) у модулі Erlang так само, як asn1ct з OTP: Module.erl з encode/2, decode/2 і значеннями модуля та Module.hrl з його record і макросами. Згенерований модуль долучається до пакета компіляції як будь-який інший вихідний файл; його кодування та декодування виконує рушій BER, DER і PER мовою C++ у clause_runtime (OpenSSL не потрібна). Специфікації public_key з OTP компілюватимуться так само.

Вхідні дані

Позиційні вхідні файли із закінченням .asn або .asn1 є специфікаціями:

clau --asn1-option der --asn1-outdir gen Kitchen.asn main.erl -o app
clau --generate-asn1 --asn1-outdir gen Kitchen.asn   # only write gen/Kitchen.erl and gen/Kitchen.hrl
ПараметрЗначення
--asn1-option <option>Параметр asn1ct для всіх специфікацій виклику; можна повторювати. Типово ber.
--asn1-outdir <dir>Куди записуються Module.erl і Module.hrl (outdir в asn1ct); типово поточний каталог. Каталог долучається до шляху включення, тому -include("Module.hrl"). працює.
--generate-asn1Лише записати згенеровані модулі та заголовки; нічого не компілювати.
-I <dir>Також використовується для пошуку імпортованих модулів ASN.1 (i в asn1ct), після власного каталогу специфікації.

Ціль проєкту перелічує специфікації в групах [[targets.asn1]], кожна з яких компілюється зі своїми параметрами:

[[targets]]
name = "app"
sources = ["src/*.erl"]

[[targets.asn1]]
sources = ["asn1/*.asn"]
options = ["per", "noobj"]
outdir = "build/gen"   # default: asn1/ in the target's build directory

sources (обов'язкове) приймає файли та шаблони підстановки так само, як вихідні файли цілі, зіставляючи .asn і .asn1; відсутність збігів є помилкою. Імпортовані модулі шукаються в каталогах специфікацій групи. Згенерований модуль, уже зазначений серед вихідних файлів цілі, не додається двічі. outdir долучається до шляху включення цілі.

Файл .set.asn перелічує по одному файлу модуля в рядку (об'єднана компіляція asn1ct); кожна назва перевіряється як записана, потім із доданими .asn1, .asn та .py. Об'єднаний модуль отримує назву файла набору.

Параметри

ПараметрДія
berБазові правила кодування (типово).
derВизначені правила кодування: ber із відсортованими SET/SET OF, пропущеними значеннями DEFAULT та перевірками DER.
mapsЗначення SEQUENCE/SET є map; відсутні компоненти пропускаються.
undec_restdecode/2 повертає {ok, Value, Rest} із байтами після значення.
no_ok_wrapperencode/2 і decode/2 повертають саме значення та породжують винятки в разі помилок.
legacy_erlang_typesЗначення BIT STRING і OCTET STRING як списки, {Unused, Binary} та цілі числа приймаються.
legacy_bit_string, compact_bit_stringСтарі форми BIT STRING (списки 0 і 1, {Unused, Binary}); передбачають legacy_erlang_types.
noobj, asn1config, verbose, warnings, errors, deterministicПриймаються, нічого не змінюють.
per, uperУпаковані правила кодування, з вирівнюванням і без нього (PER).
no_final_paddingЗ uper: encode/2 повертає біти без доповнення до октету (bitstring).
jerВідхиляється: jer (JSON encoding rules) is not supported.

Будь-який інший параметр дає unknown ASN.1 option 'Name' (код виходу 2).

Підтримувані конструкції

Конструкції X.680/X.681/X.682/X.683, які використовують модулі PKIX і PKCS з OTP та специфікації emqx:

Не підтримуються; кожна конструкція спричиняє помилку у своїй позиції: EXTERNAL, EMBEDDED PDV і CHARACTER STRING (unsupported ASN.1 type), параметризовані значення, об'єкти, видобуті з наборів об'єктів, визначення MACRO та нотації значень, яких не використовують специфікації OTP (unsupported value notation).

Згенеровані модулі

Module.erl експортує те саме, що й asn1ct: encoding_rule/0, maps/0, bit_string_format/0, legacy_erlang_types/0, encode/2, decode/2, info/0 та по одній функції на кожне присвоєння значення. Record та їхні назви відповідають asn1ct (внутрішні типи названо за їхнім шляхом, SEQOF/SETOF для елементів колекцій, параметризовані екземпляри), тому Module.hrl ідентичний заголовку asn1ct, крім першого рядка коментаря; значення виводяться так само, як в asn1ct.

encode/2 і decode/2 повертають {ok, Value} або {error, {asn1, Reason}} із причинами asn1ct ({bad_range, ...}, {unexpected, ...}, {invalid_choice_type, ...}, {'Type not compatible with table constraint', ...}, помилки TLV із asn1rt_nif); декодування зберігає поблажливість та особливості asn1ct (невідомі компоненти розширення пропускаються, {asn1_OPENTYPE, Bytes} і {asn1_ExtAlt, Bytes} для невідомих значень відкритих типів та CHOICE, {asn1_enum, N}).

Згенеровані функції викликають clause_asn1:encode/3 і clause_asn1:decode/3 з термом схеми: {asn1_schema, 1, Rule, Flags, #{Type => Node}, Nodes}. Кожен вузол — це {Kind, Tags, Fields...} (види в порядку NodeKind компілятора, теги як Number bsl 2 bor Class; межі {Lower, Upper, Extensible} з кореневими значеннями розширюваного списку окремих значень як четвертим елементом, обмежені рядки з їхнім алфавітом PER, компоненти з прапорцем групи доповнення); формат є внутрішнім для Clause та може змінитися.

PER

per (із вирівнюванням) і uper (без вирівнювання) побайтово відтворюють код, згенерований asn1ct, та asn1rtt_per/asn1rtt_uper/asn1rtt_per_common (X.691 у реалізації OTP):

Діагностика

Помилки містять шлях, рядок і стовпець специфікації та зупиняють виклик (код виходу 1) до компіляції Erlang:

syntax.asn:4:1: error: expected '::=' near 'END'
undefined.asn:3:22: error: undefined reference Missing
import.asn:4:9: error: cannot find ASN.1 module Absent
empty.asn:1:1: error: no ASN.1 module found

Відмінності від asn1ct перелічено у differences.md.