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: utils.go
    path of file: ./repos/encore/runtimes/go/pubsub/internal/utils
    
    the code of the file until where you have to start completion: package utils

import (
	"cmp"
	"encoding/json"
	"errors"
	"fmt"
	"math"
	"reflect"
	"strconv"
	"sync"
	"time"

	"encore.dev/beta/errs"
	"encore.dev/pubsub/internal/types"
)

const AttrTag = "pubsub-attr"

// UnmarshalMessage unmarshals a message into a struct. The message must be a JSON object.
func UnmarshalMessage[T any](attrs map[string]string, data []byte) (msg T, err error) {
	if err = json.Unmarshal(data, &msg); err != nil {
		err = errs.B().Cause(err).Code(errs.InvalidArgument).Msg("failed to unmarshal message").Err()
		return
	}

	if err = UnmarshalFields(attrs, &msg, AttrTag); err != nil {
		err = errs.B().Cause(err).Code(errs.InvalidArgument).Msg("failed to unmarshal attributes").Err()
		return
	}

	return
}

// MarshalFields creates a map[string]string of fields in `msg` tagged with `tag`. The name of the tag
// will be used as map key, and values are converted to strings using fmt.Sprintf. Pointers will be dereferenced
// and ignored if nil. Only basic types (bool, numeric, string) and pointers to those types are supported fields.
// Fields without a tag will not be marshalled. `msg` must be a struct or pointer to a struct
func Marsh
    
func UnmarshalFields[T any](attrs map[string]string, val T, tag string) error {
	v := reflect.ValueOf(val)
	// target type must be a pointer for us to set fields
	if v.Kind() != reflect.Pointer {
		return errors.New("target must be a pointer to a struct")
	}
	// Dereference the pointer
	for v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	// We only support structs for now
	if v.Kind() != reflect.Struct {
		return errors.New(fmt.Sprintf("unsupported kind, fields can only be unmarshaled into a struct. Got a %s", v.Kind()))
	}

	// Loop through the fields of the struct and look for `tag`s
	for i := 0; i < v.NumField(); i++ {
		if name, ok := v.Type().Field(i).Tag.Lookup(tag); ok {
			// If the attributes contain an element with the tag name, unmarshal it into target
			if attrVal, ok := attrs[name]; ok {
				dataField := v.Field(i)
				dataType := dataField.Type()
				ptrDepth := 0
				// Dereference the type (we can't use the value here because it might be nil)
				// Keep track of the pointer depth which is used later to create a pointer to
				// the value
				for ; dataType.Kind() == reflect.Ptr; ptrDepth++ {
					dataType = dataType.Elem()
				}

				assigner, _ := decodeCache.LoadOrStore(dataType.Kind(), func() fieldAssigner {
					// Parse and set the value. If the target type is a pointer, we need to
					// create a pointer. We use the type specific setter (e.g. SetInt) to handle
					// int bitsize conversions, and the generic setter (Set) to set pointers
					switch dataType.Kind() {
					case reflect.String:
						return getFieldAssigner(
							func(v string) (string, error) {
								return v, nil
							}, reflect.Value.SetString)
					case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
						return getFieldAssigner(
							func(v string) (int64, error) {
								return strconv.ParseInt(v, 10, 64)
							}, reflect.Value.SetInt)
					case reflect.Float32, reflect.Float64:
						return getFieldAssigner(
							func(v string) (float64, error) {
								return strconv.ParseFloat(v, 64)
							}, reflect.Value.SetFloat)
					case reflect.Bool:
						return getFieldAssigner(
							func(v string) (bool, error) {
								return strconv.ParseBool(v)
							}, reflect.Value.SetBool)
					case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
						return getFieldAssigner(
							func(v string) (uint64, error) {
								return strconv.ParseUint(v, 10, 64)
							}, reflect.Value.SetUint)
					case reflect.Complex64, reflect.Complex128:
						return getFieldAssigner(
							func(v string) (complex128, error) {
								return strconv.ParseComplex(v, 128)
							}, reflect.Value.SetComplex)
					default:
						return func(val string, ptrDepth int, dataField reflect.Value) error {
							return errors.New(fmt.Sprintf("unsupported kind: %s", dataField.Kind()))
						}
					}
				}())
				assignFunc := assigner.(fieldAssigner)
				err := assignFunc(attrVal, ptrDepth, dataField)
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}