Help us shape the future of Go! Take the 2026 Go Developer Survey

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