/* |-------------------------------------------------------------------------- | Manifest |-------------------------------------------------------------------------- | | Name: | - Codec | | Purpose: | - Provide unified encoding and decoding capabilities using Base8, | Base10, Base16, Base32, Base64, and Sqids with centralized | validation, dispatching, transformation management, and | structured result handling. | | Guideline: | - Use ObrimCodec() as the public entry point. | - Validate all parameters before dispatching operations. | - Use supported formats only. | - Handle all failures through structured responses. | | Example: | - ObrimCodec("encode", config) | - ObrimCodec("decode", config) | |-------------------------------------------------------------------------- */ /* |-------------------------------------------------------------------------- | Credit |-------------------------------------------------------------------------- | | Contributor: | - Rajon Ahmed | - Scionite | |-------------------------------------------------------------------------- */ package codec import ( "encoding/base32" "encoding/base64" "encoding/hex" "errors" "fmt" "strconv" "strings" "go/module/essential/visible/service/helper/log" "go/module/essential/visible/service/helper/retriever" "go/module/essential/visible/service/helper/status" "github.com/sqids/sqids-go" ) // ObrimCodecResult represents the standardized utility response. type ObrimCodecResult struct { Status bool `json:"status"` Code string `json:"code"` Payload map[string]any `json:"payload"` } // ObrimCodecConfig represents validated codec configuration. type ObrimCodecConfig struct { Format string Data any Charset string Salt string Case string Length int } // ObrimCodec validates configuration, dispatches codec operations, and returns structured results. func ObrimCodec(operation string, config map[string]any) map[string]any { _ = retriever.ObrimRetriever status.ObrimStatus("INFO", "Codec operation initialized.") log.ObrimLog("INIT", "Codec operation initialized.") validatedConfig, validationCode, validationError := obrimCodecValidation(operation, config) if validationError != nil { status.ObrimStatus("ERROR", validationError.Error()) log.ObrimLog("ERROR", validationError.Error()) return map[string]any{ "status": false, "code": validationCode, "payload": nil, } } payload, dispatchCode, dispatchError := obrimCodecDispatch(operation, validatedConfig) if dispatchError != nil { status.ObrimStatus("ERROR", dispatchError.Error()) log.ObrimLog("ERROR", dispatchError.Error()) return map[string]any{ "status": false, "code": dispatchCode, "payload": nil, } } status.ObrimStatus("SUCCESS", "Codec operation completed.") log.ObrimLog("SUCCESS", "Codec operation completed.") return map[string]any{ "status": true, "code": dispatchCode, "payload": payload, } } // obrimCodecValidation validates required parameters, supported operations, formats, and parameter types. func obrimCodecValidation(operation string, config map[string]any) (ObrimCodecConfig, string, error) { // Mutable validated configuration. var validated ObrimCodecConfig switch operation { case "encode", "decode": default: return validated, "FAILED_UNSUPPORTED_OPERATION", errors.New("unsupported operation") } // Mutable format value. formatValue, exists := config["format"] if !exists { return validated, "FAILED_MISSING_FORMAT", errors.New("missing format") } format, ok := formatValue.(string) if !ok { return validated, "FAILED_INVALID_FORMAT_TYPE", errors.New("invalid format type") } switch format { case "base8", "base10", "base16", "base32", "base64", "sqids": default: return validated, "FAILED_UNSUPPORTED_FORMAT", errors.New("unsupported format") } // Mutable data value. dataValue, exists := config["data"] if !exists { return validated, "FAILED_MISSING_DATA", errors.New("missing data") } switch dataValue.(type) { case string, []byte: default: return validated, "FAILED_INVALID_DATA_TYPE", errors.New("invalid data type") } // Mutable charset value. charsetValue, exists := config["charset"] if !exists { return validated, "FAILED_MISSING_CHARSET", errors.New("missing charset") } charset, ok := charsetValue.(string) if !ok { return validated, "FAILED_INVALID_CHARSET_TYPE", errors.New("invalid charset type") } // Mutable salt value. saltValue, exists := config["salt"] if !exists { return validated, "FAILED_MISSING_SALT", errors.New("missing salt") } salt, ok := saltValue.(string) if !ok { return validated, "FAILED_INVALID_SALT_TYPE", errors.New("invalid salt type") } validated.Format = format validated.Data = dataValue validated.Charset = charset validated.Salt = salt if format == "sqids" { // Mutable length value. lengthValue, exists := config["length"] if !exists { return validated, "FAILED_MISSING_LENGTH", errors.New("missing length") } switch value := lengthValue.(type) { case int: validated.Length = value case int64: validated.Length = int(value) case float64: validated.Length = int(value) default: return validated, "FAILED_INVALID_LENGTH_TYPE", errors.New("invalid length type") } } else { // Mutable case value. caseValue, exists := config["case"] if !exists { return validated, "FAILED_MISSING_CASE", errors.New("missing case") } caseRule, ok := caseValue.(string) if !ok { return validated, "FAILED_INVALID_CASE_TYPE", errors.New("invalid case type") } switch caseRule { case "lower", "upper": default: return validated, "FAILED_INVALID_CASE_VALUE", errors.New("invalid case value") } validated.Case = caseRule } return validated, "SUCCESS_VALIDATION", nil } // obrimCodecDispatch routes validated requests to the appropriate codec implementation. func obrimCodecDispatch(operation string, config ObrimCodecConfig) (map[string]any, string, error) { switch operation { case "encode": switch config.Format { case "base8": return obrimCodecEncodeBase8(config) case "base10": return obrimCodecEncodeBase10(config) case "base16": return obrimCodecEncodeBase16(config) case "base32": return obrimCodecEncodeBase32(config) case "base64": return obrimCodecEncodeBase64(config) case "sqids": return obrimCodecEncodeSqids(config) } case "decode": switch config.Format { case "base8": return obrimCodecDecodeBase8(config) case "base10": return obrimCodecDecodeBase10(config) case "base16": return obrimCodecDecodeBase16(config) case "base32": return obrimCodecDecodeBase32(config) case "base64": return obrimCodecDecodeBase64(config) case "sqids": return obrimCodecDecodeSqids(config) } } return nil, "FAILED_DISPATCH", errors.New("dispatch failed") } // obrimCodecEncodeBase8 encodes data using Base8 encoding. func obrimCodecEncodeBase8(config ObrimCodecConfig) (map[string]any, string, error) { value := obrimCodecBytesToBase(config, 8) return map[string]any{ "operation": "encode", "format": "base8", "value": obrimCodecApplyCase(obrimCodecTransformEncode(value, config), config.Case), }, "SUCCESS_BASE8_ENCODE", nil } // obrimCodecEncodeBase10 encodes data using Base10 encoding. func obrimCodecEncodeBase10(config ObrimCodecConfig) (map[string]any, string, error) { value := obrimCodecBytesToBase(config, 10) return map[string]any{ "operation": "encode", "format": "base10", "value": obrimCodecApplyCase(obrimCodecTransformEncode(value, config), config.Case), }, "SUCCESS_BASE10_ENCODE", nil } // obrimCodecEncodeBase16 encodes data using Base16 encoding. func obrimCodecEncodeBase16(config ObrimCodecConfig) (map[string]any, string, error) { value := hex.EncodeToString(obrimCodecBytes(config.Data)) value = obrimCodecApplyCase(value, config.Case) value = obrimCodecTransformEncode(value, config) return map[string]any{ "operation": "encode", "format": "base16", "value": value, }, "SUCCESS_BASE16_ENCODE", nil } // obrimCodecEncodeBase32 encodes data using Base32 encoding. func obrimCodecEncodeBase32(config ObrimCodecConfig) (map[string]any, string, error) { value := base32.StdEncoding.EncodeToString(obrimCodecBytes(config.Data)) value = obrimCodecApplyCase(value, config.Case) value = obrimCodecTransformEncode(value, config) return map[string]any{ "operation": "encode", "format": "base32", "value": value, }, "SUCCESS_BASE32_ENCODE", nil } // obrimCodecEncodeBase64 encodes data using Base64 encoding. func obrimCodecEncodeBase64(config ObrimCodecConfig) (map[string]any, string, error) { value := base64.StdEncoding.EncodeToString(obrimCodecBytes(config.Data)) value = obrimCodecApplyCase(value, config.Case) value = obrimCodecTransformEncode(value, config) return map[string]any{ "operation": "encode", "format": "base64", "value": value, }, "SUCCESS_BASE64_ENCODE", nil } // obrimCodecEncodeSqids encodes data using Sqids encoding with minimum length enforcement. func obrimCodecEncodeSqids(config ObrimCodecConfig) (map[string]any, string, error) { options := sqids.Options{ MinLength: uint8(config.Length), Alphabet: obrimCodecAlphabet(config.Charset), Blocklist: []string{}, } instance, err := sqids.New(options) if err != nil { return nil, "FAILED_SQIDS_INITIALIZATION", err } number, err := strconv.ParseUint(obrimCodecTransformNumberInput(config), 10, 64) if err != nil { return nil, "FAILED_SQIDS_INPUT", err } value, err := instance.Encode([]uint64{number}) if err != nil { return nil, "FAILED_SQIDS_ENCODE", err } value = config.Salt + value return map[string]any{ "operation": "encode", "format": "sqids", "value": value, }, "SUCCESS_SQIDS_ENCODE", nil } // obrimCodecDecodeBase8 decodes Base8 encoded data. func obrimCodecDecodeBase8(config ObrimCodecConfig) (map[string]any, string, error) { value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) return map[string]any{ "operation": "decode", "format": "base8", "value": value, }, "SUCCESS_BASE8_DECODE", nil } // obrimCodecDecodeBase10 decodes Base10 encoded data. func obrimCodecDecodeBase10(config ObrimCodecConfig) (map[string]any, string, error) { value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) return map[string]any{ "operation": "decode", "format": "base10", "value": value, }, "SUCCESS_BASE10_DECODE", nil } // obrimCodecDecodeBase16 decodes Base16 encoded data. func obrimCodecDecodeBase16(config ObrimCodecConfig) (map[string]any, string, error) { value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) decoded, err := hex.DecodeString(value) if err != nil { return nil, "FAILED_BASE16_DECODE", err } return map[string]any{ "operation": "decode", "format": "base16", "value": string(decoded), }, "SUCCESS_BASE16_DECODE", nil } // obrimCodecDecodeBase32 decodes Base32 encoded data. func obrimCodecDecodeBase32(config ObrimCodecConfig) (map[string]any, string, error) { value := strings.ToUpper(obrimCodecTransformDecode(obrimCodecString(config.Data), config)) decoded, err := base32.StdEncoding.DecodeString(value) if err != nil { return nil, "FAILED_BASE32_DECODE", err } return map[string]any{ "operation": "decode", "format": "base32", "value": string(decoded), }, "SUCCESS_BASE32_DECODE", nil } // obrimCodecDecodeBase64 decodes Base64 encoded data. func obrimCodecDecodeBase64(config ObrimCodecConfig) (map[string]any, string, error) { value := obrimCodecTransformDecode(obrimCodecString(config.Data), config) decoded, err := base64.StdEncoding.DecodeString(value) if err != nil { return nil, "FAILED_BASE64_DECODE", err } return map[string]any{ "operation": "decode", "format": "base64", "value": string(decoded), }, "SUCCESS_BASE64_DECODE", nil } // obrimCodecDecodeSqids decodes Sqids encoded data using deterministic length validation. func obrimCodecDecodeSqids(config ObrimCodecConfig) (map[string]any, string, error) { options := sqids.Options{ MinLength: uint8(config.Length), Alphabet: obrimCodecAlphabet(config.Charset), Blocklist: []string{}, } instance, err := sqids.New(options) if err != nil { return nil, "FAILED_SQIDS_INITIALIZATION", err } value := strings.TrimPrefix(obrimCodecString(config.Data), config.Salt) decoded := instance.Decode(value) if len(decoded) == 0 { return nil, "FAILED_SQIDS_DECODE", errors.New("invalid sqids value") } return map[string]any{ "operation": "decode", "format": "sqids", "value": fmt.Sprintf("%d", decoded[0]), }, "SUCCESS_SQIDS_DECODE", nil } // obrimCodecBytes converts supported data types to bytes. func obrimCodecBytes(data any) []byte { switch value := data.(type) { case string: return []byte(value) case []byte: return value default: return []byte{} } } // obrimCodecString converts supported data types to string. func obrimCodecString(data any) string { switch value := data.(type) { case string: return value case []byte: return string(value) default: return "" } } // obrimCodecApplyCase applies output casing rules. func obrimCodecApplyCase(value string, caseRule string) string { if caseRule == "upper" { return strings.ToUpper(value) } return strings.ToLower(value) } // obrimCodecTransformEncode applies charset and salt transformations. func obrimCodecTransformEncode(value string, config ObrimCodecConfig) string { return config.Salt + config.Charset + ":" + value } // obrimCodecTransformDecode reverses charset and salt transformations. func obrimCodecTransformDecode(value string, config ObrimCodecConfig) string { value = strings.TrimPrefix(value, config.Salt) value = strings.TrimPrefix(value, config.Charset+":") return value } // obrimCodecAlphabet resolves Sqids alphabet. func obrimCodecAlphabet(charset string) string { if charset == "" { return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" } return charset } // obrimCodecTransformNumberInput converts input into deterministic numeric content. func obrimCodecTransformNumberInput(config ObrimCodecConfig) string { value := obrimCodecString(config.Data) if _, err := strconv.ParseUint(value, 10, 64); err == nil { return value } return fmt.Sprintf("%d", len(value)+len(config.Salt)+len(config.Charset)) } // obrimCodecBytesToBase converts bytes into arbitrary base string representation. func obrimCodecBytesToBase(config ObrimCodecConfig, base int) string { data := obrimCodecBytes(config.Data) var builder strings.Builder for _, item := range data { builder.WriteString(strconv.FormatInt(int64(item), base)) } return builder.String() }