github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/common/dtypeutils/dtypeutils.go (about)

     1  /*
     2  Copyright 2023.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package dtypeutils
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"math"
    23  	"regexp"
    24  	"strconv"
    25  	"strings"
    26  	"unsafe"
    27  )
    28  
    29  type TimeRange struct {
    30  	StartEpochMs uint64
    31  	EndEpochMs   uint64
    32  }
    33  
    34  type MetricsTimeRange struct {
    35  	StartEpochSec uint32
    36  	EndEpochSec   uint32
    37  }
    38  
    39  // returns true if [earliest_ts, latest_ts] overlaps with tsVal
    40  func (tsVal *TimeRange) CheckRangeOverLap(earliest_ts, latest_ts uint64) bool {
    41  
    42  	if (earliest_ts >= tsVal.StartEpochMs && earliest_ts <= tsVal.EndEpochMs) ||
    43  		(latest_ts >= tsVal.StartEpochMs && latest_ts <= tsVal.EndEpochMs) ||
    44  		(earliest_ts <= tsVal.StartEpochMs && latest_ts >= tsVal.EndEpochMs) {
    45  		return true
    46  	}
    47  	return false
    48  }
    49  
    50  // returns true if [earliest_ts, latest_ts] overlaps with tsVal
    51  func (tsVal *MetricsTimeRange) CheckRangeOverLap(earliest_ts, latest_ts uint32) bool {
    52  
    53  	if (earliest_ts >= tsVal.StartEpochSec && earliest_ts <= tsVal.EndEpochSec) ||
    54  		(latest_ts >= tsVal.StartEpochSec && latest_ts <= tsVal.EndEpochSec) ||
    55  		(earliest_ts <= tsVal.StartEpochSec && latest_ts >= tsVal.EndEpochSec) {
    56  		return true
    57  	}
    58  	return false
    59  }
    60  
    61  // returns true if [lowTs, highTs] is fully enclosed within timeRange
    62  func (tr *TimeRange) AreTimesFullyEnclosed(lowTs, highTs uint64) bool {
    63  
    64  	if lowTs >= tr.StartEpochMs && lowTs <= tr.EndEpochMs &&
    65  		highTs >= tr.StartEpochMs && highTs <= tr.EndEpochMs {
    66  		return true
    67  	}
    68  	return false
    69  }
    70  
    71  func (tsVal *TimeRange) CheckInRange(timeStamp uint64) bool {
    72  
    73  	if tsVal.StartEpochMs <= timeStamp && timeStamp <= tsVal.EndEpochMs {
    74  		return true
    75  	}
    76  	return false
    77  }
    78  
    79  func (tsVal *MetricsTimeRange) CheckInRange(timeStamp uint32) bool {
    80  
    81  	if tsVal.StartEpochSec <= timeStamp && timeStamp <= tsVal.EndEpochSec {
    82  		return true
    83  	}
    84  	return false
    85  }
    86  
    87  func ConvertToUInt(exp interface{}, bytes int) (uint64, error) {
    88  	str := fmt.Sprint(exp)
    89  	return strconv.ParseUint(str, 10, bytes)
    90  }
    91  
    92  func ConvertToInt(exp interface{}, bytes int) (int64, error) {
    93  	str := fmt.Sprint(exp)
    94  	return strconv.ParseInt(str, 10, bytes)
    95  }
    96  
    97  func ConvertToFloat(exp interface{}, bytes int) (float64, error) {
    98  	str := fmt.Sprint(exp)
    99  	return strconv.ParseFloat(str, bytes)
   100  }
   101  
   102  func ConvertToFloatAndReturnString(exp interface{}, bytes int) (float64, string, error) {
   103  	str := fmt.Sprint(exp)
   104  	floatExp, err := strconv.ParseFloat(str, bytes)
   105  	if err != nil {
   106  		return 0, "", err
   107  	}
   108  	return floatExp, str, nil
   109  }
   110  
   111  func ConvertExpToType(valueToConvert interface{}, knownType interface{}) (interface{}, error) {
   112  
   113  	switch knownType.(type) {
   114  	case uint8:
   115  		retVal, ok := valueToConvert.(uint8)
   116  		if !ok {
   117  			retVal, err := ConvertToUInt(valueToConvert, 8)
   118  			return uint8(retVal), err
   119  		} else {
   120  			return retVal, nil
   121  		}
   122  	case uint16:
   123  		retVal, ok := valueToConvert.(uint16)
   124  		if !ok {
   125  			retVal, err := ConvertToUInt(valueToConvert, 16)
   126  			return uint16(retVal), err
   127  		} else {
   128  			return retVal, nil
   129  		}
   130  	case uint32:
   131  		retVal, ok := valueToConvert.(uint32)
   132  		if !ok {
   133  			retVal, err := ConvertToUInt(valueToConvert, 32)
   134  			return uint32(retVal), err
   135  		} else {
   136  			return retVal, nil
   137  		}
   138  	case uint64:
   139  		retVal, ok := valueToConvert.(uint64)
   140  		if !ok {
   141  			return ConvertToUInt(valueToConvert, 64)
   142  		} else {
   143  			return retVal, nil
   144  		}
   145  	case int8:
   146  		retVal, ok := valueToConvert.(int8)
   147  		if !ok {
   148  			retVal, err := ConvertToInt(valueToConvert, 8)
   149  			return int8(retVal), err
   150  		} else {
   151  			return retVal, nil
   152  		}
   153  	case int16:
   154  		retVal, ok := valueToConvert.(int16)
   155  		if !ok {
   156  			retVal, err := ConvertToInt(valueToConvert, 16)
   157  			return int16(retVal), err
   158  		} else {
   159  			return retVal, nil
   160  		}
   161  	case int32:
   162  		retVal, ok := valueToConvert.(int32)
   163  		if !ok {
   164  			retVal, err := ConvertToInt(valueToConvert, 32)
   165  			return int32(retVal), err
   166  		} else {
   167  			return retVal, nil
   168  		}
   169  	case int64:
   170  		retVal, ok := valueToConvert.(int64)
   171  		if !ok {
   172  			return ConvertToInt(valueToConvert, 64)
   173  		} else {
   174  			return retVal, nil
   175  		}
   176  	case float64:
   177  		retVal, ok := valueToConvert.(float64)
   178  		if !ok {
   179  			return ConvertToFloat(valueToConvert, 64)
   180  		} else {
   181  			return retVal, nil
   182  		}
   183  	case bool:
   184  		retVal, ok := valueToConvert.(bool)
   185  		if !ok {
   186  			retVal, err := ConvertToInt(valueToConvert, 8)
   187  
   188  			if err != nil {
   189  				return int8(0), err
   190  			}
   191  			number := int8(retVal)
   192  
   193  			if number == int8(0) {
   194  				return false, nil
   195  			} else {
   196  				return true, nil
   197  			}
   198  		} else {
   199  			return retVal, nil
   200  		}
   201  	case string:
   202  		retVal, ok := valueToConvert.(string)
   203  		if !ok {
   204  			return fmt.Sprint(valueToConvert), nil
   205  		} else {
   206  			return retVal, nil
   207  		}
   208  	}
   209  	return nil, errors.New("invalid conversion type")
   210  }
   211  
   212  // TODO: add logic for overflow/underflow cases
   213  func Multiply(left interface{}, right interface{}) (interface{}, error) {
   214  
   215  	switch left.(type) {
   216  	case uint8:
   217  		a := left.(uint8)
   218  		b := right.(uint8)
   219  		c := uint16(a) * uint16(b)
   220  		return c, nil
   221  
   222  	case uint16:
   223  		a := left.(uint16)
   224  		b := right.(uint16)
   225  		c := uint32(a) * uint32(b)
   226  		return c, nil
   227  
   228  	case uint32:
   229  		a := left.(uint32)
   230  		b := right.(uint32)
   231  		c := uint64(a) * uint64(b)
   232  		return c, nil
   233  
   234  	case uint64:
   235  		a := left.(uint64)
   236  		b := right.(uint64)
   237  		c := a * b
   238  		return c, nil
   239  
   240  	case int8:
   241  		a := left.(int8)
   242  		b := right.(int8)
   243  		c := int16(a) * int16(b)
   244  		return c, nil
   245  
   246  	case int16:
   247  		a := left.(int16)
   248  		b := right.(int16)
   249  		c := int32(a) * int32(b)
   250  		return c, nil
   251  
   252  	case int32:
   253  		a := left.(int32)
   254  		b := right.(int32)
   255  		c := int64(a) * int64(b)
   256  		return c, nil
   257  
   258  	case int64:
   259  		a := left.(int64)
   260  		b := right.(int64)
   261  		c := a * b
   262  		if a == 0 || b == 0 {
   263  			return c, nil
   264  		}
   265  
   266  		if (c < 0) == ((a < 0) != (b < 0)) {
   267  			if c/b == a {
   268  				return c, nil
   269  			}
   270  		}
   271  		return c, errors.New("Overflow")
   272  	case float64:
   273  		c := left.(float64) * right.(float64)
   274  		if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) {
   275  			return c, nil
   276  		}
   277  		return c, errors.New("Overflow")
   278  	}
   279  
   280  	return "", errors.New("invalid type for multiply")
   281  
   282  }
   283  
   284  // TODO: add logic for overflow/underflow cases
   285  func Add(left interface{}, right interface{}) (interface{}, error) {
   286  
   287  	switch left.(type) {
   288  	case uint8:
   289  		c := left.(uint8) + right.(uint8)
   290  		if (c > left.(uint8)) == (right.(uint8) > 0) {
   291  			return c, nil
   292  		}
   293  		return c, errors.New("Overflow")
   294  	case uint16:
   295  		c := left.(uint16) + right.(uint16)
   296  		if (c > left.(uint16)) == (right.(uint16) > 0) {
   297  			return c, nil
   298  		}
   299  		return c, errors.New("Overflow")
   300  	case uint32:
   301  		c := left.(uint32) + right.(uint32)
   302  		if (c > left.(uint32)) == (right.(uint32) > 0) {
   303  			return c, nil
   304  		}
   305  		return c, errors.New("Overflow")
   306  	case uint64:
   307  		c := left.(uint64) + right.(uint64)
   308  		if (c > left.(uint64)) == (right.(uint64) > 0) {
   309  			return c, nil
   310  		}
   311  		return c, errors.New("Overflow")
   312  	case int8:
   313  		c := left.(int8) + right.(int8)
   314  		if (c > left.(int8)) == (right.(int8) > 0) {
   315  			return c, nil
   316  		}
   317  		return c, errors.New("Overflow")
   318  	case int16:
   319  		c := left.(int16) + right.(int16)
   320  		if (c > left.(int16)) == (right.(int16) > 0) {
   321  			return c, nil
   322  		}
   323  		return c, errors.New("Overflow")
   324  	case int32:
   325  		c := left.(int32) + right.(int32)
   326  		if (c > left.(int32)) == (right.(int32) > 0) {
   327  			return c, nil
   328  		}
   329  		return c, errors.New("Overflow")
   330  	case int64:
   331  		c := left.(int64) + right.(int64)
   332  		if (c > left.(int64)) == (right.(int64) > 0) {
   333  			return c, nil
   334  		}
   335  		return c, errors.New("Overflow")
   336  	case int:
   337  		c := left.(int) + right.(int)
   338  		if (c > left.(int)) == (right.(int) > 0) {
   339  			return c, nil
   340  		}
   341  		return c, errors.New("Overflow")
   342  	case float64:
   343  		c := left.(float64) + right.(float64)
   344  		if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) {
   345  			return c, nil
   346  		}
   347  		return c, errors.New("Overflow")
   348  	}
   349  
   350  	return "", errors.New("invalid type for addition")
   351  }
   352  
   353  // TODO: add logic for overflow/underflow cases
   354  func Subtract(left interface{}, right interface{}) (interface{}, error) {
   355  
   356  	switch left.(type) {
   357  	case uint8:
   358  		c := left.(uint8) - right.(uint8)
   359  		if (c < left.(uint8)) == (right.(uint8) > 0) {
   360  			return c, nil
   361  		}
   362  		return c, errors.New("Overflow")
   363  
   364  	case uint16:
   365  		c := left.(uint16) - right.(uint16)
   366  		if (c < left.(uint16)) == (right.(uint16) > 0) {
   367  			return c, nil
   368  		}
   369  		return c, errors.New("Overflow")
   370  	case uint32:
   371  		c := left.(uint32) - right.(uint32)
   372  		if (c < left.(uint32)) == (right.(uint32) > 0) {
   373  			return c, nil
   374  		}
   375  		return c, errors.New("Overflow")
   376  	case uint64:
   377  		c := left.(uint64) - right.(uint64)
   378  		if (c < left.(uint64)) == (right.(uint64) > 0) {
   379  			return c, nil
   380  		}
   381  		return c, errors.New("Overflow")
   382  	case int8:
   383  		c := left.(int8) - right.(int8)
   384  		if (c < left.(int8)) == (right.(int8) > 0) {
   385  			return c, nil
   386  		}
   387  		return c, errors.New("Overflow")
   388  	case int16:
   389  		c := left.(int16) - right.(int16)
   390  		if (c < left.(int16)) == (right.(int16) > 0) {
   391  			return c, nil
   392  		}
   393  		return c, errors.New("Overflow")
   394  	case int32:
   395  		c := left.(int32) - right.(int32)
   396  		if (c < left.(int32)) == (right.(int32) > 0) {
   397  			return c, nil
   398  		}
   399  		return c, errors.New("Overflow")
   400  	case int64:
   401  		c := left.(int64) - right.(int64)
   402  		if (c < left.(int64)) == (right.(int64) > 0) {
   403  			return c, nil
   404  		}
   405  		return c, errors.New("Overflow")
   406  	case float64:
   407  		c := left.(float64) - right.(float64)
   408  		if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) {
   409  			return c, nil
   410  		}
   411  		return c, errors.New("Overflow")
   412  	}
   413  
   414  	return "", errors.New("invalid type for subtraction")
   415  }
   416  
   417  // TODO: add logic for overflow/underflow cases and divide by 0 verification
   418  func Divide(left interface{}, right interface{}) (interface{}, error) {
   419  
   420  	switch left.(type) {
   421  	case uint8:
   422  		if right.(uint8) == 0 {
   423  			return nil, errors.New("cannot divide by zero")
   424  		}
   425  		return left.(uint8) / right.(uint8), nil
   426  	case uint16:
   427  		if right.(uint16) == 0 {
   428  			return nil, errors.New("cannot divide by zero")
   429  		}
   430  		return left.(uint16) / right.(uint16), nil
   431  	case uint32:
   432  		if right.(uint32) == 0 {
   433  			return nil, errors.New("cannot divide by zero")
   434  		}
   435  		return left.(uint32) / right.(uint32), nil
   436  	case uint64:
   437  		if right.(uint64) == 0 {
   438  			return nil, errors.New("cannot divide by zero")
   439  		}
   440  		return left.(uint64) / right.(uint64), nil
   441  	case int8:
   442  		if right.(int8) == 0 {
   443  			return nil, errors.New("cannot divide by zero")
   444  		}
   445  		return left.(int8) / right.(int8), nil
   446  	case int16:
   447  		if right.(int16) == 0 {
   448  			return nil, errors.New("cannot divide by zero")
   449  		}
   450  		return left.(int16) / right.(int16), nil
   451  	case int32:
   452  		if right.(int32) == 0 {
   453  			return nil, errors.New("cannot divide by zero")
   454  		}
   455  		return left.(int32) / right.(int32), nil
   456  	case int64:
   457  		if right.(int64) == 0 {
   458  			return nil, errors.New("cannot divide by zero")
   459  		}
   460  		return left.(int64) / right.(int64), nil
   461  	case float64:
   462  		if right.(float64) == 0 {
   463  			return nil, errors.New("cannot divide by zero")
   464  		}
   465  		c := left.(float64) / right.(float64)
   466  		if c != float64(math.Inf(1)) && c != float64(math.Inf(-1)) {
   467  			return c, nil
   468  		}
   469  		return c, errors.New("Overflow")
   470  	}
   471  
   472  	return "", errors.New("invalid type for divide")
   473  
   474  }
   475  
   476  // TODO: divide by 0 verification
   477  func Modulo(left interface{}, right interface{}) (interface{}, error) {
   478  
   479  	switch left.(type) {
   480  	case uint8:
   481  		if right.(uint8) == 0 {
   482  			return nil, errors.New("cannot divide by zero")
   483  		}
   484  		return left.(uint8) % right.(uint8), nil
   485  	case uint16:
   486  		if right.(uint16) == 0 {
   487  			return nil, errors.New("cannot divide by zero")
   488  		}
   489  		return left.(uint16) % right.(uint16), nil
   490  	case uint32:
   491  		if right.(uint32) == 0 {
   492  			return nil, errors.New("cannot divide by zero")
   493  		}
   494  		return left.(uint32) % right.(uint32), nil
   495  	case uint64:
   496  		if right.(uint64) == 0 {
   497  			return nil, errors.New("cannot divide by zero")
   498  		}
   499  		return left.(uint64) % right.(uint64), nil
   500  	case int8:
   501  		if right.(int8) == 0 {
   502  			return nil, errors.New("cannot divide by zero")
   503  		}
   504  		return left.(int8) % right.(int8), nil
   505  	case int16:
   506  		if right.(int16) == 0 {
   507  			return nil, errors.New("cannot divide by zero")
   508  		}
   509  		return left.(int16) % right.(int16), nil
   510  	case int32:
   511  		if right.(int32) == 0 {
   512  			return nil, errors.New("cannot divide by zero")
   513  		}
   514  		return left.(int32) % right.(int32), nil
   515  	case int64:
   516  		if right.(int64) == 0 {
   517  			return nil, errors.New("cannot divide by zero")
   518  		}
   519  		return left.(int64) % right.(int64), nil
   520  	}
   521  
   522  	return "", errors.New("invalid type for modulus")
   523  }
   524  
   525  func BitwiseAnd(left interface{}, right interface{}) (interface{}, error) {
   526  
   527  	switch left.(type) {
   528  	case uint8:
   529  		return left.(uint8) & right.(uint8), nil
   530  	case uint16:
   531  		return left.(uint16) & right.(uint16), nil
   532  	case uint32:
   533  		return left.(uint32) & right.(uint32), nil
   534  	case uint64:
   535  		return left.(uint64) & right.(uint64), nil
   536  	case int8:
   537  		return left.(int8) & right.(int8), nil
   538  	case int16:
   539  		return left.(int16) & right.(int16), nil
   540  	case int32:
   541  		return left.(int32) & right.(int32), nil
   542  	case int64:
   543  		return left.(int64) & right.(int64), nil
   544  	}
   545  
   546  	return "", errors.New("invalid type for bitwise and")
   547  }
   548  
   549  func BitwiseOr(left interface{}, right interface{}) (interface{}, error) {
   550  
   551  	switch left.(type) {
   552  	case uint8:
   553  		return left.(uint8) | right.(uint8), nil
   554  	case uint16:
   555  		return left.(uint16) | right.(uint16), nil
   556  	case uint32:
   557  		return left.(uint32) | right.(uint32), nil
   558  	case uint64:
   559  		return left.(uint64) | right.(uint64), nil
   560  	case int8:
   561  		return left.(int8) | right.(int8), nil
   562  	case int16:
   563  		return left.(int16) | right.(int16), nil
   564  	case int32:
   565  		return left.(int32) | right.(int32), nil
   566  	case int64:
   567  		return left.(int64) | right.(int64), nil
   568  	}
   569  
   570  	return "", errors.New("invalid type for bitwise or")
   571  }
   572  
   573  func BitwiseXOr(left interface{}, right interface{}) (interface{}, error) {
   574  
   575  	switch left.(type) {
   576  	case uint8:
   577  		return left.(uint8) ^ right.(uint8), nil
   578  	case uint16:
   579  		return left.(uint16) ^ right.(uint16), nil
   580  	case uint32:
   581  		return left.(uint32) ^ right.(uint32), nil
   582  	case uint64:
   583  		return left.(uint64) ^ right.(uint64), nil
   584  	case int8:
   585  		return left.(int8) ^ right.(int8), nil
   586  	case int16:
   587  		return left.(int16) ^ right.(int16), nil
   588  	case int32:
   589  		return left.(int32) ^ right.(int32), nil
   590  	case int64:
   591  		return left.(int64) ^ right.(int64), nil
   592  	}
   593  
   594  	return "", errors.New("invalid type for bitwise xor")
   595  }
   596  
   597  // todo: better wildcard comparison
   598  func ReplaceWildcardStarWithRegex(input string) string {
   599  	var result strings.Builder
   600  	for i, literal := range strings.Split(input, "*") {
   601  
   602  		// Replace * with .*
   603  		if i > 0 {
   604  			result.WriteString(".*")
   605  		}
   606  
   607  		// Quote any regular expression meta characters in the
   608  		// literal text.
   609  		result.WriteString(regexp.QuoteMeta(literal))
   610  	}
   611  	return result.String()
   612  }
   613  
   614  func AlmostEquals(left, right float64) bool {
   615  	tolerance := 0.000001
   616  	if difference := math.Abs(left - right); difference < tolerance {
   617  		return true
   618  	} else {
   619  		return false
   620  	}
   621  }
   622  
   623  func ConvertToSameType(leftType, rightType interface{}) (interface{}, interface{}, error) {
   624  
   625  	if fmt.Sprintf("%T", leftType) == fmt.Sprintf("%T", rightType) {
   626  		return leftType, rightType, nil
   627  	}
   628  
   629  	if unsafe.Sizeof(leftType) > unsafe.Sizeof(rightType) {
   630  		rightType, err := ConvertExpToType(rightType, leftType)
   631  		return leftType, rightType, err
   632  	} else {
   633  		leftType, err := ConvertExpToType(leftType, rightType)
   634  		return rightType, leftType, err
   635  	}
   636  }
   637  
   638  type AccessLogData struct {
   639  	TimeStamp   string
   640  	UserName    string
   641  	URI         string
   642  	RequestBody string
   643  	StatusCode  int
   644  	Duration    int64
   645  }