package validator import "strings" // InMemoryWorkerLookup is a zero-deps WorkerLookup useful for tests // and small-fixture validation. Mirrors Rust's // `InMemoryWorkerLookup::from_records`. // // Lookup is case-insensitive on candidate_id since Rust's // HashMap with PartialEq + the source data's casing inconsistency // (some IDs uppercase, some lowercase, some mixed) means // case-sensitive lookup misses real matches. Lower-casing on // insert keeps the contract. type InMemoryWorkerLookup struct { byID map[string]WorkerRecord } // NewInMemoryWorkerLookup builds a lookup from a list of records. // Duplicate candidate_ids: last-write-wins. Empty candidate_id: skipped. func NewInMemoryWorkerLookup(records []WorkerRecord) *InMemoryWorkerLookup { m := make(map[string]WorkerRecord, len(records)) for _, r := range records { if r.CandidateID == "" { continue } m[strings.ToLower(strings.TrimSpace(r.CandidateID))] = r } return &InMemoryWorkerLookup{byID: m} } // Find satisfies WorkerLookup. Returns (rec, true) on hit, // (nil, false) on miss. func (l *InMemoryWorkerLookup) Find(candidateID string) (*WorkerRecord, bool) { if l == nil { return nil, false } r, ok := l.byID[strings.ToLower(strings.TrimSpace(candidateID))] if !ok { return nil, false } // Return a copy so callers can't mutate the lookup's internal state. cp := r return &cp, true } // Len exposes the size for tests + admin endpoints. func (l *InMemoryWorkerLookup) Len() int { if l == nil { return 0 } return len(l.byID) } // strPtr is a tiny convenience for tests that need *string fields // on WorkerRecord.City/State/Role. func strPtr(s string) *string { return &s }