github.com/Psiphon-Inc/goarista@v0.0.0-20160825065156-d002785f4c67/areflect/force.go (about)

     1  // Copyright (C) 2014  Arista Networks, Inc.
     2  // Use of this source code is governed by the Apache License 2.0
     3  // that can be found in the COPYING file.
     4  
     5  // Package areflect provides utilities to help with reflection.
     6  package areflect
     7  
     8  import (
     9  	"reflect"
    10  	"unsafe"
    11  )
    12  
    13  // ForceExport returns a new reflect.Value that is identical to the one passed
    14  // in argument except that it's considered as an exported symbol even if in
    15  // reality it isn't.
    16  //
    17  // The `reflect' package intentionally makes it impossible to access the value
    18  // of an unexported attribute.  The implementation of reflect.DeepEqual() cheats
    19  // as it bypasses this check.  Unfortunately, we can't use the same cheat, which
    20  // prevents us from re-implementing DeepEqual properly or implementing some other
    21  // reflection-based tools.  So this is our cheat on top of theirs.  It makes
    22  // the given reflect.Value appear as if it was exported.
    23  func ForceExport(v reflect.Value) reflect.Value {
    24  	const flagRO uintptr = 1 << 5 // from reflect/value.go
    25  	ptr := unsafe.Pointer(&v)
    26  	rv := (*struct {
    27  		typ  unsafe.Pointer // a *reflect.rtype (reflect.Type)
    28  		ptr  unsafe.Pointer // The value wrapped by this reflect.Value
    29  		flag uintptr
    30  	})(ptr)
    31  	rv.flag &= ^flagRO // Unset the flag so this value appears to be exported.
    32  	return v
    33  }