matchtree

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2025 License: MIT Imports: 6 Imported by: 0

README

matchtree

Go Reference Coverage

matchtree is a generic Go package that provides a tree structure for efficient, multi-dimensional pattern matching. It allows users to define rules based on a sequence of various data types (strings, integers, intervals, and regular expressions) and retrieve associated values using a sequence of keys.


Features

  • Multi-Dimensional Matching: Define matching rules across a sequence of different data types (dimensions).
  • Diverse Pattern Types: Supports matching against:
    • String (exact match for string)
    • Integer (exact match for int64)
    • IntegerInterval (range match for int64)
    • NumberInterval (range match for float64)
    • Regexp (regular expression match for string)
  • Wildcard and Inverse Matching: Supports "match any" and "match none of these" patterns.
  • Priority-Based Results: Rules can be assigned a priority, and search results are sorted by priority (descending) and then insertion order.

Quick Start

package main

import (
    "fmt"
    "github.com/roy2220/matchtree"
)

type Role struct {
    Name string
}

func main() {
    // Define tree structure: Gender -> Age -> Height
    tree := matchtree.NewMatchTree[Role]([]matchtree.MatchType{
        matchtree.MatchString,
        matchtree.MatchIntegerInterval,
        matchtree.MatchNumberInterval,
    })

    // Add rule #1:
    //   WHEN Gender=any Age=[18,30] Height=[165.0,185.0]
    //   THEN Role=Athlete
    tree.AddRule(matchtree.MatchRule[Role]{
        Patterns: []matchtree.MatchPattern{
            {Type: matchtree.MatchString, IsAny: true},
            {Type: matchtree.MatchIntegerInterval, IntegerIntervals: []matchtree.IntegerInterval{
                {Min: matchtree.Int64Ptr(18), Max: matchtree.Int64Ptr(30)},
            }},
            {Type: matchtree.MatchNumberInterval, NumberIntervals: []matchtree.NumberInterval{
                {Min: matchtree.Float64Ptr(165.0), Max: matchtree.Float64Ptr(185.0)},
            }},
        },
        Value:    Role{Name: "Athlete"},
        Priority: 10,
    })

    // Add rule #2:
    //   WHEN Gender=female Age=[25,40] Height=any
    //   THEN Role=Manager
    tree.AddRule(matchtree.MatchRule[Role]{
        Patterns: []matchtree.MatchPattern{
            {Type: matchtree.MatchString, Strings: []string{"female"}},
            {Type: matchtree.MatchIntegerInterval, IntegerIntervals: []matchtree.IntegerInterval{
                {Min: matchtree.Int64Ptr(25), Max: matchtree.Int64Ptr(40)},
            }},
            {Type: matchtree.MatchNumberInterval, IsAny: true},
        },
        Value:    Role{Name: "Manager"},
        Priority: 5,
    })

    // Search with keys: Gender=female Age=35 Height=170.0
    results, _ := tree.Search([]matchtree.MatchKey{
        {Type: matchtree.MatchString, String: "female"},
        {Type: matchtree.MatchIntegerInterval, Integer: 35},
        {Type: matchtree.MatchNumberInterval, Number: 170.0},
    })
    for _, role := range results {
        fmt.Println(role.Name) // Output: Manager
    }
}

Pattern Examples

Exact Match
// Match 'male' or 'female' strings
{Type: matchtree.MatchString, Strings: []string{"male", "female"}}

// Match integers 18, 21, or 25
{Type: matchtree.MatchInteger, Integers: []int64{18, 21, 25}}
Interval Match
// Closed integer interval [18, 65]
{Type: matchtree.MatchIntegerInterval, IntegerIntervals: []matchtree.IntegerInterval{
    {Min: matchtree.Int64Ptr(18), Max: matchtree.Int64Ptr(65)},
}}

// Open float interval (160.0, 180.0)
{Type: matchtree.MatchNumberInterval, NumberIntervals: []matchtree.NumberInterval{
    {Min: matchtree.Float64Ptr(160.0), MinIsExcluded: true,
     Max: matchtree.Float64Ptr(180.0), MaxIsExcluded: true},
}}

