func()

in object.go [107:217]


func (e *Encoder) encObject(v interface{}) error {
	var (
		i      int
		idx    int
		num    int
		err    error
		clsDef *ClassInfo
	)
	pojo, isPojo := v.(POJO)
	// get none pojo JavaClassName
	var nonePojoJavaName string
	if !isPojo {
		s, ok := loadPOJORegistry(v)
		if !ok {
			return perrors.Errorf("non-pojo obj %s has not being registered before!", typeof(v))
		}
		nonePojoJavaName = s.javaName
	}

	vv := reflect.ValueOf(v)
	// check ref
	if n, ok := e.checkRefMap(vv); ok {
		e.buffer = encRef(e.buffer, n)
		return nil
	}

	vv = UnpackPtr(vv)
	// check nil pointer
	if !vv.IsValid() {
		e.buffer = EncNull(e.buffer)
		return nil
	}

	// write object definition
	idx = -1
	for i = range e.classInfoList {
		if isPojo && pojo.JavaClassName() == e.classInfoList[i].javaName || !isPojo && nonePojoJavaName == e.classInfoList[i].javaName {
			idx = i
			break
		}
	}

	var ok bool
	if idx == -1 {
		idx, ok = checkPOJORegistry(v)
		if !ok {
			if reflect.TypeOf(v).Implements(javaEnumType) {
				idx = RegisterJavaEnum(v.(POJOEnum))
			} else if isPojo {
				idx = RegisterPOJO(pojo)
			} else {
				return perrors.Errorf("non-pojo obj %s has not being registered before!", typeof(v))
			}
		}
		_, clsDef, err = getStructDefByIndex(idx)
		if err != nil {
			return perrors.WithStack(err)
		}

		idx = len(e.classInfoList)
		e.classInfoList = append(e.classInfoList, clsDef)
		e.buffer = append(e.buffer, clsDef.buffer...)
	}

	// write object instance
	if byte(idx) <= OBJECT_DIRECT_MAX {
		e.buffer = encByte(e.buffer, byte(idx)+BC_OBJECT_DIRECT)
	} else {
		e.buffer = encByte(e.buffer, BC_OBJECT)
		e.buffer = encInt32(e.buffer, int32(idx))
	}

	if reflect.TypeOf(v).Implements(javaEnumType) {
		e.buffer = encString(e.buffer, v.(POJOEnum).String())
		return nil
	}

	structs := []reflect.Value{vv}
	for len(structs) > 0 {
		vv := structs[0]
		vvt := vv.Type()
		num = vv.NumField()
		for i = 0; i < num; i++ {
			tf := vvt.Field(i)
			// skip unexported anonymous field
			if tf.PkgPath != "" {
				continue
			}

			// skip ignored field
			if tag, _ := tf.Tag.Lookup(tagIdentifier); tag == `-` {
				continue
			}

			field := vv.Field(i)
			if tf.Anonymous && field.Kind() == reflect.Struct {
				structs = append(structs, field)
				continue
			}

			if err = e.Encode(field.Interface()); err != nil {
				fieldName := field.Type().String()
				return perrors.Wrapf(err, "failed to encode field: %s, %+v", fieldName, field.Interface())
			}
		}

		structs = structs[1:]
	}

	return nil
}