You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: compare_internal.go
    path of file: ./repos/lancet/compare
    
    the code of the file until where you have to start completion: package compare

import (
	"bytes"
	"encoding/json"
	"reflect"
	"time"

	"github.com/duke-git/lancet/v2/convertor"
)

func compareValue(operator string, left, right any) bool {
	leftType, rightType := reflect.TypeOf(left), reflect.TypeOf(right)

	if leftType.Kind() != rightType.Kind() {
		return false
	}

	switch leftType.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Float32, reflect.Float64, reflect.Bool, reflect.String:
		return compareBasicValue(operator, left, right)

	case reflect.Struct, reflect.Slice, reflect.Map:
		return compareRefValue(operator, left, right, leftType.Kind())
	}

	return false
}

func compareRefValue(operator string, leftObj, rightObj any, kind reflect.Kind) bool {
	leftVal, rightVal := reflect.ValueOf(leftObj), reflect.ValueOf(rightObj)

	switch kind {
	case reflect.Struct:

		// compare time
		if leftVal.CanConvert(timeType) {
			timeObj1, ok := leftObj.(time.Time)
			if !ok {
				timeObj1 = leftVal.Convert(timeType).Interface().(time.Time)
			}

			timeObj2, ok := rightObj.(time.Time)
			if !ok {
				timeObj2 = rightVal.Convert(timeType).Interface().(time.Time)
			}

			return compareBasicValue(operator, timeObj1.UnixNano(), timeObj2.UnixNano())
		}

		// for other struct type, only process equal operator
		switch operator {
		case equal:
			return objectsAreEqualValues(leftObj, rightObj)
		}

	case reflect.Slice:
		// compare []byte
		if leftVal.CanConvert(bytesType) {
			bytesObj1, ok := leftObj.([]byte)
			if !ok {
				bytesObj1 = leftVal.Co
    
func compareRefValue(operator string, leftObj, rightObj any, kind reflect.Kind) bool {
	leftVal, rightVal := reflect.ValueOf(leftObj), reflect.ValueOf(rightObj)

	switch kind {
	case reflect.Struct:

		// compare time
		if leftVal.CanConvert(timeType) {
			timeObj1, ok := leftObj.(time.Time)
			if !ok {
				timeObj1 = leftVal.Convert(timeType).Interface().(time.Time)
			}

			timeObj2, ok := rightObj.(time.Time)
			if !ok {
				timeObj2 = rightVal.Convert(timeType).Interface().(time.Time)
			}

			return compareBasicValue(operator, timeObj1.UnixNano(), timeObj2.UnixNano())
		}

		// for other struct type, only process equal operator
		switch operator {
		case equal:
			return objectsAreEqualValues(leftObj, rightObj)
		}

	case reflect.Slice:
		// compare []byte
		if leftVal.CanConvert(bytesType) {
			bytesObj1, ok := leftObj.([]byte)
			if !ok {
				bytesObj1 = leftVal.Convert(bytesType).Interface().([]byte)
			}
			bytesObj2, ok := rightObj.([]byte)
			if !ok {
				bytesObj2 = rightVal.Convert(bytesType).Interface().([]byte)
			}

			switch operator {
			case equal:
				if bytes.Equal(bytesObj1, bytesObj2) {
					return true
				}
			case lessThan:
				if bytes.Compare(bytesObj1, bytesObj2) == -1 {
					return true
				}
			case greaterThan:
				if bytes.Compare(bytesObj1, bytesObj2) == 1 {
					return true
				}
			case lessOrEqual:
				if bytes.Compare(bytesObj1, bytesObj2) <= 0 {
					return true
				}
			case greaterOrEqual:
				if bytes.Compare(bytesObj1, bytesObj2) >= 0 {
					return true
				}
			}

		}

		// for other type slice, only process equal operator
		switch operator {
		case equal:
			return reflect.DeepEqual(leftObj, rightObj)
		}

	case reflect.Map:
		// only process equal operator
		switch operator {
		case equal:
			return reflect.DeepEqual(leftObj, rightObj)
		}
	}

	return false
}