// Half-open interval [18, infinity)
{Type: matchtree.MatchIntegerInterval, IntegerIntervals: []matchtree.IntegerInterval{
    {Min: matchtree.Int64Ptr(18)},
}}
Wildcard
// Match any string
{Type: matchtree.MatchString, IsAny: true}
Inverse Match
// Match any string except "admin" and "root"
{Type: matchtree.MatchString, IsInverse: true, Strings: []string{"admin", "root"}}

// Match any integer except 0 and 100
{Type: matchtree.MatchInteger, IsInverse: true, Integers: []int64{0, 100}}

// Match any integer except in the intervals [0, 10] and [20, 30]
{Type: matchtree.MatchIntegerInterval, IsInverse: true, IntegerIntervals: []matchtree.IntegerInterval{
    {Min: matchtree.Int64Ptr(0), Max: matchtree.Int64Ptr(10)},
    {Min: matchtree.Int64Ptr(20), Max: matchtree.Int64Ptr(30)},
}}
Regular Expression
// Match strings starting with "user_" followed by one or more digits
{Type: matchtree.MatchRegexp, Regexp: "^user_[0-9]+$"}

Priority and Result Ordering

Results are sorted by:

  1. Priority (descending) - higher priority rules appear first.
  2. Insertion order (ascending) - earlier rules appear first when priorities are equal.

Options

TreatEmptyPatternAsAny
tree.AddRule(rule, matchtree.TreatEmptyPatternAsAny())

This option treats patterns that are IsEmpty() (i.e., matchtree.MatchPattern{}) as a wildcard. This allows for partial rule definitions where an omitted pattern means "match anything for this dimension."


License

MIT

Documentation

Index

Constants

View Source
const (
	// MatchNone is a placeholder, typically used for leaf nodes.
	MatchNone = MatchType(iota)
	// MatchString represents a string type.
	MatchString
	// MatchInteger represents an integer type.
	MatchInteger
	// MatchIntegerInterval represents an integer interval type.
	MatchIntegerInterval
	// MatchNumberInterval represents a floating-point number interval type.
	MatchNumberInterval
	// MatchRegexp represents a regular expression type.
	MatchRegexp
	// NumberOfMatchTypes indicates the total number of defined match types.
	NumberOfMatchTypes = int(iota)
)

Variables

This section is empty.

Functions

func Float64Ptr

func Float64Ptr(x float64) *float64

Float64Ptr is a helper function to create a pointer to a float64 value.

func Int64Ptr

func Int64Ptr(x int64) *int64

Int64Ptr is a helper function to create a pointer to an int64 value.

Types

type AddRuleOptionFunc added in v0.3.0

type AddRuleOptionFunc func(addRuleOptions) addRuleOptions

AddRuleOptionFunc defines a function type for configuring the AddRule operation.

func TreatEmptyPatternAsAny added in v0.3.0

func TreatEmptyPatternAsAny() AddRuleOptionFunc

TreatEmptyPatternAsAny configures the AddRule operation to treat empty patterns as wildcards.

type IntegerInterval

type IntegerInterval struct {
	Min           *int64 `json:"min"`
	MinIsExcluded bool   `json:"min_is_excluded"`
	Max           *int64 `json:"max"`
	MaxIsExcluded bool   `json:"max_is_excluded"`
}

IntegerInterval represents a closed, open, or half-open interval for integers.

func (IntegerInterval) Contains

func (i IntegerInterval) Contains(x int64) bool

Contains checks if the given integer `x` falls within the interval.

func (IntegerInterval) Equals

func (i IntegerInterval) Equals(other IntegerInterval) bool

Equals checks if two IntegerIntervals are equal.

type MatchKey

type MatchKey struct {
	Type MatchType `json:"type"`

	// String for MatchString, MatchRegexp types.
	String string `json:"string"`

	// Integer for MatchInteger, MatchIntegerInterval types.
	Integer int64 `json:"integer"`

	// Number for MatchNumberInterval type.
	Number float64 `json:"number"`
}

