MCPcopy Create free account
hub / github.com/apache/fory / WriteRefOrNull

Method WriteRefOrNull

go/fory/ref_resolver.go:131–193  ·  view source on GitHub ↗

WriteRefOrNull write reference and tag for the value if the value has been written previously, write null/not-null tag otherwise. Returns true if no bytes need to be written for the object. See https://go101.org/article/value-part.html for internal structure definitions of common types. Note that fo

(buffer *ByteBuffer, value reflect.Value)

Source from the content-addressed store, hash-verified

129// Note that for slice and substring, if the start addr or length are different, we take two objects as
130// different references.
131func (r *RefResolver) WriteRefOrNull(buffer *ByteBuffer, value reflect.Value) (refWritten bool, err error) {
132 if !r.refTracking || value.Kind() == reflect.String {
133 if isNil(value) {
134 buffer.WriteInt8(NullFlag)
135 return true, nil
136 } else {
137 buffer.WriteInt8(NotNullValueFlag)
138 return false, nil
139 }
140 }
141 length := 0
142 isNil := false
143 kind := value.Kind()
144 // reference types such as channel/function are not handled here and will be handled by typeResolver.
145 switch kind {
146 case reflect.Ptr:
147 elemValue := value.Elem()
148 if elemValue.Kind() == reflect.Array {
149 length = elemValue.Len()
150 }
151 isNil = value.IsNil()
152 case reflect.Map:
153 isNil = value.IsNil()
154 case reflect.Slice:
155 isNil = value.IsNil()
156 length = value.Len()
157 case reflect.Interface:
158 value = value.Elem()
159 return r.WriteRefOrNull(buffer, value)
160 case reflect.Invalid:
161 isNil = true
162 case reflect.Struct:
163 // Struct values are value types, not reference types.
164 // They should not participate in reference tracking.
165 buffer.WriteInt8(NotNullValueFlag)
166 return false, nil
167 default:
168 // The object is being written for the first time.
169 buffer.WriteInt8(NotNullValueFlag)
170 return false, nil
171 }
172 if isNil {
173 buffer.WriteInt8(NullFlag)
174 return true, nil
175 } else {
176 refKey := refKey{pointer: unsafe.Pointer(value.Pointer()), length: length}
177 if writtenId, ok := r.writtenObjects[refKey]; ok {
178 // The obj has been written previously.
179 buffer.WriteInt8(RefFlag)
180 buffer.WriteVarUint32(uint32(writtenId))
181 return true, nil
182 } else {
183 // The id should be consistent with `nextReadRefId`
184 newWriteRefId := len(r.writtenObjects)
185 if newWriteRefId >= MaxInt32 {
186 return false, fmt.Errorf("too many objects execced %d to serialize", MaxInt32)
187 }
188 r.writtenObjects[refKey] = int32(newWriteRefId)

Callers 15

WriteMethod · 0.80
writeSameTypeMethod · 0.80
writeDifferentTypesMethod · 0.80
writeDifferentTypesMethod · 0.80
WriteMethod · 0.80
writeUnionOverrideValueFunction · 0.80
writeMapRefAndTypeFunction · 0.80
WriteMethod · 0.80
writeWithTypeInfoMethod · 0.80
WriteMethod · 0.80
WriteMethod · 0.80
WriteMethod · 0.80

Calls 7

isNilFunction · 0.85
KindMethod · 0.80
LenMethod · 0.80
uint32Function · 0.50
int32Function · 0.50
WriteInt8Method · 0.45
WriteVarUint32Method · 0.45

Tested by 2

TestReferenceResolverFunction · 0.64
TestNonReferenceResolverFunction · 0.64