39 lines
1.4 KiB
Go
39 lines
1.4 KiB
Go
|
// Copyright (c) 2014 Arista Networks, Inc.
|
||
|
// Use of this source code is governed by the Apache License 2.0
|
||
|
// that can be found in the COPYING file.
|
||
|
|
||
|
// Package areflect provides utilities to help with reflection.
|
||
|
package areflect
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
// ForceExport returns a new reflect.Value that is identical to the one passed
|
||
|
// in argument except that it's considered as an exported symbol even if in
|
||
|
// reality it isn't.
|
||
|
//
|
||
|
// The `reflect' package intentionally makes it impossible to access the value
|
||
|
// of an unexported attribute. The implementation of reflect.DeepEqual() cheats
|
||
|
// as it bypasses this check. Unfortunately, we can't use the same cheat, which
|
||
|
// prevents us from re-implementing DeepEqual properly or implementing some other
|
||
|
// reflection-based tools. So this is our cheat on top of theirs. It makes
|
||
|
// the given reflect.Value appear as if it was exported.
|
||
|
//
|
||
|
// This function requires go1.6 or newer.
|
||
|
func ForceExport(v reflect.Value) reflect.Value {
|
||
|
// constants from reflect/value.go
|
||
|
const flagStickyRO uintptr = 1 << 5
|
||
|
const flagEmbedRO uintptr = 1 << 6 // new in go1.6 (was flagIndir before)
|
||
|
const flagRO uintptr = flagStickyRO | flagEmbedRO
|
||
|
ptr := unsafe.Pointer(&v)
|
||
|
rv := (*struct {
|
||
|
typ unsafe.Pointer // a *reflect.rtype (reflect.Type)
|
||
|
ptr unsafe.Pointer // The value wrapped by this reflect.Value
|
||
|
flag uintptr
|
||
|
})(ptr)
|
||
|
rv.flag &= ^flagRO // Unset the flag so this value appears to be exported.
|
||
|
return v
|
||
|
}
|