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: read.go
    path of file: ./repos/xorm/vendor/github.com/tealeg/xlsx
    
    the code of the file until where you have to start completion: package xlsx

import (
	"errors"
	"reflect"
	"strconv"
	"time"
)

var (
	errNilInterface     = errors.New("nil pointer is not a valid argument")
	errNotStructPointer = errors.New("argument must be a pointer to struct")
	errInvalidTag       = errors.New(`invalid tag: must have the format xlsx:idx`)
)

//XLSXUnmarshaler is the interface implemented for types that can unmarshal a Row
//as a representation of themselves.
type XLSXUnmarshaler interface {
	Unmarshal(*Row) error
}

//ReadStruct reads a struct from r to ptr. Accepts a ptr
//to struct. This code expects a tag xlsx:"N", where N is the index
//of the cell to be used. Basic types like int,string,float64 and bool
//are supported
func (r *Row) ReadStruct(ptr interface{}) error {
	if ptr == nil {
		return errNilInterface
	}
	//check if the type implements XLSXUnmarshaler. If so,
	//just let it do the work.
	unmarshaller, ok := ptr.(XLSXUnmarshaler)
	if ok {
		return unmarshaller.Unmarshal(r)
	}
	v := reflect.ValueOf(ptr)
	if v.Kind() != reflect.Ptr {
		return errNotStructPointer
	}
	v = v.Elem()
	if v.Kind() != reflect.Struct {
		return errNotStructPointer
	}
	n := v.NumField()
	for i := 0; i < n; i++ {
		field := v.Type().Field(i)
		idx := field.Tag.Get("xlsx")
		//do a recursive check for the field if it is a struct or a pointer
		//even if it doesn't have a tag
		//ignore if it has a - or empty tag
		isTime := false
		switch {
		case idx == "-":
			continue
		case field.Type.Kind() == reflect.Ptr || field.Type.Kind() == reflect.Struct:
			var structPtr interface{}
			if !v.Field(i).CanSet() {
				continue
			}
			if field.Type.Kind() == reflect.Struct {
				structPtr = v.Field(i).Addr().Interface()
			} else {
				structPtr = v.Field(i).Interface()
			}
			//check if the container is a time.Time
			_, isTim
    
func (r *Row) ReadStruct(ptr interface{}) error {
	if ptr == nil {
		return errNilInterface
	}
	//check if the type implements XLSXUnmarshaler. If so,
	//just let it do the work.
	unmarshaller, ok := ptr.(XLSXUnmarshaler)
	if ok {
		return unmarshaller.Unmarshal(r)
	}
	v := reflect.ValueOf(ptr)
	if v.Kind() != reflect.Ptr {
		return errNotStructPointer
	}
	v = v.Elem()
	if v.Kind() != reflect.Struct {
		return errNotStructPointer
	}
	n := v.NumField()
	for i := 0; i < n; i++ {
		field := v.Type().Field(i)
		idx := field.Tag.Get("xlsx")
		//do a recursive check for the field if it is a struct or a pointer
		//even if it doesn't have a tag
		//ignore if it has a - or empty tag
		isTime := false
		switch {
		case idx == "-":
			continue
		case field.Type.Kind() == reflect.Ptr || field.Type.Kind() == reflect.Struct:
			var structPtr interface{}
			if !v.Field(i).CanSet() {
				continue
			}
			if field.Type.Kind() == reflect.Struct {
				structPtr = v.Field(i).Addr().Interface()
			} else {
				structPtr = v.Field(i).Interface()
			}
			//check if the container is a time.Time
			_, isTime = structPtr.(*time.Time)
			if isTime {
				break
			}
			err := r.ReadStruct(structPtr)
			if err != nil {
				return err
			}
			continue
		case len(idx) == 0:
			continue
		}
		pos, err := strconv.Atoi(idx)
		if err != nil {
			return errInvalidTag
		}

		//check if desired position is not out of bounds
		if pos > len(r.Cells)-1 {
			continue
		}
		cell := r.Cells[pos]
		fieldV := v.Field(i)
		//continue if the field is not settable
		if !fieldV.CanSet() {
			continue
		}
		if isTime {
			t, err := cell.GetTime(false)
			if err != nil {
				return err
			}
			if field.Type.Kind() == reflect.Ptr {
				fieldV.Set(reflect.ValueOf(&t))
			} else {
				fieldV.Set(reflect.ValueOf(t))
			}
			continue
		}
		switch field.Type.Kind() {
		case reflect.String:
			value, err := cell.FormattedValue()
			if err != nil {
				return err
			}
			fieldV.SetString(value)
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			value, err := cell.Int64()
			if err != nil {
				return err
			}
			fieldV.SetInt(value)
		case reflect.Float64:
			value, err := cell.Float()
			if err != nil {
				return err
			}
			fieldV.SetFloat(value)
		case reflect.Bool:
			value := cell.Bool()
			fieldV.SetBool(value)
		}
	}
	value := v.Interface()
	ptr = &value
	return nil
}