Browse Source

Added export method for structs

luis 7 năm trước cách đây
mục cha
commit
42264fa0f1
3 tập tin đã thay đổi với 66 bổ sung15 xóa
  1. 66 6
      clientctx.go
  2. 0 2
      wsrpc.go
  3. 0 7
      wsrpcAssets/wsrpcAssets.go.bak

+ 66 - 6
clientctx.go

@@ -2,12 +2,24 @@
 package wsrpc
 
 import (
+	"errors"
+	"log"
+	"reflect"
+	"strings"
 	"sync"
 
 	"github.com/google/uuid"
 	"golang.org/x/net/websocket"
 )
 
+var (
+	ErrNParam            = errors.New("Invalid number of parameters")
+	ErrNReturn           = errors.New("Number of outputs mismatch")
+	ErrBadImplementation = errors.New("Bad implementation")
+
+	errorInterface = reflect.TypeOf((*error)(nil)).Elem()
+)
+
 // Call object
 type CallObj struct {
 	OP     string `json:"op"`     // operation
@@ -19,10 +31,10 @@ type CallObj struct {
 }
 
 // DataObj common structure for dymanic json object
-type DataObj map[string]interface{}
+//type DataObj map[string]interface{}
 
 // ListenerFunc function type to handle browser events
-type ListenerFunc func(...interface{}) interface{}
+type ListenerFunc func(...interface{}) (interface{}, error)
 
 // Request request type for handling requests channels
 
@@ -52,16 +64,19 @@ func (c *ClientCtx) Process(data CallObj) {
 	case "call":
 		params := data.Params
 		var idn = data.Method
-		var reqId = data.ID
+		var reqID = data.ID
 		var fn, ok = c.listeners[idn]
 		if !ok {
 			return
 		}
-		go func() {
-			ret := fn(params...)
+		go func() { // async send
+			ret, err := fn(params...)
+			if err != nil {
+				log.Println("Create error response, panic?")
+			}
 			var responseObj = CallObj{
 				OP:       "response",
-				ID:       reqId,
+				ID:       reqID,
 				Response: ret,
 			}
 			//log.Println("Sending response")
@@ -103,3 +118,48 @@ func (c *ClientCtx) Call(method string, params ...interface{}) interface{} {
 func (c *ClientCtx) Define(name string, listener ListenerFunc) {
 	c.listeners[name] = listener
 }
+
+func (c *ClientCtx) Export(obj interface{}) {
+	// Reflect here
+	typ := reflect.TypeOf(obj)
+	val := reflect.ValueOf(obj)
+
+	for i := 0; i < typ.NumField(); i++ {
+		fTyp := typ.Field(i)
+		if fTyp.Type.Kind() != reflect.Func {
+			log.Println("Ignore non func value")
+			continue
+		}
+		tag, ok := fTyp.Tag.Lookup("wsexport")
+		if !ok {
+			continue
+		}
+		tagParts := strings.Split(tag, ",")
+
+		exportName := tagParts[0]
+		fnVal := val.Field(i)
+		// Slow?
+		c.listeners[exportName] = func(params ...interface{}) (interface{}, error) {
+			if len(params) != fnVal.Type().NumIn() {
+				return nil, ErrNParam
+			}
+			if fnVal.Type().NumOut() != 2 {
+				return nil, ErrNReturn
+			}
+			if !fnVal.Type().Out(1).Implements(errorInterface) {
+				return nil, ErrBadImplementation
+
+			}
+
+			vparam := []reflect.Value{}
+			for _, p := range params {
+				vparam = append(vparam, reflect.ValueOf(p))
+			}
+			r := fnVal.Call(vparam)
+			return r[0].Interface(), r[1].Interface().(error)
+		}
+
+		// It is a func, check for tag
+	}
+
+}

+ 0 - 2
wsrpc.go

@@ -32,10 +32,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
 	switch urlPath {
 	case "ws", "wsrpc":
-		log.Println("Provide ws connection")
 		h.wsHandler.ServeHTTP(w, r)
 	case "cli.js": // Serve client JS file
-		log.Println("Sending cli")
 		w.Header().Set("Content-type", "application/javascript")
 		w.WriteHeader(200)
 		w.Write(wsrpcAssets.Data["wsrpc.js"])

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 7
wsrpcAssets/wsrpcAssets.go.bak