package engine type sequenceSelectorSegmentKind uint8 const ( sequenceSelectorLiteral sequenceSelectorSegmentKind = iota + 1 sequenceSelectorAnyMappingKey ) type sequenceSelectorSegment struct { kind sequenceSelectorSegmentKind key string } type sequenceIdentitySelector []sequenceSelectorSegment type sequenceIdentityRegistration struct { selector sequenceIdentitySelector identityFields []string invalidPath *Path } // SequenceIdentitySelectorSegment carries one root-owned selector segment into // an engine definition. This transport type remains behind the internal package // boundary. type SequenceIdentitySelectorSegment struct { Key string AnyMappingKey bool } // SequenceIdentityRegistrationInput carries detached root-owned registration // data into an engine definition without exposing its compiled policy. A // non-nil ExactPath selects exact-path registration; otherwise Selector is used. type SequenceIdentityRegistrationInput struct { ExactPath *Path Selector []SequenceIdentitySelectorSegment IdentityFields []string } type sequenceSelectorTrie struct { literals map[string]*sequenceSelectorTrie wildcard *sequenceSelectorTrie fields []string terminal bool } type sequencePolicy struct { selectorTrie *sequenceSelectorTrie } // DefinitionWithSequenceIdentityRegistrations attaches facade-owned // registrations to a detached engine definition without exposing compiled // engine policy. func DefinitionWithSequenceIdentityRegistrations[T any](definition Definition[T], registrations []SequenceIdentityRegistrationInput) Definition[T] { if registrations == nil { definition.sequenceIdentityRegistrations = nil return definition } definition.sequenceIdentityRegistrations = make([]sequenceIdentityRegistration, len(registrations)) for index, registration := range registrations { compiled := sequenceIdentityRegistration{identityFields: append([]string(nil), registration.IdentityFields...)} if registration.ExactPath != nil { path, err := normalizeDestination(registration.ExactPath.clone()) if err != nil { invalid := registration.ExactPath.clone() compiled.invalidPath = &invalid } else { compiled.selector = make(sequenceIdentitySelector, len(path.segments)) for segmentIndex, segment := range path.segments { compiled.selector[segmentIndex] = sequenceSelectorSegment{kind: sequenceSelectorLiteral, key: segment.key} } } } else { compiled.selector = make(sequenceIdentitySelector, len(registration.Selector)) for segmentIndex, segment := range registration.Selector { kind := sequenceSelectorLiteral if segment.AnyMappingKey { kind = sequenceSelectorAnyMappingKey } compiled.selector[segmentIndex] = sequenceSelectorSegment{kind: kind, key: segment.Key} } } definition.sequenceIdentityRegistrations[index] = compiled } return definition } func compileSequenceIdentityPolicy(registrations []sequenceIdentityRegistration) (sequencePolicy, []Diagnostic) { policy := sequencePolicy{} compiled := make([]sequenceIdentityRegistration, 0, len(registrations)) var diagnostics []Diagnostic for _, registration := range registrations { selector := cloneSequenceIdentitySelector(registration.selector) if registration.invalidPath != nil { diagnostics = append(diagnostics, Diagnostic{ Code: CodeOptionsInvalid, Severity: SeverityError, Path: registration.invalidPath.clone(), Message: "sequence registration path must contain only non-reserved mapping keys", }) continue } fields, err := normalizeSequenceIdentityFields(registration.identityFields) if err != nil { diagnostics = append(diagnostics, Diagnostic{ Code: CodeOptionsInvalid, Severity: SeverityError, Path: selectorDiagnosticPath(selector), Message: "sequence registration requires at least one identity field", }) continue } if err := validateSequenceIdentitySelector(selector); err != nil { diagnostics = append(diagnostics, Diagnostic{ Code: CodeOptionsInvalid, Severity: SeverityError, Path: selectorDiagnosticPath(selector), Message: "sequence registration selector must contain only valid mapping segments", }) continue } compiled = append(compiled, sequenceIdentityRegistration{selector: selector, identityFields: fields}) } for leftIndex := 0; leftIndex < len(compiled); leftIndex++ { for rightIndex := leftIndex + 1; rightIndex < len(compiled); rightIndex++ { left, right := compiled[leftIndex], compiled[rightIndex] if !sequenceIdentitySelectorsOverlap(left.selector, right.selector) || equalSequenceIdentityFields(left.identityFields, right.identityFields) { continue } diagnostics = append(diagnostics, Diagnostic{ Code: CodeOptionsInvalid, Severity: SeverityError, Path: selectorDiagnosticPath(left.selector), Message: "overlapping sequence registrations must use the same identity fields", }) } } if len(diagnostics) != 0 { return policy, canonicalDiagnostics(diagnostics) } unique := make([]sequenceIdentityRegistration, 0, len(compiled)) for _, registration := range compiled { duplicate := false for _, existing := range unique { if sequenceIdentitySelectorsEqual(existing.selector, registration.selector) && equalSequenceIdentityFields(existing.identityFields, registration.identityFields) { duplicate = true break } } if duplicate { continue } unique = append(unique, registration) } for _, registration := range unique { policy.addRegistration(registration) } return policy, nil } func (p *sequencePolicy) addRegistration(registration sequenceIdentityRegistration) { if p.selectorTrie == nil { p.selectorTrie = &sequenceSelectorTrie{} } node := p.selectorTrie for _, segment := range registration.selector { if segment.kind == sequenceSelectorAnyMappingKey { if node.wildcard == nil { node.wildcard = &sequenceSelectorTrie{} } node = node.wildcard continue } if node.literals == nil { node.literals = make(map[string]*sequenceSelectorTrie) } if node.literals[segment.key] == nil { node.literals[segment.key] = &sequenceSelectorTrie{} } node = node.literals[segment.key] } node.fields = append([]string(nil), registration.identityFields...) node.terminal = true } func (p sequencePolicy) identityFieldsAt(path Path) ([]string, bool) { if !path.valid() { return nil, false } if p.selectorTrie == nil { return nil, false } current := []*sequenceSelectorTrie{p.selectorTrie} for _, segment := range path.segments { if segment.kind != pathSegmentKey && segment.kind != pathSegmentParsed { return nil, false } next := make([]*sequenceSelectorTrie, 0, len(current)*2) for _, node := range current { if literal := node.literals[segment.key]; literal != nil { next = append(next, literal) } if node.wildcard != nil { next = append(next, node.wildcard) } } if len(next) == 0 { return nil, false } current = next } for _, node := range current { if node.terminal { return append([]string(nil), node.fields...), true } } return nil, false } func (p sequencePolicy) registered(path Path) bool { _, ok := p.identityFieldsAt(path) return ok } func validateSequenceIdentitySelector(selector sequenceIdentitySelector) error { for _, segment := range selector { switch segment.kind { case sequenceSelectorLiteral: if _, err := normalizeDestination(Keys(segment.key)); err != nil { return err } case sequenceSelectorAnyMappingKey: default: return errInvalidDestination } } return nil } func sequenceIdentitySelectorsEqual(left, right sequenceIdentitySelector) bool { if len(left) != len(right) { return false } for index := range left { if left[index] != right[index] { return false } } return true } func sequenceIdentitySelectorsOverlap(left, right sequenceIdentitySelector) bool { if len(left) != len(right) { return false } for index := range left { if left[index].kind == sequenceSelectorLiteral && right[index].kind == sequenceSelectorLiteral && left[index].key != right[index].key { return false } } return true } func equalSequenceIdentityFields(left, right []string) bool { if len(left) != len(right) { return false } for index := range left { if left[index] != right[index] { return false } } return true } func cloneSequenceIdentitySelector(selector sequenceIdentitySelector) sequenceIdentitySelector { return append(sequenceIdentitySelector(nil), selector...) } func selectorDiagnosticPath(selector sequenceIdentitySelector) Path { path := Path{} for _, segment := range selector { if segment.kind != sequenceSelectorLiteral { return Path{} } path = path.Key(segment.key) } return path }