func Transform(...option) cmp.Option {
	// addrType returns a pointer to t if t isn't a pointer or interface.
	addrType := func(t reflect.Type) reflect.Type {
		if k := t.Kind(); k == reflect.Interface || k == reflect.Ptr {
			return t
		}
		return reflect.PtrTo(t)
	}

	// TODO: Should this transform protoreflect.Enum types to Enum as well?
	return cmp.FilterPath(func(p cmp.Path) bool {
		ps := p.Last()
		if isMessageType(addrType(ps.Type())) {
			return true
		}

		// Check whether the concrete values of an interface both satisfy
		// the Message interface.
		if ps.Type().Kind() == reflect.Interface {
			vx, vy := ps.Values()
			if !vx.IsValid() || vx.IsNil() || !vy.IsValid() || vy.IsNil() {
				return false
			}
			return isMessageType(addrType(vx.Elem().Type())) && isMessageType(addrType(vy.Elem().Type()))
		}

		return false
	}, cmp.Transformer("protocmp.Transform", func(v interface{}) Message {
		// For user convenience, shallow copy the message value if necessary
		// in order for it to implement the message interface.
		if rv := reflect.ValueOf(v); rv.IsValid() && rv.Kind() != reflect.Ptr && !isMessageType(rv.Type()) {
			pv := reflect.New(rv.Type())
			pv.Elem().Set(rv)
			v = pv.Interface()
		}

		m := protoimpl.X.MessageOf(v)
		switch {
		case m == nil:
			return nil
		case !m.IsValid():
			return Message{messageTypeKey: messageType{md: m.Descriptor()}, messageInvalidKey: true}
		default:
			return transformMessage(m)
		}
	}))
}
// Transform returns a cmp.Option that converts each proto.Message to a Message.
// The transformation does not mutate nor alias any converted messages.
//
// The google.protobuf.Any message is automatically unmarshaled such that the
// "value" field is a Message representing the underlying message value
// assuming it could be resolved and properly unmarshaled.
//
// This does not directly transform higher-order composite Go types.
// For example, []*foopb.Message is not transformed into []Message,
// but rather the individual message elements of the slice are transformed.
//
// Note that there are currently no custom options for Transform,
// but the use of an unexported type keeps the future open.
Transform returns a cmp.Option that converts each proto.Message to a Message.
The transformation does not mutate nor alias any converted messages.

The google.protobuf.Any message is automatically unmarshaled such that the
"value" field is a Message representing the underlying message value
assuming it could be resolved and properly unmarshaled.

This does not directly transform higher-order composite Go types.
For example, []*foopb.Message is not transformed into []Message,
but rather the individual message elements of the slice are transformed.

Note that there are currently no custom options for Transform,
but the use of an unexported type keeps the future open.
// Transform returns a cmp . Option that converts each proto . Message to a Message . // The transformation does not mutate nor alias any converted messages . // // The google . protobuf . Any message is automatically unmarshaled such that the // " value " field is a Message representing the underlying message value // assuming it could be resolved and properly unmarshaled . // // This does not directly transform higher - order composite Go types . // For example [] * foopb . Message is not transformed into [] Message // but rather the individual message elements of the slice are transformed . // // Note that there are currently no custom options for Transform // but the use of an unexported type keeps the future open .
func Transform(...option) cmp.Option {
	addrType := func(t reflect.Type) reflect.Type {
		if k := t.Kind(); k == reflect.Interface || k == reflect.Ptr {
			return t
		}
		return reflect.PtrTo(t)
	}
	return cmp.FilterPath(func(p cmp.Path) bool {
		ps := p.Last()
		if isMessageType(addrType(ps.Type())) {
			return true
		}
		if ps.Type().Kind() == reflect.Interface {
			vx, vy := ps.Values()
			if !vx.IsValid() || vx.IsNil() || !vy.IsValid() || vy.IsNil() {
				return false
			}
			return isMessageType(addrType(vx.Elem().Type())) && isMessageType(addrType(vy.Elem().Type()))
		}
		return false
	}, cmp.Transformer("protocmp.Transform", func(v interface{}) Message {
		if rv := reflect.ValueOf(v); rv.IsValid() && rv.Kind() != reflect.Ptr && !isMessageType(rv.Type()) {
			pv := reflect.New(rv.Type())
			pv.Elem().Set(rv)
			v = pv.Interface()
		}
		m := protoimpl.X.MessageOf(v)
		switch {
		case m == nil:
			return nil
		case !m.IsValid():
			return Message{messageTypeKey: messageType{md: m.Descriptor()}, messageInvalidKey: true}
		default:
			return transformMessage(m)
		}
	}))
}
func Transform ( ... option ) cmp . Option { addrType := func ( t reflect . Type ) reflect . Type { if k := t . Kind ( ) ; k == reflect . Interface || k == reflect . Ptr { return t } return reflect . PtrTo ( t ) } return cmp . FilterPath ( func ( p cmp . Path ) bool { ps := p . Last ( ) if isMessageType ( addrType ( ps . Type ( ) ) ) { return true } if ps . Type ( ) . Kind ( ) == reflect . Interface { vx , vy := ps . Values ( ) if ! vx . IsValid ( ) || vx . IsNil ( ) || ! vy . IsValid ( ) || vy . IsNil ( ) { return false } return isMessageType ( addrType ( vx . Elem ( ) . Type ( ) ) ) && isMessageType ( addrType ( vy . Elem ( ) . Type ( ) ) ) } return false } , cmp . Transformer ( " " , func ( v interface { } ) Message { if rv := reflect . ValueOf ( v ) ; rv . IsValid ( ) && rv . Kind ( ) != reflect . Ptr && ! isMessageType ( rv . Type ( ) ) { pv := reflect . New ( rv . Type ( ) ) pv . Elem ( ) . Set ( rv ) v = pv . Interface ( ) } m := protoimpl . X . MessageOf ( v ) switch { case m == nil : return nil case ! m . IsValid ( ) : return Message { messageTypeKey : messageType { md : m . Descriptor ( ) } , messageInvalidKey : true } default : return transformMessage ( m ) } } ) ) }
Transform returns a cmp.Option that converts each proto.Message to a Message.
Transform returns a cmp . Option that converts each proto . Message to a Message .
// addrType returns a pointer to t if t isn't a pointer or interface. // TODO: Should this transform protoreflect.Enum types to Enum as well? // Check whether the concrete values of an interface both satisfy // the Message interface. // For user convenience, shallow copy the message value if necessary // in order for it to implement the message interface.