blob: 25c20035a9c26a2aae341f84c54b31340be5e90d [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001// +build android
2
3package main
4
5import (
6 "fmt"
7 "path"
8 "reflect"
9 "strings"
10
11 // Imported IDLs. Please add a link to all IDLs you care about here,
12 // and add all interfaces you care about to the init() function below.
13 "veyron/examples/fortune"
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070014 "veyron2/ipc"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070015)
16
Jiri Simsa5293dcb2014-05-10 09:56:38 -070017func init() {
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070018 registerInterface((*fortune.Fortune)(nil))
19 registerInterface((*fortune.FortuneService)(nil))
Jiri Simsa5293dcb2014-05-10 09:56:38 -070020}
21
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070022// A list of all registered argGetter-s.
23var register map[string]*argGetter = make(map[string]*argGetter)
24
25// registerInterface registers the provided IDL client or server interface
26// so that its methods' arguments can be created on-the-fly.
27func registerInterface(ifacePtr interface{}) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070028 t := reflect.TypeOf(ifacePtr)
29 if t.Kind() != reflect.Ptr {
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070030 panic(fmt.Sprintf("expected pointer type for %q, got: %v", ifacePtr, t.Kind()))
Jiri Simsa5293dcb2014-05-10 09:56:38 -070031 }
32 t = t.Elem()
33 if t.Kind() != reflect.Interface {
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070034 panic(fmt.Sprintf("expected interface type for %q, got: %v", ifacePtr, t.Kind()))
Jiri Simsa5293dcb2014-05-10 09:56:38 -070035 }
36
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070037 // Create a new arg getter.
Jiri Simsa5293dcb2014-05-10 09:56:38 -070038 methods := make(map[string][]methodInfo)
39 for i := 0; i < t.NumMethod(); i++ {
40 m := t.Method(i)
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070041 in := make([]reflect.Type, m.Type.NumIn()-1)
42 idx := 0
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -070043 contextType := reflect.TypeOf((*ipc.ServerContext)(nil)).Elem()
44 optType := reflect.TypeOf((*ipc.CallOpt)(nil)).Elem()
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070045 for j := 0; j < m.Type.NumIn(); j++ {
46 argType := m.Type.In(j)
47 if j == 0 && argType == contextType { // skip the Context argument.
48 continue
49 }
50 if j == m.Type.NumIn()-1 && argType == optType { // skip the CallOption argument.
51 continue
52 }
53 in[idx] = argType
54 idx++
Jiri Simsa5293dcb2014-05-10 09:56:38 -070055 }
56 out := make([]reflect.Type, m.Type.NumOut()-1) // skip error argument
57 for j := 0; j < m.Type.NumOut()-1; j++ {
58 out[j] = m.Type.Out(j)
59 }
60 mis := methods[m.Name]
61 mis = append(mis, methodInfo{
62 inTypes: in,
63 outTypes: out,
64 })
65 methods[m.Name] = mis
66 }
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070067 path := path.Join(t.PkgPath(), t.Name())
68 register[path] = &argGetter{
Jiri Simsa5293dcb2014-05-10 09:56:38 -070069 methods: methods,
70 idlPath: path,
71 }
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070072}
Jiri Simsa5293dcb2014-05-10 09:56:38 -070073
Srdjan Petrovic16683eb2014-05-19 17:31:34 -070074// newPtrInstance returns the pointer to the new instance of the provided type.
75func newPtrInstance(t reflect.Type) interface{} {
76 return reflect.New(t).Interface()
77}
78
79// newArgGetter returns the argument getter for the provided IDL interface.
80func newArgGetter(javaIdlIfacePath string) *argGetter {
81 return register[strings.Join(strings.Split(javaIdlIfacePath, ".")[1:], "/")]
Jiri Simsa5293dcb2014-05-10 09:56:38 -070082}
83
84// argGetter serves method arguments for a specific interface.
85type argGetter struct {
86 methods map[string][]methodInfo
87 idlPath string
88}
89
90// methodInfo contains argument type information for a method belonging to an interface.
91type methodInfo struct {
92 inTypes []reflect.Type
93 outTypes []reflect.Type
94}
95
96func (m methodInfo) String() string {
97 in := fmt.Sprintf("[%d]", len(m.inTypes))
98 out := fmt.Sprintf("[%d]", len(m.outTypes))
99 for _, t := range m.inTypes {
100 in = in + ", " + t.Name()
101 }
102 for _, t := range m.outTypes {
103 out = out + ", " + t.Name()
104 }
105 return fmt.Sprintf("(%s; %s)", in, out)
106}
107
108// findMethod returns the method type information for the given method, or nil if
109// the method doesn't exist.
110func (ag *argGetter) findMethod(method string, numInArgs int) *methodInfo {
111 ms, ok := ag.methods[method]
112 if !ok {
113 return nil
114 }
115 var m *methodInfo
116 for _, mi := range ms {
117 if len(mi.inTypes) == numInArgs {
118 m = &mi
119 break
120 }
121 }
122 return m
123}
124
125// GetInArgTypes returns types of all input arguments for the given method.
126func (ag *argGetter) GetInArgTypes(method string, numInArgs int) ([]reflect.Type, error) {
127 m := ag.findMethod(method, numInArgs)
128 if m == nil {
129 return nil, fmt.Errorf("couldn't find method %q with %d args in path %s", method, numInArgs, ag.idlPath)
130 }
131 return m.inTypes, nil
132}
133
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700134// GenInArgPtrs returns pointers to instances of all input arguments for the given method.
135func (ag *argGetter) GetInArgPtrs(method string, numInArgs int) (argptrs []interface{}, err error) {
136 m := ag.findMethod(method, numInArgs)
137 if m == nil {
138 return nil, fmt.Errorf("couldn't find method %q with %d args in path %s", method, numInArgs, ag.idlPath)
139 }
140 argptrs = make([]interface{}, len(m.inTypes))
141 for i, arg := range m.inTypes {
142 argptrs[i] = newPtrInstance(arg)
143 }
144 return
145}
146
147// GetOurArgTypes returns types of all output arguments for the given method.
148func (ag *argGetter) GetOutArgTypes(method string, numInArgs int) ([]reflect.Type, error) {
149 m := ag.findMethod(method, numInArgs)
150 if m == nil {
151 return nil, fmt.Errorf("couldn't find method %q with %d args in path %s", method, numInArgs, ag.idlPath)
152 }
153 return m.outTypes, nil
154}
155
Srdjan Petrovic16683eb2014-05-19 17:31:34 -0700156// GetOutArgPtrs returns pointers to instances of all output arguments for the given method.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700157func (ag *argGetter) GetOutArgPtrs(method string, numInArgs int) (argptrs []interface{}, err error) {
158 m := ag.findMethod(method, numInArgs)
159 if m == nil {
160 return nil, fmt.Errorf("couldn't find method %q with %d args in path %s", method, numInArgs, ag.idlPath)
161 }
162 argptrs = make([]interface{}, len(m.outTypes))
163 for i, arg := range m.outTypes {
164 argptrs[i] = newPtrInstance(arg)
165 }
166 return
167}
168
169// argGetters is a cache of created argument getters, keyed by IDL interface path.
170var argGetters map[string]*argGetter = make(map[string]*argGetter)