common

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Jan 29, 2026 License: LGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package common provides reusable components for device detection parsers.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildByMatch

func BuildByMatch(template string, matches []string) string

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

func BuildModel(template string, matches []string) string

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

func ExtractKeywords(pattern string) []string

ExtractKeywords extracts indexable keywords from a regex pattern. These are literal strings that MUST appear in any matching input.

func IsUsefulKeyword

func IsUsefulKeyword(kw string) bool

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

func WrapDeviceDetectorPattern(pattern string) string

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

type OrderedPattern interface {
	Pattern
	GetPosition() int
	SetPosition(int)
}

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.

const (
	// Auto tries RE2 first, then falls back to regexp2 for PCRE features.
	Auto RegexMode = iota
	// Re2Only only uses Go's regexp (RE2); patterns that can't compile are skipped.
	Re2Only
)

type UniversalRegex

type UniversalRegex interface {
	MatchString(s string) (bool, error)
}

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

type YAMLHTTPHeader http.Header

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.

Jump to

Keyboard shortcuts

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