initFields initializes fields from local struct type using TypeResolver
(typeResolver *TypeResolver)
| 113 | |
| 114 | // initFields initializes fields from local struct type using TypeResolver |
| 115 | func (s *structSerializer) initFields(typeResolver *TypeResolver) error { |
| 116 | // If we have fieldDefs from type_def (remote meta), use them |
| 117 | if len(s.fieldDefs) > 0 { |
| 118 | return s.initFieldsFromTypeDef(typeResolver) |
| 119 | } |
| 120 | |
| 121 | // Otherwise initialize from local struct type |
| 122 | type_ := s.type_ |
| 123 | var fields []FieldInfo |
| 124 | var fieldNames []string |
| 125 | var serializers []Serializer |
| 126 | var typeIds []TypeId |
| 127 | var nullables []bool |
| 128 | var tagIDs []int |
| 129 | |
| 130 | for i := 0; i < type_.NumField(); i++ { |
| 131 | field := type_.Field(i) |
| 132 | firstRune, _ := utf8.DecodeRuneInString(field.Name) |
| 133 | if unicode.IsLower(firstRune) { |
| 134 | continue // skip unexported fields |
| 135 | } |
| 136 | |
| 137 | fieldSpec, err := parseFieldSpec(field, typeResolver.fory.config.IsXlang, typeResolver.TrackRef()) |
| 138 | if err != nil { |
| 139 | return err |
| 140 | } |
| 141 | fieldSpec.Type = bindResolvedTypeSpec(typeResolver, field.Type, fieldSpec.Type) |
| 142 | if fieldSpec.Ignore { |
| 143 | continue // skip ignored fields |
| 144 | } |
| 145 | |
| 146 | fieldType := field.Type |
| 147 | optionalInfo, isOptional := getOptionalInfo(fieldType) |
| 148 | baseType := fieldType |
| 149 | if isOptional { |
| 150 | if err := validateOptionalValueType(optionalInfo.valueType); err != nil { |
| 151 | return fmt.Errorf("field %s: %w", field.Name, err) |
| 152 | } |
| 153 | baseType = optionalInfo.valueType |
| 154 | } |
| 155 | fieldKind := FieldKindValue |
| 156 | if isOptional { |
| 157 | fieldKind = FieldKindOptional |
| 158 | } else if fieldType.Kind() == reflect.Ptr { |
| 159 | fieldKind = FieldKindPointer |
| 160 | } |
| 161 | fieldSerializer, err := serializerForTypeSpec(typeResolver, fieldType, fieldSpec.Type) |
| 162 | if err != nil && fieldType.Kind() != reflect.Interface { |
| 163 | return fmt.Errorf("field %s: %w", field.Name, err) |
| 164 | } |
| 165 | fieldTypeId := fieldSpec.Type.TypeId() |
| 166 | nullableFlag := fieldDeclaredNullable(fieldSpec) |
| 167 | trackRef := fieldDeclaredTrackRef(fieldSpec, typeResolver.fory.config.IsXlang, typeResolver.TrackRef()) |
| 168 | |
| 169 | // Pre-compute RefMode based on TrackRef and nullable. |
| 170 | // When TrackRef is true, we must write ref flags even for non-nullable fields. |
| 171 | refMode := RefModeNone |
| 172 | if trackRef { |
no test coverage detected