MatchKey represents a single key to search within the MatchTree. It specifies the type and the value for that key.

type MatchPattern

type MatchPattern struct {
	Type MatchType `json:"type"`

	// IsAny indicates if this pattern matches any value for its type.
	IsAny bool `json:"is_any"`

	// IsInverse indicates if this pattern matches any value NOT in its specified list/intervals.
	IsInverse bool `json:"is_inverse"`

	// Strings for MatchString type.
	Strings []string `json:"strings"`

	// Integers for MatchInteger type.
	Integers []int64 `json:"integers"`

	// IntegerIntervals for MatchIntegerInterval type.
	IntegerIntervals []IntegerInterval `json:"integer_intervals"`

	// NumberIntervals for MatchNumberInterval type.
	NumberIntervals []NumberInterval `json:"number_intervals"`

	// Regexp for MatchRegexp type.
	Regexp string `json:"regexp"`
	// contains filtered or unexported fields
}

MatchPattern defines a single pattern within a MatchRule. It can be an 'any' pattern, an 'inverse' pattern, or a specific value/interval pattern.

func (*MatchPattern) IsEmpty added in v0.3.0

func (p *MatchPattern) IsEmpty() bool

IsEmpty checks if the MatchPattern is empty (i.e., has no specific matching criteria).

type MatchRule

type MatchRule[T any] struct {
	Patterns []MatchPattern `json:"patterns"`
	Value    T              `json:"value"`
	Priority int            `json:"priority"`
}

MatchRule represents a single rule to be added to the MatchTree. It consists of a sequence of patterns, a value to associate, and a priority.

type MatchTree

type MatchTree[T any] struct {
	// contains filtered or unexported fields
}

MatchTree is a generic tree structure for efficient pattern matching. It allows defining rules with various pattern types and searching for matching values based on keys.

func NewMatchTree

func NewMatchTree[T any](types []MatchType) *MatchTree[T]

NewMatchTree creates a new MatchTree with the specified sequence of MatchTypes. The order of types matters and defines the structure of the tree.

func (*MatchTree[T]) AddRule

func (t *MatchTree[T]) AddRule(rule MatchRule[T], optionFuncs ...AddRuleOptionFunc) error

AddRule adds a new MatchRule to the MatchTree. It returns an error if the rule's patterns do not match the tree's defined types.

func (*MatchTree[T]) Search

func (t *MatchTree[T]) Search(keys []MatchKey) ([]T, error)

Search traverses the MatchTree with the given keys and returns a slice of matching values. The returned values are sorted by priority (descending) and then by their insertion order. It returns an error if the keys do not match the tree's defined types.

type MatchType

type MatchType int

MatchType defines the type of data a pattern or key represents.

func ParseMatchType

func ParseMatchType(s string) (MatchType, error)

ParseMatchType parses a string into a MatchType.

func (MatchType) MarshalJSON

func (t MatchType) MarshalJSON() ([]byte, error)

MarshalJSON marshals the MatchType to its string representation.

func (MatchType) String

func (t MatchType) String() string

String returns the string representation of a MatchType.

func (*MatchType) UnmarshalJSON

func (t *MatchType) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals a JSON string into a MatchType.

type NumberInterval

type NumberInterval struct {
	Min           *float64 `json:"min"`
	MinIsExcluded bool     `json:"min_is_excluded"`
	Max           *float64 `json:"max"`
	MaxIsExcluded bool     `json:"max_is_excluded"`
}

NumberInterval represents a closed, open, or half-open interval for floating-point numbers.

func (NumberInterval) Contains

func (i NumberInterval) Contains(x float64) bool

Contains checks if the given floating-point number `x` falls within the interval, considering floating-point precision.

func (NumberInterval) Equals

func (i NumberInterval) Equals(other NumberInterval) bool

Equals checks if two NumberIntervals are equal, considering floating-point precision.

Jump to

Keyboard shortcuts

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