func()

in ref.go [105:157]


func (e *Encoder) checkRefMap(v reflect.Value) (int, bool) {
	var (
		kind reflect.Kind
		tp   reflect.Type
		addr unsafe.Pointer
	)

	if v.Kind() == reflect.Ptr {
		for v.Elem().Kind() == reflect.Ptr {
			v = v.Elem()
		}
		kind = v.Elem().Kind()
		if kind != reflect.Invalid {
			tp = v.Elem().Type()
		}
		if kind == reflect.Slice || kind == reflect.Map {
			addr = unsafe.Pointer(v.Elem().Pointer())
		} else {
			addr = unsafe.Pointer(v.Pointer())
		}
	} else {
		kind = v.Kind()
		tp = v.Type()
		switch kind {
		case reflect.Slice, reflect.Map:
			addr = unsafe.Pointer(v.Pointer())
		default:
			addr = unsafe.Pointer(PackPtr(v).Pointer())
		}
	}

	if addr == _emptySliceAddr || addr == _nilMapAddr {
		return 0, false
	}

	if elem, ok := e.refMap[addr]; ok {
		if elem.kind == kind {
			// If kind is not struct, just return the index. Otherwise,
			// check whether the types are same, because the different
			// empty struct may share the same address and kind.
			if elem.kind != reflect.Struct {
				return elem.index, ok
			} else if elem.tp == tp {
				return elem.index, ok
			}
		}
		return 0, false
	}

	n := len(e.refMap)
	e.refMap[addr] = _refElem{kind, tp, n}
	return 0, false
}