コード例 #1
0
ファイル: server.go プロジェクト: tenntenn/netchan
func (cnn *serverConn) handle(chpv reflect.Value, name []byte) {

	handler := func(ws *websocket.Conn) {

		// send
		go func() {
			for {
				if v, ok := chpv.Recv(); ok {
					cnn.codec.Send(ws, v)
				} else {
					panic(Closed)
				}
			}
		}()

		// recieve
		for {
			v := reflect.New(chpv.Type().Elem())
			cnn.codec.Receive(ws, v.Interface())
			chpv.Send(reflect.Indirect(v))
		}
	}

	encodedName := base64.URLEncoding.EncodeToString(name)
	if _, ok := cnn.channels[encodedName]; !ok {
		cnn.channels[encodedName] = true
		pattern := fmt.Sprintf("/%s", encodedName)
		cnn.handlers.Handle(pattern, websocket.Handler(handler))
	}
}
コード例 #2
0
ファイル: netchan.go プロジェクト: CNDonny/scope
// Publish all values that arrive on the channel until it is closed or we
// encounter an error.
func chPublish(c *EncodedConn, chVal reflect.Value, subject string) {
	for {
		val, ok := chVal.Recv()
		if !ok {
			// Channel has most likely been closed.
			return
		}
		if e := c.Publish(subject, val.Interface()); e != nil {
			// Do this under lock.
			c.Conn.mu.Lock()
			defer c.Conn.mu.Unlock()

			if c.Conn.Opts.AsyncErrorCB != nil {
				// FIXME(dlc) - Not sure this is the right thing to do.
				// FIXME(ivan) - If the connection is not yet closed, try to schedule the callback
				if c.Conn.isClosed() {
					go c.Conn.Opts.AsyncErrorCB(c.Conn, nil, e)
				} else {
					c.Conn.ach <- func() { c.Conn.Opts.AsyncErrorCB(c.Conn, nil, e) }
				}
			}
			return
		}
	}
}
コード例 #3
0
ファイル: apply.go プロジェクト: nativetouch/gopath
func applyToChan(obj reflect.Value, head P, mid string, tail P, ctx *Context) error {
	if dir := obj.Type().ChanDir(); dir != reflect.RecvDir && dir != reflect.BothDir {
		return fmt.Errorf("invalid channel direction '%s' at '%s'", dir, head)
	}

	switch mid {

	case "1":
		result, ok := obj.Recv()
		if !ok {
			return ErrMissing
		}

		return apply(result, append(head, mid), tail, ctx)

	case "*":
		for !ctx.stop {
			result, ok := obj.Recv()
			if !ok {
				return nil
			}

			if err := apply(result, append(head, mid), tail, ctx); err != nil && err != ErrMissing {
				return err
			}
		}

		return nil

	default:
		return fmt.Errorf("invalid channel component '%s' at '%s'", mid, head)

	}
}
コード例 #4
0
ファイル: iterate.go プロジェクト: gitter-badger/cfops
func iterateChan(valueOfIter reflect.Value, out chan Pair) {
	i := 0

	for v, ok := valueOfIter.Recv(); ok; v, ok = valueOfIter.Recv() {
		out <- Pair{i, v.Interface()}
		i++
	}
}
コード例 #5
0
ファイル: func.go プロジェクト: benashford/go-func
func pMapChanInt(inChan reflect.Value, f interface{}, outChan reflect.Value) {
	fVal := reflect.ValueOf(f)
	val, ok := inChan.Recv()
	for ok {
		results := fVal.Call([]reflect.Value{val})
		outChan.Send(results[0])
		val, ok = inChan.Recv()
	}
	outChan.Close()
}
コード例 #6
0
ファイル: fatchan.go プロジェクト: rjmcguire/fatchan
func (t *Transport) fromChan(cid uint64, cval reflect.Value) error {
	// Type check! woo
	if cval.Kind() != reflect.Chan {
		return fmt.Errorf("fatchan: cannot connect a %s - must be a channel", cval.Type())
	}
	if cval.Type().ChanDir()&reflect.RecvDir == 0 {
		return fmt.Errorf("fatchan: cannot connect a %s - send-only channel", cval.Type())
	}

	sid := t.sid

	go func() {
		buf := new(bytes.Buffer)
		for {
			// Keep reusing the same buffer
			buf.Reset()

			// Wait for an object from the channel
			v, ok := cval.Recv()
			if !ok {
				// send close message
				t.writeBuf(cid, buf)
				return
			}

			// Encode the object
			if err := t.encodeValue(buf, v); err != nil {
				t.err(sid, cid, err)
				continue
			}

			// Send the encoding
			if err := t.writeBuf(cid, buf); err != nil {
				t.err(sid, cid, err)
				break
			}
		}
		// Drain the channel to close
		for {
			v, ok := cval.Recv()
			if !ok {
				break
			}
			t.err(sid, cid, fmt.Errorf("discarding %+v - channel closed due to error", v))
		}
		// Send EOF
		t.err(sid, cid, io.EOF)
	}()

	return nil
}
コード例 #7
0
ファイル: netchan.go プロジェクト: nagyist/nats
// Publish all values that arrive on the channel until it is closed or we
// ecounter an error.
func chPublish(c *EncodedConn, chVal reflect.Value, subject string) {
	for {
		val, ok := chVal.Recv()
		if !ok {
			// Channel has most likely been closed.
			return
		}
		if e := c.Publish(subject, val.Interface()); e != nil {
			if c.Conn.Opts.AsyncErrorCB != nil {
				// FIXME(dlc) - Not sure this is the right thing to do.
				go c.Conn.Opts.AsyncErrorCB(c.Conn, nil, e)
			}
			return
		}
	}
}
コード例 #8
0
ファイル: channels.go プロジェクト: privatego/glow
func ConnectTypedWriteChannelToRaw(writeChan reflect.Value, c chan []byte, wg *sync.WaitGroup) {
	wg.Add(1)
	go func() {
		defer wg.Done()

		var t reflect.Value
		for ok := true; ok; {
			if t, ok = writeChan.Recv(); ok {
				var buf bytes.Buffer
				enc := gob.NewEncoder(&buf)
				if err := enc.EncodeValue(t); err != nil {
					log.Fatal("data type:", t.Type().String(), " ", t.Kind(), " encode error:", err)
				}
				c <- buf.Bytes()
			}
		}
		close(c)

	}()

}
コード例 #9
0
ファイル: reduce.go プロジェクト: feyeleanor/sexp
func reduceChan(c reflect.Value, seed, f interface{}) (r interface{}, ok bool) {
	switch f := f.(type) {
	case func(interface{}, interface{}) interface{}:
		v := reflect.New(c.Type().Elem()).Elem()
		v.Set(reflect.ValueOf(seed))
		for {
			if x, open := c.Recv(); open {
				v = reflect.ValueOf(f(v.Interface(), x))
			} else {
				break
			}
		}
		r = v.Interface()
		ok = true

	default:
		if f := reflect.ValueOf(f); f.Kind() == reflect.Func {
			v := reflect.New(c.Type().Elem()).Elem()
			v.Set(reflect.ValueOf(seed))
			switch f.Type().NumIn() {
			case 2:
				for {
					if x, open := c.Recv(); open {
						v = f.Call([]reflect.Value{v, x})[0]
					} else {
						break
					}
				}
				ok = true
			}
			if ok {
				r = v.Interface()
			}
		}
	}
	return
}
コード例 #10
0
func eachChannel(enum *Enumerator, c R.Value) (i int) {
	var forEachReceived func(func(R.Value))
	var x R.Value
	var open bool

	if enum.Span == 1 {
		forEachReceived = func(f func(R.Value)) {
			for {
				if x, open = c.Recv(); !open {
					PanicWithIndex(enum.cursor)
				}
				f(x)
				i++
			}
			enum.cursor++
		}
	} else {
		forEachReceived = func(f func(R.Value)) {
			var offset int
			for {
				for offset = enum.Span; offset > 0; offset-- {
					if x, open = c.Recv(); !open {
						PanicWithIndex(enum.cursor + enum.Span)
					}
				}
				f(x)
				i++
			}
			enum.cursor += enum.Span
		}
	}
	switch f := enum.f.(type) {
	case func(interface{}):
		forEachReceived(func(v R.Value) {
			f(v.Interface())
		})
	case func(int, interface{}):
		forEachReceived(func(v R.Value) {
			f(enum.cursor, v.Interface())
		})
	case func(interface{}, interface{}):
		forEachReceived(func(v R.Value) {
			f(enum.cursor, v.Interface())
		})
	case func(R.Value):
		forEachReceived(func(v R.Value) {
			f(v)
		})
	case func(int, R.Value):
		forEachReceived(func(v R.Value) {
			f(enum.cursor, v)
		})
	case func(interface{}, R.Value):
		forEachReceived(func(v R.Value) {
			f(enum.cursor, v)
		})
	case func(R.Value, R.Value):
		forEachReceived(func(v R.Value) {
			f(R.ValueOf(enum.cursor), v)
		})
	case chan interface{}:
		forEachReceived(func(v R.Value) {
			f <- v.Interface()
		})
	case chan R.Value:
		forEachReceived(func(v R.Value) {
			f <- v
		})
		//	case []chan interface{}:
		//	case []chan R.Value:
	default:
		if f := R.ValueOf(f); f.Kind() == R.Func {
			if t := f.Type(); !t.IsVariadic() {
				switch t.NumIn() {
				case 1: //	f(v)
					p := make([]R.Value, 1, 1)
					forEachReceived(func(v R.Value) {
						p[0] = v
						f.Call(p)
					})
				case 2: //	f(i, v)
					p := make([]R.Value, 2, 2)
					forEachReceived(func(v R.Value) {
						p[0], p[1] = R.ValueOf(enum.cursor), v
						f.Call(p)
					})
				default:
					panic(UNHANDLED_ITERATOR)
				}
			}
		} else {
			panic(UNHANDLED_ITERATOR)
		}
	}
	return
}
コード例 #11
0
ファイル: partial_iterate.go プロジェクト: feyeleanor/sexp
func whileChannel(c R.Value, r bool, f interface{}) (count int) {
	switch f := f.(type) {
	case func(interface{}) bool:
		for v, open := c.Recv(); open && f(v.Interface()) == r; count++ {
			v, open = c.Recv()
		}

	case func(int, interface{}) bool:
		for v, open := c.Recv(); open && f(count, v.Interface()) == r; count++ {
			v, open = c.Recv()
		}

	case func(interface{}, interface{}) bool:
		for v, open := c.Recv(); open && f(count, v.Interface()) == r; count++ {
			v, open = c.Recv()
		}

	case func(...interface{}) bool:
		p := make([]interface{}, 0, 4)
		for v, open := c.Recv(); open; {
			p = append(p, v.Interface())
			v, open = c.Recv()
		}
		if f(p...) == r {
			count = 1
		}

	case func(bool, ...interface{}) int:
		p := make([]interface{}, 0, 4)
		for v, open := c.Recv(); open; {
			p = append(p, v.Interface())
			v, open = c.Recv()
		}
		count = f(r, p...)

	case func(R.Value) bool:
		for v, open := c.Recv(); open && f(v) == r; count++ {
			v, open = c.Recv()
		}

	case func(int, R.Value) bool:
		for v, open := c.Recv(); open && f(count, v) == r; count++ {
			v, open = c.Recv()
		}

	case func(interface{}, R.Value) bool:
		for v, open := c.Recv(); open && f(count, v) == r; count++ {
			v, open = c.Recv()
		}

	case func(R.Value, R.Value) bool:
		for v, open := c.Recv(); open && f(R.ValueOf(count), v) == r; count++ {
			v, open = c.Recv()
		}

	case func(...R.Value) bool:
		p := make([]R.Value, 0, 4)
		for v, open := c.Recv(); open; {
			p = append(p, v)
			v, open = c.Recv()
		}
		if f(p...) == r {
			count = 1
		}

	case func(bool, ...R.Value) int:
		p := make([]R.Value, 0, 4)
		for v, open := c.Recv(); open; {
			p = append(p, v)
			v, open = c.Recv()
		}
		count = f(r, p...)

	default:
		if f := R.ValueOf(f); f.Kind() == R.Func {
			if t := f.Type(); t.IsVariadic() {
				switch t.NumIn() {
				case 1: //	f(...v) bool
					p := make([]R.Value, 0, 4)
					i := 0
					for v, open := c.Recv(); open; i++ {
						p = append(p, v)
						v, open = c.Recv()
					}
					if f.Call(p)[0].Bool() == r {
						count = 1
					}

				case 2: //	f(bool, ...v) int
					p := make([]R.Value, 0, 4)
					i := 0
					for v, open := c.Recv(); open; i++ {
						p = append(p, v)
						v, open = c.Recv()
					}
					count = int(f.Call(p)[0].Int())
				}

			} else {
				switch t.NumIn() {
				case 1: //	f(v) bool
					open := false
					p := make([]R.Value, 1, 1)
					for p[0], open = c.Recv(); open && f.Call(p)[0].Bool() == r; count++ {
						p[0], open = c.Recv()
					}

				case 2: //	f(i, v) bool
					open := false
					p := make([]R.Value, 2, 2)
					p[0] = R.ValueOf(0)
					for p[1], open = c.Recv(); open && f.Call(p)[0].Bool() == r; count++ {
						p[0] = R.ValueOf(count)
						p[1], open = c.Recv()
					}
				}

			}
		}
	}
	return
}
コード例 #12
0
ファイル: while.go プロジェクト: feyeleanor/sequences
func whileChannel(c R.Value, r bool, f interface{}) (count int) {
	switch f := f.(type) {
	case func(interface{}) bool:
		for v, open := c.Recv(); open && f(v.Interface()) == r; count++ {
			v, open = c.Recv()
		}
	case func(int, interface{}) bool:
		for v, open := c.Recv(); open && f(count, v.Interface()) == r; count++ {
			v, open = c.Recv()
		}
	case func(interface{}, interface{}) bool:
		for v, open := c.Recv(); open && f(count, v.Interface()) == r; count++ {
			v, open = c.Recv()
		}
	case func(R.Value) bool:
		for v, open := c.Recv(); open && f(v) == r; count++ {
			v, open = c.Recv()
		}
	case func(int, R.Value) bool:
		for v, open := c.Recv(); open && f(count, v) == r; count++ {
			v, open = c.Recv()
		}
	case func(interface{}, R.Value) bool:
		for v, open := c.Recv(); open && f(count, v) == r; count++ {
			v, open = c.Recv()
		}
	case func(R.Value, R.Value) bool:
		for v, open := c.Recv(); open && f(R.ValueOf(count), v) == r; count++ {
			v, open = c.Recv()
		}
	default:
		if f := R.ValueOf(f); f.Kind() == R.Func {
			if t := f.Type(); t.NumOut() == 1 {
				switch t.NumIn() {
				case 1: //	f(v) bool
					open := false
					p := make([]R.Value, 1, 1)
					for p[0], open = c.Recv(); open && f.Call(p)[0].Bool() == r; count++ {
						p[0], open = c.Recv()
					}
				case 2: //	f(i, v) bool
					open := false
					p := make([]R.Value, 2, 2)
					p[0] = R.ValueOf(0)
					for p[1], open = c.Recv(); open && f.Call(p)[0].Bool() == r; count++ {
						p[0] = R.ValueOf(count)
						p[1], open = c.Recv()
					}
				default:
					panic(UNHANDLED_ITERATOR)
				}
			}
		}
	}
	return
}
コード例 #13
0
ファイル: fatchan.go プロジェクト: gonuts/fatchan
func (t *Transport) fromChan(cval reflect.Value) (uint64, uint64, error) {
	sid, cid := t.sid, atomic.AddUint64(&t.nextCID, 1)

	// Type check! woo
	if cval.Kind() != reflect.Chan {
		return sid, cid, fmt.Errorf("fatchan: cannot connect a %s - must be a channel", cval.Type())
	}
	if cval.Type().ChanDir()&reflect.RecvDir == 0 {
		return sid, cid, fmt.Errorf("fatchan: cannot connect a %s - send-only channel", cval.Type())
	}

	var raw [8]byte
	send := func(buf *bytes.Buffer) error {
		t.write.Lock()
		defer t.write.Unlock()

		// Send the cid
		n := binary.PutUvarint(raw[:], cid)
		if _, err := t.rwc.Write(raw[:n]); err != nil {
			return err
		}
		// Send the length
		n = binary.PutUvarint(raw[:], uint64(buf.Len()))
		if _, err := t.rwc.Write(raw[:n]); err != nil {
			return err
		}
		// Send the bytes
		if _, err := io.Copy(t.rwc, buf); err != nil {
			return err
		}
		return nil
	}

	go func() {
		buf := new(bytes.Buffer)
		for {
			// Keep reusing the same buffer
			buf.Reset()

			// Wait for an object from the channel
			v, ok := cval.Recv()
			if !ok {
				send(buf)
				return
			}

			// Encode the object
			if err := t.encodeValue(buf, v); err != nil {
				t.err(sid, cid, err)
				continue
			}

			// Send the encoding
			if err := send(buf); err != nil {
				t.err(sid, cid, err)
				break
			}
		}
		for {
			v, ok := cval.Recv()
			if !ok {
				break
			}
			t.err(sid, cid, fmt.Errorf("discarding %+v - channel closed", v))
		}
		t.err(sid, cid, io.EOF)
	}()

	return sid, cid, nil
}
コード例 #14
0
ファイル: table.go プロジェクト: bmatsuo/go-table
// Iterate over a range of values, issuing a callback for each one. The callback
// fn is expected to take two arguments (index/key, value pair) and return an
// error.
func doRange(t *testingT, v reflect.Value, fn interface{}) {
	t = t.sub("internal doRange")
	fnval := reflect.ValueOf(fn)
	fntyp := fnval.Type()
	if numin := fntyp.NumIn(); numin != 2 {
		t.Fatalf("function of %d arguments %v", numin, fn)
	} else if numout := fntyp.NumOut(); numout != 1 {
		t.Fatalf("function of %d return values %v", numout, fn)
	}
	zero := reflect.Zero(fnval.Type().In(1))
	var out reflect.Value
	switch k := v.Kind(); k {
	case reflect.Slice:
		for i, n := 0, v.Len(); i < n; i++ {
			ival, vval := reflect.ValueOf(i), v.Index(i)
			arg := validValue(t.sub(sprintf("index %d", i)), vval, zero)
			if !arg.IsValid() {
				continue
			}
			out = fnval.Call([]reflect.Value{ival, arg})[0]
			if !out.IsNil() {
				t.Error(out.Interface())
				break
			}

		}
	case reflect.Map:
		for _, kval := range v.MapKeys() {
			vval := v.MapIndex(kval)
			arg := validValue(t.sub(sprintf("index %v", kval.Interface())), vval, zero)
			if !arg.IsValid() {
				continue
			}
			out = fnval.Call([]reflect.Value{kval, arg})[0]
			if !out.IsNil() {
				t.Error(out.Interface())
				break
			}
		}
	case reflect.Chan:
		var vval reflect.Value
		var ok bool
		for i := 0; true; i++ {
			ival := reflect.ValueOf(i)
			if vval, ok = v.Recv(); !ok {
				break
			}
			arg := validValue(t.sub(sprintf("received value %d", i)), vval, zero)
			if !arg.IsValid() {
				continue
			}
			out = fnval.Call([]reflect.Value{ival, arg})[0]
			if !out.IsNil() {
				t.Error(out.Interface())
				break
			}
		}
	default:
		t.Fatalf("unacceptable type for range %v", v.Type())
	}
}
コード例 #15
0
ファイル: iterate.go プロジェクト: feyeleanor/sexp
func rangeChannel(c R.Value, f interface{}) (ok bool) {
	switch f := f.(type) {
	case func(interface{}):
		for v, open := c.Recv(); open; {
			f(v.Interface())
			v, open = c.Recv()
		}
		ok = true

	case func(int, interface{}):
		i := 0
		for v, open := c.Recv(); open; i++ {
			f(i, v.Interface())
			v, open = c.Recv()
		}
		ok = true

	case func(interface{}, interface{}):
		i := 0
		for v, open := c.Recv(); open; i++ {
			f(i, v.Interface())
			v, open = c.Recv()
		}
		ok = true

	case func(...interface{}):
		p := make([]interface{}, 0, 4)
		for v, open := c.Recv(); open; {
			p = append(p, v.Interface())
			v, open = c.Recv()
		}
		f(p...)
		ok = true

	case func(R.Value):
		for v, open := c.Recv(); open; {
			f(v)
			v, open = c.Recv()
		}
		ok = true

	case func(int, R.Value):
		i := 0
		for v, open := c.Recv(); open; i++ {
			f(i, v)
			v, open = c.Recv()
		}
		ok = true

	case func(interface{}, R.Value):
		i := 0
		for v, open := c.Recv(); open; i++ {
			f(i, v)
			v, open = c.Recv()
		}
		ok = true

	case func(...R.Value):
		p := make([]R.Value, 0, 4)
		for v, open := c.Recv(); open; {
			p = append(p, v)
			v, open = c.Recv()
		}
		f(p...)
		ok = true

	default:
		if f := R.ValueOf(f); f.Kind() == R.Func {
			if t := f.Type(); t.IsVariadic() {
				//	f(...v)
				p := make([]R.Value, 0, 4)
				for v, open := c.Recv(); open; {
					p = append(p, v)
					v, open = c.Recv()
				}
				f.Call(p)
			} else {
				switch t.NumIn() {
				case 1: //	f(v)
					p := make([]R.Value, 1, 1)
					for v, open := c.Recv(); open; {
						p[0] = v
						f.Call(p)
						v, open = c.Recv()
					}
					ok = true

				case 2: //	f(i, v)
					p := make([]R.Value, 2, 2)
					i := 0
					for v, open := c.Recv(); open; i++ {
						p[0], p[1] = R.ValueOf(i), v
						f.Call(p)
						v, open = c.Recv()
					}
					ok = true
				}
			}
		}
	}
	return
}
コード例 #16
0
ファイル: template.go プロジェクト: gnanderson/kasia.go
func (tpl *Template) run(wr io.Writer, defer_out *[][]byte,
	ctx ...interface{}) (ret bool, err error) {
	for _, va := range tpl.elems {
		switch el := va.(type) {
		case *TxtElem:
			_, err = wr.Write(el.txt)
			if err != nil {
				return
			}

		case *VarFunElem:
			var val reflect.Value
			val, err = execVarFun(wr, el, ctx, tpl.Strict)
			if err != nil {
				return
			}
			// Dereferencja zwroconej wartosci
			dereference(&val)
			if !val.IsValid() {
				break
			}
			switch vtn := val.Interface().(type) {
			case Template:
				// Zagniezdzony szablon
				err = vtn.Run(wr, ctx...)
				if err != nil {
					err = RunErr{el.ln, RUN_NESTED, err}
					return
				}
			case NestedTemplate:
				// Zagniezdzony szablon z wlasnym kontekstem
				err = vtn.tpl.Run(wr, vtn.ctx...)
				if err != nil {
					err = RunErr{el.ln, RUN_NESTED, err}
					return
				}
			case []byte:
				// Raw text
				if el.filt && tpl.EscapeFunc != nil {
					err = tpl.EscapeFunc(wr, vtn)
				} else {
					_, err = wr.Write(vtn)
				}
			default:
				// Inna wartosc
				if el.filt && tpl.EscapeFunc != nil {
					// Wysylamy z wykorzystaniem EscapeFunc
					var buf bytes.Buffer
					fmt.Fprint(&buf, vtn)
					err = tpl.EscapeFunc(wr, buf.Bytes())
				} else {
					// Wysylamy
					_, err = fmt.Fprint(wr, vtn)
				}
			}
			//# 20.17

		case *IfElem:
			var v1, v2 reflect.Value
			// Parametry musza istniec jesli porownujemy je ze soba.
			v1, err = execParam(wr, el.arg1, ctx, el.ln, el.cmp != if_nocmp)
			if err != nil {
				return
			}
			var tf bool
			if el.cmp == if_nocmp {
				tf = getBool(v1)
			} else {
				v2, err = execParam(wr, el.arg2, ctx, el.ln, true)
				if err != nil {
					return
				}
				var stat int
				tf, stat = getCmp(v1, v2, el.cmp)
				if stat != RUN_OK {
					err = RunErr{el.ln, stat, nil}
					return
				}
			}
			// Aby wyswietlic blok if'a tworzymy kopie glownego szablonu.
			ift := *tpl
			// W kopii podmieniamy liste elementow na liste wybranego bloku.
			if tf {
				ift.elems = el.true_block
			} else {
				ift.elems = el.false_block
			}
			// Renderujemy szablon wybranego bloku.
			ret, err = ift.run(wr, defer_out, ctx...)
			if ret || err != nil {
				return
			}

		case *ForElem:
			var val reflect.Value
			val, err = execVarFun(wr, el.arg, ctx, false)
			if err != nil {
				return
			}
			// Tworzymy kopie glownego szablonu dla blokow for'a.
			for_tpl := *tpl
			// Dereferencja argumentu
			dereference(&val)
			switch val.Kind() {
			case reflect.Array, reflect.Slice:
				val_len := val.Len()
				if val_len != 0 {
					for_tpl.elems = el.iter_block
					// Tworzymy kontekst dla iteracyjnego bloku for
					local_ctx := make(map[string]interface{})
					for_ctx := append(ctx, local_ctx)
					for ii := 0; ii < val_len; ii++ {
						ev := val.Index(ii)
						if ev.IsValid() {
							local_ctx[el.val] = ev.Interface()
						} else {
							local_ctx[el.val] = nil
						}
						local_ctx[el.iter] = ii + el.iter_inc
						ret, err = for_tpl.run(wr, defer_out, for_ctx...)
						if ret || err != nil {
							return
						}
					}
				} else {
					// Pusta tablica
					for_tpl.elems = el.else_block
					ret, err = for_tpl.run(wr, defer_out, ctx...)
					if ret || err != nil {
						return
					}
				}
			case reflect.Map:
				if val.Len() != 0 {
					if el.iter_inc != 0 {
						err = RunErr{el.ln, RUN_INC_MAP_KEY, nil}
						return
					}
					for_tpl.elems = el.iter_block
					// Tworzymy kontekst dla iteracyjnego bloku for
					local_ctx := make(map[string]interface{})
					for_ctx := append(ctx, local_ctx)
					for _, key := range val.MapKeys() {
						ev := val.MapIndex(key)
						if ev.IsValid() {
							local_ctx[el.val] = ev.Interface()
						} else {
							local_ctx[el.val] = nil
						}
						local_ctx[el.iter] = key.Interface()
						ret, err = for_tpl.run(wr, defer_out, for_ctx...)
						if ret || err != nil {
							return
						}
					}
				} else {
					// Pusty slownik
					for_tpl.elems = el.else_block
					ret, err = for_tpl.run(wr, defer_out, ctx...)
					if ret || err != nil {
						return
					}
				}
			case reflect.Chan:
				for_tpl.elems = el.iter_block
				// Tworzymy kontekst dla iteracyjnego bloku for
				local_ctx := make(map[string]interface{})
				for_ctx := append(ctx, local_ctx)
				ii := el.iter_inc
				for {
					ev, ok := val.Recv()
					if !ok {
						break
					}
					if ev.IsValid() {
						local_ctx[el.val] = ev.Interface()
					} else {
						local_ctx[el.val] = nil
					}
					local_ctx[el.iter] = ii
					ret, err = for_tpl.run(wr, defer_out, for_ctx...)
					if ret || err != nil {
						return
					}
					ii++
				}
				if ii == el.iter_inc {
					// Nic nie odebralismy z kanalu
					for_tpl.elems = el.else_block
					ret, err = for_tpl.run(wr, defer_out, ctx...)
					if ret || err != nil {
						return
					}
				}
			case reflect.Invalid:
				for_tpl.elems = el.else_block
				ret, err = for_tpl.run(wr, defer_out, ctx...)
				if ret || err != nil {
					return
				}
			default:
				// Zmienna jest skalarem, różnym od nil
				for_tpl.elems = el.iter_block
				ret, err = for_tpl.run(
					wr,
					defer_out,
					append(
						ctx,
						map[string]interface{}{
							el.val:  val.Interface(),
							el.iter: nil,
						},
					)...,
				)
				if ret || err != nil {
					return
				}
			}

		case *ReturnElem:
			ret = true
			return

		case *DeferElem:
			buf := new(bytes.Buffer)
			// Tworzymy kopie glonego szablonu dla bloku defer
			defer_tpl := *tpl
			// W kopii podmieniamy liste elementow na liste bloku defer
			defer_tpl.elems = el.defer_block
			// Uruchamiamy blok defer a jego wyjscie zapisujemy w buforze
			_, err = defer_tpl.run(buf, defer_out, ctx...)
			if err != nil {
				return
			}
			// Zapisujemy wynik na stos opoznionego wyjscia
			*defer_out = append(*defer_out, buf.Bytes())

		default:
			panic(fmt.Sprintln("Blaa!:", el))
			panic("tmpl:exec: Unknown element!")
		}
	}
	return
}
コード例 #17
0
ファイル: encode.go プロジェクト: eswdd/bosun
func (f encFnInfo) kSlice(rv reflect.Value) {
	ti := f.ti
	// array may be non-addressable, so we have to manage with care
	//   (don't call rv.Bytes, rv.Slice, etc).
	// E.g. type struct S{B [2]byte};
	//   Encode(S{}) will bomb on "panic: slice of unaddressable array".
	if f.seq != seqTypeArray {
		if rv.IsNil() {
			f.ee.EncodeNil()
			return
		}
		// If in this method, then there was no extension function defined.
		// So it's okay to treat as []byte.
		if ti.rtid == uint8SliceTypId {
			f.ee.EncodeStringBytes(c_RAW, rv.Bytes())
			return
		}
	}
	rtelem := ti.rt.Elem()
	l := rv.Len()
	if rtelem.Kind() == reflect.Uint8 {
		switch f.seq {
		case seqTypeArray:
			// if l == 0 { f.ee.encodeStringBytes(c_RAW, nil) } else
			if rv.CanAddr() {
				f.ee.EncodeStringBytes(c_RAW, rv.Slice(0, l).Bytes())
			} else {
				var bs []byte
				if l <= cap(f.e.b) {
					bs = f.e.b[:l]
				} else {
					bs = make([]byte, l)
				}
				reflect.Copy(reflect.ValueOf(bs), rv)
				// TODO: Test that reflect.Copy works instead of manual one-by-one
				// for i := 0; i < l; i++ {
				// 	bs[i] = byte(rv.Index(i).Uint())
				// }
				f.ee.EncodeStringBytes(c_RAW, bs)
			}
		case seqTypeSlice:
			f.ee.EncodeStringBytes(c_RAW, rv.Bytes())
		case seqTypeChan:
			bs := f.e.b[:0]
			// do not use range, so that the number of elements encoded
			// does not change, and encoding does not hang waiting on someone to close chan.
			// for b := range rv.Interface().(<-chan byte) {
			// 	bs = append(bs, b)
			// }
			ch := rv.Interface().(<-chan byte)
			for i := 0; i < l; i++ {
				bs = append(bs, <-ch)
			}
			f.ee.EncodeStringBytes(c_RAW, bs)
		}
		return
	}

	if ti.mbs {
		if l%2 == 1 {
			f.e.errorf("mapBySlice requires even slice length, but got %v", l)
			return
		}
		f.ee.EncodeMapStart(l / 2)
	} else {
		f.ee.EncodeArrayStart(l)
	}

	e := f.e
	if l > 0 {
		for rtelem.Kind() == reflect.Ptr {
			rtelem = rtelem.Elem()
		}
		// if kind is reflect.Interface, do not pre-determine the
		// encoding type, because preEncodeValue may break it down to
		// a concrete type and kInterface will bomb.
		var fn encFn
		if rtelem.Kind() != reflect.Interface {
			rtelemid := reflect.ValueOf(rtelem).Pointer()
			fn = e.getEncFn(rtelemid, rtelem, true, true)
		}
		// TODO: Consider perf implication of encoding odd index values as symbols if type is string
		for j := 0; j < l; j++ {
			if f.seq == seqTypeChan {
				if rv2, ok2 := rv.Recv(); ok2 {
					e.encodeValue(rv2, fn)
				}
			} else {
				e.encodeValue(rv.Index(j), fn)
			}
		}

	}

	f.ee.EncodeEnd()
}
コード例 #18
0
ファイル: enumerator.go プロジェクト: feyeleanor/sequences
func skipToChannelOffset(c R.Value, offset int) int {
	for open := true; open && offset > 0; offset-- {
		_, open = c.Recv()
	}
	return offset
}