transform

package
v1.26.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package transform объявляет преобразования пакета и правила их сочетания.

Здесь нет ни одной реализации — только имена шагов, порядок между ними и запреты. Реализации живут в packet, processors и командах CLI; этот пакет отвечает на два вопроса: можно ли включить такой набор и в каком порядке его выполнять.

Зачем отдельный пакет

Порядок был закодирован очередью вызовов chain.Add и комментариями вида "MUST run before ComputeIntegrity". Это работает ровно до тех пор, пока каждый, кто добавляет шаг, прочитал все комментарии. За один месяц так набралось три бага, и все — про порядок, а не про сами преобразования:

  • разложить по колонкам после ComputeIntegrity, но присвоив Data целиком, значило выбросить уже проставленный xxh3;
  • разложить по колонкам ДО хеширования значило бы, что писатель хеширует колонки, а читатель строки, — расхождение на каждом пакете;
  • materializeForWrite гасила намерение разложить, потому что к моменту её вызова строки уже построчные, — и --columnar --integrity молча писал обычный пакет.

Ни один не виден на одиночном флаге, и ни один не виден на паре. Они живут в стыке между шагами.

Почему объявление, а не перечень сочетаний

Перебор N флагов — это 2^N наборов, попарный — N². Написанная руками матрица отстанет от кода на первом же новом преобразовании, а дописывать в неё строку под каждый новый флаг — это и есть костыль, только оформленный таблицей. Ограничения объявляются у шага один раз; наборы для проверки порождаются из них (см. stages_test.go).

Правило для нового преобразования

Добавляя формат или преобразование, объявите его здесь и ничего не добавляйте в вызывающий код руками:

  1. Заведите Stage с именем и ограничениями: After/Before — если порядок важен, Conflicts — если сочетание бессмысленно или опасно.
  2. Reason пишите как ответ пользователю, а не как записку себе: он попадёт в текст отказа.
  3. Не ставьте ограничение "на всякий случай". Каждое из перечисленных существует потому, что его нарушение уже ломало данные, и в комментарии сказано как именно. Ограничение без такой причины запретит рабочее сочетание.
  4. Шаг обязан быть идемпотентным либо применяться ровно из одного места. Раскладка по колонкам применялась из двух — писателем и шагом сжатия, — и второй проход читал колонки как строки, отдавая значения чужих записей. Молча: такой пакет конвертируется без замечаний.

Index

Examples

Constants

View Source
const (
	// StageRowProcessors — цепочка pre-export: маскирование, нормализация,
	// валидация. Идёт первой: всё дальнейшее обязано считать уже изменённые
	// значения, иначе хеш накроет то, чего в пакете не будет.
	StageRowProcessors = "row-processors"

	// StageCompact — carry-forward кодирование фиксированных полей (v1.3.1).
	StageCompact = "compact"

	// StageColumnar — колоночная раскладка Data (layout="columns").
	StageColumnar = "columnar"

	// StageIntegrity — xxh3-хеши Schema, Data и отпечаток пакета (v1.4).
	StageIntegrity = "integrity"

	// StageCompress — zstd или kanzi.
	StageCompress = "compress"

	// StageEncrypt — AES-256-GCM посекционно (v1.5).
	StageEncrypt = "encrypt"
)

Имена шагов. Строки, а не iota: они попадают в сообщения об ошибках и в имена подтестов, и должны читаться человеком.

Variables

This section is empty.

Functions

func All

func All() []string

All возвращает имена всех объявленных шагов в порядке объявления.

func MustRunBefore

func MustRunBefore(a, b string) bool

MustRunBefore сообщает, обязан ли a идти раньше b при обоих включённых. Нужен проверкам и диагностике; на горячем пути не используется.

func Plan

func Plan(enabled []string) ([]string, error)

Plan упорядочивает включённые шаги и отвергает несовместимый набор.

Порядок детерминирован: при равных ограничениях шаги идут в порядке объявления в registry. Это не косметика — недетерминированный план означал бы, что один и тот же набор флагов даёт разные байты от запуска к запуску.

Example
plan, _ := Plan([]string{StageCompress, StageColumnar, StageIntegrity, StageCompact})
fmt.Println(strings.Join(plan, " → "))
Output:
compact → integrity → columnar → compress

func ReadMustPrecede

func ReadMustPrecede(a, b string) bool

ReadMustPrecede сообщает, обязан ли a идти раньше b при чтении.

func ReadStepIndex

func ReadStepIndex(name string) int

ReadStepIndex возвращает позицию шага чтения, или -1.

Types

type ReadStep

type ReadStep struct {
	Name string
	Note string
}

ReadStep — шаг чтения и причина его места в порядке.

func ReadOrder

func ReadOrder() []ReadStep

ReadOrder возвращает порядок шагов чтения.

Это описание, а не исполнитель: шаги разбросаны по ParseBytes, DecompressData, VerifyIntegrity и командам CLI. Список существует затем, чтобы место каждого было записано вместе с причиной — три бага здесь случились ровно потому, что причина жила в чьей-то голове.

Example
for _, s := range ReadOrder() {
	fmt.Println(s.Name)
}
Output:
parse
decrypt
decompress
expand-columnar
expand-compact
verify-rowcount
verify-integrity
expand-dictionary

type Stage

type Stage struct {
	Name string

	// After перечисляет шаги, которые обязаны отработать РАНЬШЕ этого.
	After []string

	// Conflicts перечисляет шаги, с которыми этот несовместим. Отношение
	// симметрично: объявлять его достаточно с одной стороны.
	Conflicts []string

	// Reason объясняет ограничение словами, пригодными для показа
	// пользователю. Пустой Reason допустим только у шага без ограничений.
	Reason string
}

Stage — одно преобразование и правила его сочетания с другими.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL