Switch to exports
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
parent
219fc093b1
commit
9f8572018f
@ -4,8 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
)
|
)
|
||||||
@ -42,7 +40,7 @@ func (inv *invoker) Invoke(act *Actor, vmctx *VMContext, method uint64, params [
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv *invoker) register(c cid.Cid, instance interface{}) {
|
func (inv *invoker) register(c cid.Cid, instance Invokee) {
|
||||||
code, err := inv.transform(instance)
|
code, err := inv.transform(instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -54,51 +52,45 @@ type unmarshalCBOR interface {
|
|||||||
UnmarshalCBOR([]byte) (int, error)
|
UnmarshalCBOR([]byte) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Invokee interface {
|
||||||
|
Exports() []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
var tUnmarhsalCBOR = reflect.TypeOf((*unmarshalCBOR)(nil)).Elem()
|
var tUnmarhsalCBOR = reflect.TypeOf((*unmarshalCBOR)(nil)).Elem()
|
||||||
var tError = reflect.TypeOf((*error)(nil)).Elem()
|
var tError = reflect.TypeOf((*error)(nil)).Elem()
|
||||||
|
|
||||||
func (*invoker) transform(instance interface{}) (nativeCode, error) {
|
func (*invoker) transform(instance Invokee) (nativeCode, error) {
|
||||||
itype := reflect.TypeOf(instance)
|
itype := reflect.TypeOf(instance)
|
||||||
newErr := func(str string) error {
|
exports := instance.Exports()
|
||||||
return fmt.Errorf("transform(%s): %s", itype.Name(), str)
|
for i, m := range exports {
|
||||||
|
i := i
|
||||||
|
newErr = func(str string) error {
|
||||||
|
return fmt.Errorf("transform(%s) export(%d): %s", itype.Name(), i, str)
|
||||||
}
|
}
|
||||||
var maxn uint64
|
if m == nil {
|
||||||
invokes := make(map[uint64]reflect.Method)
|
|
||||||
for i := 0; i < itype.NumMethod(); i++ {
|
|
||||||
meth := itype.Method(i)
|
|
||||||
if !strings.HasPrefix(meth.Name, "Invoke") {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sid := strings.TrimLeftFunc(meth.Name, func(r rune) bool {
|
meth := reflect.ValueOf(m)
|
||||||
return r < '0' || r > '9'
|
t := meth.Type()
|
||||||
})
|
if t.Kind() != reflect.Func {
|
||||||
|
return nil, newErr("is not a function")
|
||||||
id, err := strconv.ParseUint(sid, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
if t.NumIn() != 3 {
|
||||||
t := meth.Type
|
|
||||||
if t.NumIn() != 4 {
|
|
||||||
return nil, newErr("wrong number of inputs should be: " +
|
return nil, newErr("wrong number of inputs should be: " +
|
||||||
"*Actor, *VMContext, <type of parameter>")
|
"*Actor, *VMContext, <type of parameter>")
|
||||||
}
|
}
|
||||||
if t.In(0) != itype {
|
if t.In(0) != reflect.TypeOf(&Actor{}) {
|
||||||
return nil, newErr("passed instance is not struct")
|
|
||||||
}
|
|
||||||
if t.In(1) != reflect.TypeOf(&Actor{}) {
|
|
||||||
return nil, newErr("first arguemnt should be *Actor")
|
return nil, newErr("first arguemnt should be *Actor")
|
||||||
}
|
}
|
||||||
if t.In(2) != reflect.TypeOf(&VMContext{}) {
|
if t.In(1) != reflect.TypeOf(&VMContext{}) {
|
||||||
return nil, newErr("second argument should be *VMContext")
|
return nil, newErr("second argument should be *VMContext")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !t.In(3).Implements(tUnmarhsalCBOR) {
|
if !t.In(2).Implements(tUnmarhsalCBOR) {
|
||||||
return nil, newErr("parameter doesn't implement UnmarshalCBOR")
|
return nil, newErr("parameter doesn't implement UnmarshalCBOR")
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.In(3).Kind() != reflect.Ptr {
|
if t.In(2).Kind() != reflect.Ptr {
|
||||||
return nil, newErr("parameter has to be a pointer")
|
return nil, newErr("parameter has to be a pointer")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,21 +105,13 @@ func (*invoker) transform(instance interface{}) (nativeCode, error) {
|
|||||||
return nil, newErr("second output should be error type")
|
return nil, newErr("second output should be error type")
|
||||||
}
|
}
|
||||||
|
|
||||||
if id > maxn {
|
|
||||||
maxn = id
|
|
||||||
}
|
}
|
||||||
if _, has := invokes[id]; has {
|
code := make(nativeCode, len(exports))
|
||||||
return nil, newErr(fmt.Sprintf("repeated method=%s id: %d", meth.Name, id))
|
for id, m := range exports {
|
||||||
}
|
meth := reflect.ValueOf(m)
|
||||||
invokes[id] = meth
|
|
||||||
}
|
|
||||||
code := make(nativeCode, maxn+1)
|
|
||||||
_ = code
|
|
||||||
for id, meth := range invokes {
|
|
||||||
meth := meth
|
|
||||||
code[id] = reflect.MakeFunc(reflect.TypeOf((invokeFunc)(nil)),
|
code[id] = reflect.MakeFunc(reflect.TypeOf((invokeFunc)(nil)),
|
||||||
func(in []reflect.Value) []reflect.Value {
|
func(in []reflect.Value) []reflect.Value {
|
||||||
paramT := meth.Type.In(3).Elem()
|
paramT := meth.Type().In(2).Elem()
|
||||||
param := reflect.New(paramT)
|
param := reflect.New(paramT)
|
||||||
|
|
||||||
inBytes := in[2].Interface().([]byte)
|
inBytes := in[2].Interface().([]byte)
|
||||||
@ -138,8 +122,8 @@ func (*invoker) transform(instance interface{}) (nativeCode, error) {
|
|||||||
reflect.ValueOf(err),
|
reflect.ValueOf(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return meth.Func.Call([]reflect.Value{
|
return meth.Call([]reflect.Value{
|
||||||
reflect.ValueOf(instance), in[0], in[1], param,
|
in[0], in[1], param,
|
||||||
})
|
})
|
||||||
}).Interface().(invokeFunc)
|
}).Interface().(invokeFunc)
|
||||||
|
|
||||||
|
@ -16,6 +16,22 @@ func (b *basicParams) UnmarshalCBOR(in []byte) (int, error) {
|
|||||||
return 1, nil
|
return 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b basicContract) Exports() []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
b.InvokeSomething0,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
b.InvokeSomething10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (basicContract) InvokeSomething0(act *Actor, vmctx *VMContext,
|
func (basicContract) InvokeSomething0(act *Actor, vmctx *VMContext,
|
||||||
params *basicParams) (InvokeRet, error) {
|
params *basicParams) (InvokeRet, error) {
|
||||||
return InvokeRet{
|
return InvokeRet{
|
||||||
@ -37,7 +53,7 @@ func TestInvokerBasic(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, byte(1), ret.returnCode, "return code should be 1")
|
assert.Equal(t, byte(1), ret.returnCode, "return code should be 1")
|
||||||
|
|
||||||
ret, err = code[10](nil, nil, []byte{1})
|
ret, err = code[10](nil, nil, []byte{2})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, byte(11), ret.returnCode, "return code should be 1")
|
assert.Equal(t, byte(12), ret.returnCode, "return code should be 1")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user