Этот коммит содержится в:
Damian Gryski 2023-03-30 08:46:19 -07:00 коммит произвёл Ron Evans
родитель 5faff2e13a
коммит 0cd93a3a9e

Просмотреть файл

@ -14,6 +14,10 @@ type valueFlags uint8
const ( const (
valueFlagIndirect valueFlags = 1 << iota valueFlagIndirect valueFlags = 1 << iota
valueFlagExported valueFlagExported
valueFlagEmbedRO
valueFlagStickyRO
valueFlagRO = valueFlagEmbedRO | valueFlagStickyRO
) )
type Value struct { type Value struct {
@ -36,6 +40,16 @@ func (v Value) isExported() bool {
return v.flags&valueFlagExported != 0 return v.flags&valueFlagExported != 0
} }
func (v Value) isRO() bool {
return v.flags&(valueFlagRO) != 0
}
func (v Value) checkRO() {
if v.isRO() {
panic("reflect: value is not settable")
}
}
func Indirect(v Value) Value { func Indirect(v Value) Value {
if v.Kind() != Ptr { if v.Kind() != Ptr {
return v return v
@ -210,7 +224,7 @@ func (v Value) IsValid() bool {
} }
func (v Value) CanInterface() bool { func (v Value) CanInterface() bool {
return v.isExported() return v.isExported() && !v.isRO()
} }
func (v Value) CanAddr() bool { func (v Value) CanAddr() bool {
@ -268,7 +282,7 @@ func (v Value) UnsafeAddr() uintptr {
} }
func (v Value) CanSet() bool { func (v Value) CanSet() bool {
return v.flags&(valueFlagExported|valueFlagIndirect) == valueFlagExported|valueFlagIndirect return v.flags&(valueFlagExported|valueFlagIndirect|valueFlagRO) == valueFlagExported|valueFlagIndirect
} }
func (v Value) Bool() bool { func (v Value) Bool() bool {
@ -668,11 +682,22 @@ func (v Value) Field(i int) Value {
panic(&ValueError{Method: "Field", Kind: v.Kind()}) panic(&ValueError{Method: "Field", Kind: v.Kind()})
} }
structField := v.typecode.rawField(i) structField := v.typecode.rawField(i)
flags := v.flags
// Copy flags but clear EmbedRO; we're not an embedded field anymore
flags := v.flags & ^valueFlagEmbedRO
if structField.PkgPath != "" { if structField.PkgPath != "" {
// The fact that PkgPath is present means that this field is not // No PkgPath => not exported.
// exported. // Clear exported flag even if the parent was exported.
flags &^= valueFlagExported flags &^= valueFlagExported
// Update the RO flag
if structField.Anonymous {
// Embedded field
flags |= valueFlagEmbedRO
} else {
flags |= valueFlagStickyRO
}
} else { } else {
// Parent field may not have been exported but we are // Parent field may not have been exported but we are
flags |= valueFlagExported flags |= valueFlagExported
@ -1437,7 +1462,7 @@ func Zero(typ Type) Value {
return Value{ return Value{
typecode: typ.(*rawType), typecode: typ.(*rawType),
value: nil, value: nil,
flags: valueFlagExported, flags: valueFlagExported | valueFlagRO,
} }
} }
@ -1445,14 +1470,14 @@ func Zero(typ Type) Value {
return Value{ return Value{
typecode: typ.(*rawType), typecode: typ.(*rawType),
value: unsafe.Pointer(zerobuffer), value: unsafe.Pointer(zerobuffer),
flags: valueFlagExported, flags: valueFlagExported | valueFlagRO,
} }
} }
return Value{ return Value{
typecode: typ.(*rawType), typecode: typ.(*rawType),
value: alloc(typ.Size(), nil), value: alloc(typ.Size(), nil),
flags: valueFlagExported, flags: valueFlagExported | valueFlagRO,
} }
} }
@ -1546,6 +1571,10 @@ func Copy(dst, src Value) int {
dstbuf, dstlen := buflen(dst) dstbuf, dstlen := buflen(dst)
srcbuf, srclen := buflen(src) srcbuf, srclen := buflen(src)
if srclen > 0 {
dst.checkRO()
}
return sliceCopy(dstbuf, srcbuf, dstlen, srclen, dst.typecode.elem().Size()) return sliceCopy(dstbuf, srcbuf, dstlen, srclen, dst.typecode.elem().Size())
} }