package parser import ( "fmt" "reflect" ) // readArray handles array parsing with full substruct support func (p *Parser) readArray(field reflect.Value, fieldTag *FieldTag) error { var arraySize int if fieldTag.ArraySizeVar != "" { arraySize = p.getDynamicLength(fieldTag.ArraySizeVar) } else { size, err := p.readUint32() if err != nil { return err } arraySize = int(size) } if arraySize == 0 { return nil } if field.Kind() == reflect.Slice { elemType := field.Type().Elem() slice := reflect.MakeSlice(field.Type(), arraySize, arraySize) p.arrayStack = append(p.arrayStack, ArrayContext{ elementType: elemType, totalSize: arraySize, sizeVariable: fieldTag.ArraySizeVar, }) for i := 0; i < arraySize; i++ { p.arrayStack[len(p.arrayStack)-1].currentIndex = i elem := slice.Index(i) if elemType.Kind() == reflect.Struct { if err := p.parseStructElement(elem, elemType); err != nil { p.arrayStack = p.arrayStack[:len(p.arrayStack)-1] return fmt.Errorf("array element %d: %w", i, err) } } else { if err := p.readPrimitiveArrayElement(elem, elemType); err != nil { p.arrayStack = p.arrayStack[:len(p.arrayStack)-1] return fmt.Errorf("array element %d: %w", i, err) } } } p.arrayStack = p.arrayStack[:len(p.arrayStack)-1] field.Set(slice) } return nil } // readSubstruct handles substruct parsing func (p *Parser) readSubstruct(field reflect.Value, length int) error { if field.Kind() == reflect.Slice { elemType := field.Type().Elem() slice := reflect.MakeSlice(field.Type(), length, length) for i := 0; i < length; i++ { elem := slice.Index(i) if err := p.parseStructElement(elem, elemType); err != nil { return fmt.Errorf("substruct element %d: %w", i, err) } } field.Set(slice) return nil } else if field.Kind() == reflect.Struct { return p.parseStructElement(field, field.Type()) } else if field.Kind() == reflect.Ptr && field.Type().Elem().Kind() == reflect.Struct { structType := field.Type().Elem() newStruct := reflect.New(structType) if err := p.parseStructElement(newStruct.Elem(), structType); err != nil { return err } field.Set(newStruct) return nil } return fmt.Errorf("substruct field must be struct, slice of structs, or pointer to struct") } // parseStructElement parses a single struct element func (p *Parser) parseStructElement(elem reflect.Value, elemType reflect.Type) error { oldStruct := p.currentStruct oldCache := p.fieldCache p.currentStruct = elem p.fieldCache = make(map[string]any) p.structStack = append(p.structStack, elem) for i := 0; i < elem.NumField(); i++ { field := elem.Field(i) fieldType := elemType.Field(i) if !field.CanSet() { continue } tag := fieldType.Tag.Get("eq2") if tag == "" || tag == "-" { continue } if err := p.parseField(field, tag); err != nil { p.structStack = p.structStack[:len(p.structStack)-1] p.currentStruct = oldStruct p.fieldCache = oldCache return fmt.Errorf("field %s: %w", fieldType.Name, err) } if field.CanInterface() { p.fieldCache[fieldType.Name] = field.Interface() } } p.structStack = p.structStack[:len(p.structStack)-1] p.currentStruct = oldStruct p.fieldCache = oldCache return nil } // readPrimitiveArrayElement reads primitive array elements func (p *Parser) readPrimitiveArrayElement(elem reflect.Value, elemType reflect.Type) error { switch elemType.Kind() { case reflect.Uint8: val, err := p.readUint8() if err != nil { return err } elem.SetUint(uint64(val)) case reflect.Uint16: val, err := p.readUint16() if err != nil { return err } elem.SetUint(uint64(val)) case reflect.Uint32: val, err := p.readUint32() if err != nil { return err } elem.SetUint(uint64(val)) case reflect.Uint64: val, err := p.readUint64() if err != nil { return err } elem.SetUint(val) case reflect.Int8: val, err := p.readUint8() if err != nil { return err } elem.SetInt(int64(int8(val))) case reflect.Int16: val, err := p.readUint16() if err != nil { return err } elem.SetInt(int64(int16(val))) case reflect.Int32: val, err := p.readUint32() if err != nil { return err } elem.SetInt(int64(int32(val))) case reflect.Int64: val, err := p.readUint64() if err != nil { return err } elem.SetInt(int64(val)) case reflect.Float32: val, err := p.readFloat32() if err != nil { return err } elem.SetFloat(float64(val)) case reflect.Float64: val, err := p.readFloat64() if err != nil { return err } elem.SetFloat(val) default: return fmt.Errorf("unsupported primitive array element type: %v", elemType.Kind()) } return nil } // GetCurrentArrayIndex returns current array index for nested parsing func (p *Parser) GetCurrentArrayIndex() int { if len(p.arrayStack) > 0 { return p.arrayStack[len(p.arrayStack)-1].currentIndex } return -1 } // GetCurrentArraySize returns current array size func (p *Parser) GetCurrentArraySize() int { if len(p.arrayStack) > 0 { return p.arrayStack[len(p.arrayStack)-1].totalSize } return 0 }