Documentation
¶
Overview ¶
Package common provides reusable components for device detection parsers.
Index ¶
- func BuildByMatch(template string, matches []string) string
- func BuildModel(template string, matches []string) string
- func ExtractKeywords(pattern string) []string
- func IsUsefulKeyword(kw string) bool
- func SelectCandidates[T Pattern](all []T, idx *PatternIndex[T], ua string, mode CandidateMode) []T
- func WrapDeviceDetectorPattern(pattern string) string
- type CandidateMode
- type FactoryConfig
- type FactoryOption
- type IndexStats
- type Orderable
- type OrderedPattern
- type Pattern
- type PatternIndex
- type RegexCompiler
- type RegexMode
- type UniversalRegex
- type UniversalRegexSubmatch
- type YAMLHTTPHeader
- type YAMLListDB
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildByMatch ¶
BuildByMatch substitutes $1..$n with corresponding regex capture groups. This matches device-detector's template style used across YAML DBs.
Replacement is done from high to low index to avoid $10 being partially replaced as $1 + "0".
func BuildModel ¶
BuildModel performs template substitution and cleanup for device models. This mirrors PHP AbstractDeviceParser::buildModel().
Template substitution: $1, $2, ... are replaced with regex capture groups. Cleanup: underscores to spaces, trailing " TD" removed, "Build" rejected.
Used by Console, Camera, CarBrowser, Notebook, and Mobile parsers.
func ExtractKeywords ¶
ExtractKeywords extracts indexable keywords from a regex pattern. These are literal strings that MUST appear in any matching input.
func IsUsefulKeyword ¶
IsUsefulKeyword checks if a keyword is useful for indexing. Filters out very common strings that appear in almost all UAs.
func SelectCandidates ¶
func SelectCandidates[T Pattern](all []T, idx *PatternIndex[T], ua string, mode CandidateMode) []T
SelectCandidates returns an ordered list of candidates to test for a given UA.
Correctness rule: - In Compatibility mode, if the index yields no candidates, we fall back to full scan. - In StrictIndex mode, if the index yields no candidates, we return nil (no scan).
Note: This function does not perform the "no match in candidates -> full scan" fallback; that remains in parser logic, because only the parser knows whether a match was found.
func WrapDeviceDetectorPattern ¶
WrapDeviceDetectorPattern wraps a raw YAML regex with the same boundary logic used by PHP device-detector's AbstractParser::matchUserAgent().
PHP: '/(?:^|[^A-Z0-9_-]|[^A-Z0-9-]_|sprd-|MZ-)(?:' . $regex . ')/i'
Types ¶
type CandidateMode ¶
type CandidateMode int
CandidateMode controls how aggressively we rely on the keyword index.
- Compatibility: the index is a pure optimization; we fall back to full scan. - StrictIndex: best-effort performance mode; we only try index candidates.
const ( Compatibility CandidateMode = iota StrictIndex )
type FactoryConfig ¶
type FactoryConfig struct {
CandidateMode CandidateMode
RegexMode RegexMode
}
FactoryConfig controls shared behavior across parser factories.
func ApplyFactoryOptions ¶
func ApplyFactoryOptions(opts []FactoryOption) FactoryConfig
ApplyFactoryOptions applies options to the default config and returns the result.
type FactoryOption ¶
type FactoryOption func(*FactoryConfig)
FactoryOption configures a parser factory at construction time.
func WithCandidateMode ¶
func WithCandidateMode(mode CandidateMode) FactoryOption
WithCandidateMode sets how aggressively the parser relies on the keyword index.
func WithFullCompatibility ¶
func WithFullCompatibility() FactoryOption
WithFullCompatibility explicitly sets both modes to compatibility defaults.
func WithIndexOnly ¶
func WithIndexOnly() FactoryOption
WithIndexOnly sets candidate mode to StrictIndex (no full scan fallback).
func WithRe2Only ¶
func WithRe2Only() FactoryOption
WithRe2Only sets regex mode to RE2-only (no regexp2 fallback).
type IndexStats ¶
type IndexStats struct {
TotalPatterns int
IndexedPatterns int
NoKeywordCount int
UniqueKeywords int
AvgKeywordsPerPattern float64
}
IndexStats provides statistics about the index.
type Orderable ¶
type Orderable interface {
Order() int
}
Orderable allows candidate slices to be stably sorted to preserve YAML order. Many parser DBs rely on "first match wins", so deterministic ordering matters.
type OrderedPattern ¶
OrderedPattern extends Pattern with position tracking for order-sensitive matching. Patterns implementing this interface will be sorted by position in FindCandidates.
type Pattern ¶
type Pattern interface {
GetRegex() string
}
Pattern is the interface that pattern types must implement.
type PatternIndex ¶
type PatternIndex[T Pattern] struct { // contains filtered or unexported fields }
PatternIndex provides fast keyword-based pattern lookup using Aho-Corasick. T must be a pointer type that implements the Pattern interface.
func NewPatternIndex ¶
func NewPatternIndex[T Pattern](patterns []T) *PatternIndex[T]
NewPatternIndex builds an index from patterns. Patterns are analyzed to extract keywords, which are then indexed using the Aho-Corasick algorithm for O(n) multi-pattern matching. If patterns implement OrderedPattern, their positions are set automatically.
func (*PatternIndex[T]) AllPatterns ¶
func (idx *PatternIndex[T]) AllPatterns() []T
AllPatterns returns all patterns (for fallback scenarios).
func (*PatternIndex[T]) FindCandidates ¶
func (idx *PatternIndex[T]) FindCandidates(text string) []T
FindCandidates returns patterns that might match the given text. Uses Aho-Corasick for O(n) keyword matching where n is text length. Returns patterns whose keywords were found, plus all patterns without keywords. If patterns implement OrderedPattern, results are sorted by original position.
func (*PatternIndex[T]) NoKeywordPatterns ¶
func (idx *PatternIndex[T]) NoKeywordPatterns() []T
NoKeywordPatterns returns patterns that couldn't be indexed.
func (*PatternIndex[T]) Stats ¶
func (idx *PatternIndex[T]) Stats() IndexStats
Stats returns statistics about the index.
type RegexCompiler ¶
type RegexCompiler struct {
// contains filtered or unexported fields
}
RegexCompiler provides regex compilation with configurable engine selection.
func NewRegexCompiler ¶
func NewRegexCompiler(mode RegexMode) *RegexCompiler
NewRegexCompiler creates a compiler with the specified regex mode.
func (*RegexCompiler) Compile ¶
func (rc *RegexCompiler) Compile(wrappedPattern string) (UniversalRegex, error)
Compile attempts to compile a pattern using the configured engine policy. The wrapped pattern should already include the PHP-style prefix matching wrapper.
func (*RegexCompiler) CompileSubmatch ¶
func (rc *RegexCompiler) CompileSubmatch(wrappedPattern string) (UniversalRegexSubmatch, error)
CompileSubmatch is like Compile, but returns a value that can also provide capture groups.
type RegexMode ¶
type RegexMode int
RegexMode controls which regex engine(s) to use for pattern compilation.
type UniversalRegex ¶
UniversalRegex is a small abstraction over the two regex engines we support. It lets the rest of the code treat patterns uniformly without caring about which underlying engine is used.
func CompileRegex ¶
func CompileRegex(wrappedPattern string) (UniversalRegex, error)
CompileRegex attempts to compile a pattern with RE2 first (fast path), and falls back to regexp2 if RE2 rejects it (e.g., lookarounds, backreferences). The wrapped pattern should already include the PHP-style prefix matching wrapper.
func NewRE2Regex ¶
func NewRE2Regex(re *regexp.Regexp) UniversalRegex
NewRE2Regex creates a UniversalRegex wrapper around a standard Go regexp.Regexp.
func NewRegexp2Regex ¶
func NewRegexp2Regex(re *regexp2.Regexp) UniversalRegex
NewRegexp2Regex creates a UniversalRegex wrapper around a regexp2.Regexp.
type UniversalRegexSubmatch ¶
type UniversalRegexSubmatch interface {
UniversalRegex
FindStringSubmatch(s string) ([]string, error)
}
UniversalRegexSubmatch is a UniversalRegex that can also return capture groups. The returned slice matches Go's regexp.FindStringSubmatch behavior: element 0 is the full match, element 1..n are capture groups. If there is no match, it returns (nil, nil).
func CompileRegexSubmatch ¶
func CompileRegexSubmatch(wrappedPattern string) (UniversalRegexSubmatch, error)
CompileRegexSubmatch is like CompileRegex, but returns a value that can also provide capture groups.
type YAMLHTTPHeader ¶
YAMLHTTPHeader is a type that can unmarshal YAML maps into http.Header. It allows fixture files to use map[string]string format while being unmarshaled directly into http.Header.
func (YAMLHTTPHeader) Header ¶
func (h YAMLHTTPHeader) Header() http.Header
Header returns the underlying http.Header.
func (*YAMLHTTPHeader) UnmarshalYAML ¶
func (h *YAMLHTTPHeader) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML implements yaml.Unmarshaler for YAMLHTTPHeader. It expects a YAML map with string keys and string values, and converts it into an http.Header.
type YAMLListDB ¶
type YAMLListDB[T Pattern] struct { Patterns []T Index *PatternIndex[T] Mode CandidateMode }
YAMLListDB is a small helper for parsers whose DB is a YAML sequence (list) of entries. It centralizes: precompiled candidate index, candidate mode, and compilation-at-init.
T is typically a pointer to an entry struct (e.g. *library.Entry) that implements Pattern.
func NewYAMLListDB ¶
func NewYAMLListDB[T Pattern](patterns []T, compile func(T, *RegexCompiler) error, opts ...FactoryOption) (*YAMLListDB[T], error)
NewYAMLListDB builds an index and optionally compiles patterns once at init. The compile callback may set compiled regex fields on the entry. In Re2Only mode, compilation failures are skipped (pattern left uncompiled) instead of failing.
func (*YAMLListDB[T]) Candidates ¶
func (db *YAMLListDB[T]) Candidates(ua string) []T
Candidates returns ordered candidates for a UA, following the configured mode.