gitlab.com/evatix-go/core@v1.3.55/regexnew/LazyRegex.go (about)

     1  package regexnew
     2  
     3  import (
     4  	"errors"
     5  	"regexp"
     6  )
     7  
     8  // LazyRegex
     9  //
    10  //  lazy regex for future unwrapping or compiled but only once.
    11  type LazyRegex struct {
    12  	isCompiled   bool
    13  	isApplicable bool // no err, pattern defined, not null
    14  	pattern      string
    15  	regex        *regexp.Regexp
    16  	compiledErr  error
    17  	compiler     func(pattern string) (
    18  		*regexp.Regexp, error,
    19  	) // must be a locked function, cannot use non lock version
    20  }
    21  
    22  func (it *LazyRegex) IsNull() bool {
    23  	return it == nil
    24  }
    25  
    26  func (it *LazyRegex) IsDefined() bool {
    27  	return it != nil && it.pattern != "" && it.compiler != nil
    28  }
    29  
    30  func (it *LazyRegex) IsUndefined() bool {
    31  	return it == nil || it.pattern == "" || it.compiler == nil
    32  }
    33  
    34  // IsApplicable
    35  //
    36  //  it unwraps the regex and compiles so take memory for once.
    37  func (it *LazyRegex) IsApplicable() bool {
    38  	if it.isApplicable {
    39  		return true
    40  	}
    41  
    42  	if it.IsUndefined() {
    43  		return false
    44  	}
    45  
    46  	// compile required
    47  	// fine to swallow err
    48  	// updates isApplicable
    49  	it.Compile()
    50  
    51  	return it.isApplicable
    52  }
    53  
    54  // Compile
    55  //
    56  //  it is done through the locking mechanism
    57  func (it *LazyRegex) Compile() (regex *regexp.Regexp, err error) {
    58  	if it.IsCompiled() {
    59  		return it.regex, it.compiledErr
    60  	}
    61  
    62  	if it.IsUndefined() {
    63  		return nil, errors.New("lazy regex is undefined or nil")
    64  	}
    65  
    66  	// defined
    67  	compiledRegex, regExErr := it.compiler(it.pattern) // compiler should be locked func, must be
    68  	it.isApplicable = compiledRegex != nil && regExErr == nil
    69  	it.regex = compiledRegex
    70  	it.compiledErr = regExErr
    71  	it.isCompiled = true
    72  
    73  	return compiledRegex, regExErr
    74  }
    75  
    76  func (it *LazyRegex) CompileMust() (regex *regexp.Regexp) {
    77  	regexCompiled, err := it.Compile()
    78  
    79  	if err != nil {
    80  		panic(err)
    81  	}
    82  
    83  	return regexCompiled
    84  }
    85  
    86  func (it *LazyRegex) IsCompiled() bool {
    87  	return it != nil && it.isCompiled
    88  }
    89  
    90  func (it *LazyRegex) OnRequiredCompiled() error {
    91  	if it == nil {
    92  		return errors.New("nil LazyRegex cannot compile")
    93  	}
    94  
    95  	if it.IsCompiled() {
    96  		return it.compiledErr
    97  	}
    98  
    99  	_, err := it.Compile()
   100  
   101  	return err
   102  }
   103  
   104  func (it *LazyRegex) OnRequiredCompiledMust() {
   105  	err := it.CompileMust()
   106  
   107  	if err != nil {
   108  		panic(err)
   109  	}
   110  }
   111  
   112  func (it *LazyRegex) HasError() bool {
   113  	// fine to swallow
   114  	it.OnRequiredCompiled()
   115  
   116  	return it != nil && it.compiledErr != nil
   117  }
   118  
   119  func (it *LazyRegex) HasAnyIssues() bool {
   120  	if it == nil {
   121  		return true
   122  	}
   123  
   124  	return !it.IsApplicable()
   125  }
   126  
   127  func (it *LazyRegex) IsInvalid() bool {
   128  	if it == nil {
   129  		return true
   130  	}
   131  
   132  	return !it.IsApplicable()
   133  }
   134  
   135  func (it *LazyRegex) CompiledError() error {
   136  	return it.OnRequiredCompiled()
   137  }
   138  
   139  func (it *LazyRegex) Error() error {
   140  	return it.OnRequiredCompiled()
   141  }
   142  
   143  func (it *LazyRegex) MustBeSafe() {
   144  	compiledErr := it.CompiledError()
   145  
   146  	if compiledErr != nil {
   147  		panic(compiledErr)
   148  	}
   149  }
   150  
   151  func (it *LazyRegex) String() (pattern string) {
   152  	if it == nil {
   153  		return ""
   154  	}
   155  
   156  	return it.pattern
   157  }
   158  
   159  func (it *LazyRegex) FullString() (detail string) {
   160  	if it == nil {
   161  		return ""
   162  	}
   163  
   164  	isApplicable := it.IsApplicable()
   165  	isCompiled := it.IsCompiled()
   166  	compiledErr := it.CompiledError()
   167  
   168  	newMap := map[string]interface{}{
   169  		"pattern":      it.Pattern(),
   170  		"isCompiled":   isCompiled,
   171  		"isApplicable": isApplicable,
   172  		"error":        compiledErr,
   173  	}
   174  
   175  	return prettyJson(newMap)
   176  }
   177  
   178  func (it *LazyRegex) Pattern() (pattern string) {
   179  	if it == nil {
   180  		return ""
   181  	}
   182  
   183  	return it.pattern
   184  }
   185  
   186  func (it *LazyRegex) MatchError(matchingPattern string) error {
   187  	regEx, compiledErr := it.Compile()
   188  
   189  	if regEx != nil && regEx.MatchString(matchingPattern) {
   190  		return nil
   191  	}
   192  
   193  	return regExMatchValidationError(
   194  		it.pattern,
   195  		matchingPattern,
   196  		compiledErr,
   197  		regEx)
   198  }
   199  
   200  // MatchUsingFuncError
   201  //
   202  //  creates new regex using lock
   203  //  and then calls match.
   204  //  On condition mismatch returns error
   205  //  or else nil
   206  func (it *LazyRegex) MatchUsingFuncError(
   207  	comparing string,
   208  	matchFunc RegexValidationFunc,
   209  ) error {
   210  	regEx, compiledErr := it.Compile()
   211  
   212  	if regEx != nil && matchFunc(regEx, comparing) {
   213  		return nil
   214  	}
   215  
   216  	return regExMatchValidationError(
   217  		it.pattern,
   218  		comparing,
   219  		compiledErr,
   220  		regEx)
   221  }
   222  
   223  func (it *LazyRegex) IsMatch(
   224  	comparing string,
   225  ) bool {
   226  	regEx, compiledErr := it.Compile()
   227  
   228  	if regEx == nil || compiledErr != nil {
   229  		return false
   230  	}
   231  
   232  	return regEx.MatchString(comparing)
   233  }
   234  
   235  func (it *LazyRegex) IsMatchBytes(
   236  	comparingBytes []byte,
   237  ) bool {
   238  	regEx, compiledErr := it.Compile()
   239  
   240  	if regEx == nil || compiledErr != nil {
   241  		return false
   242  	}
   243  
   244  	return regEx.Match(comparingBytes)
   245  }
   246  
   247  func (it *LazyRegex) IsFailedMatch(
   248  	comparing string,
   249  ) bool {
   250  	regEx, compiledErr := it.Compile()
   251  
   252  	if regEx == nil || compiledErr != nil {
   253  		return true
   254  	}
   255  
   256  	return !regEx.MatchString(comparing)
   257  }
   258  
   259  func (it *LazyRegex) IsFailedMatchBytes(
   260  	comparingBytes []byte,
   261  ) bool {
   262  	regEx, compiledErr := it.Compile()
   263  
   264  	if regEx == nil || compiledErr != nil {
   265  		return true
   266  	}
   267  
   268  	return !regEx.Match(comparingBytes)
   269  }
   270  
   271  func (it *LazyRegex) FirstMatchLine(
   272  	content string,
   273  ) (firstMatch string, isInvalidMatch bool) {
   274  	regEx, compiledErr := it.Compile()
   275  
   276  	if regEx == nil || compiledErr != nil {
   277  		return "", true
   278  	}
   279  
   280  	lines := regEx.FindStringSubmatch(content)
   281  
   282  	if len(lines) > 0 {
   283  		// valid
   284  		return lines[0], false
   285  	}
   286  
   287  	// invalid
   288  	return "", true
   289  }