<commit_before>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cronjob

import (
	"context"
	"fmt"
	"testing"
	"time"

	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/informers"
	clientset "k8s.io/client-go/kubernetes"
	clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1"
	restclient "k8s.io/client-go/rest"
	kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
	"k8s.io/kubernetes/pkg/controller/cronjob"
	"k8s.io/kubernetes/pkg/controller/job"
	"k8s.io/kubernetes/test/integration/framework"
)

func setup(t *testing.T) (kubeapiservertesting.TearDownFunc, *cronjob.ControllerV2, *job.Controller, informers.SharedInformerFactory, clientset.Interface) {
	// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
	server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd())

	config := restclient.CopyConfig(server.ClientConfig)
	clientSet, err := clientset.NewForConfig(config)
	if err != nil {
		t.Fatalf("Error creating clientset: %v", err)
	}
	resyncPeriod := 12 * time.Hour
	informerSet := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(config, "cronjob-informers")), resyncPeriod)
	cjc, err := cronjob.NewControllerV2(informerSet.Batch().V1().Jobs(), informerSet.Batch().V1().CronJobs(), clientSet)
	if err != nil {
		t.Fatalf("Error creating CronJob controller: %v", err)
	}
	jc := job.NewController(informerSet.Core().V1().Pods(), informerSet.Batch().V1().Jobs(), clientSet)

	return server.TearDownFn, cjc, jc, informerSet, clientSet
}

func newCronJob(name, namespace, schedule string) *batchv1.CronJob {
	zero64 := int64(0)
	zero32 := int32(0)
	return &batchv1.CronJob{
		TypeMeta: metav1.TypeMeta{
			Kind:       "CronJob",
			APIVersion: "batch/v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      name,
		},
		Spec: batchv1.CronJobSpec{
			Schedule:                   schedule,
			SuccessfulJobsHistoryLimit: &zero32,
			JobTemplate: batchv1.JobTemplateSpec{
				Spec: batchv1.JobSpec{
					Template: corev1.PodTemplateSpec{
						Spec: corev1.PodSpec{
							Containers:                    []corev1.Container{{Name: "foo", Image: "bar"}},
							TerminationGracePeriodSeconds: &zero64,
							RestartPolicy:                 "Never",
						},
					},
				},
			},
		},
	}
}

func cleanupCronJobs(t *testing.T, cjClient clientbatchv1.CronJobInterface, name string) {
	deletePropagation := metav1.DeletePropagationForeground
	err := cjClient.Delete(context.TODO(), name, metav1.DeleteOptions{PropagationPolicy: &deletePropagation})
	if err != nil {
		t.Errorf("Failed to delete CronJob: %v", err)
	}
}

func validateJobAndPod(t *testing.T, clientSet clientset.Interface, namespace string) {
	if err := wait.PollImmediate(1*time.Second, 120*time.Second, func() (bool, error) {
		jobs, err := clientSet.BatchV1().Jobs(namespace).List(context.TODO(), metav1.ListOptions{})
		if err != nil {
			t.Fatalf("Failed to list jobs: %v", err)
		}

		if len(jobs.Items) == 0 {
			return false, nil
		}

		for _, j := range jobs.Items {
			ownerReferences := j.ObjectMeta.OwnerReferences
			if refCount := len(ownerReferences); refCount != 1 {
				return false, fmt.Errorf("job %s has %d OwnerReferences, expected only 1", j.Name, refCount)
			}

			reference := ownerReferences[0]
			if reference.Kind != "CronJob" {
				return false, fmt.Errorf("job %s has OwnerReference with Kind %s, expected CronJob", j.Name, reference.Kind)
			}
		}

		pods, err := clientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
		if err != nil {
			t.Fatalf("Failed to list pods: %v", err)
		}

		if len(pods.Items) != 1 {
			return false, nil
		}

		for _, pod := range pods.Items {
			ownerReferences := pod.ObjectMeta.OwnerReferences
			if refCount := len(ownerReferences); refCount != 1 {
				return false, fmt.Errorf("pod %s has %d OwnerReferences, expected only 1", pod.Name, refCount)
			}

			reference := ownerReferences[0]
			if reference.Kind != "Job" {
				return false, fmt.Errorf("pod %s has OwnerReference with Kind %s, expected Job", pod.Name, reference.Kind)
			}
		}
		return true, nil
	}); err != nil {
		t.Fatal(err)
	}
}

func TestCronJobLaunchesPodAndCleansUp(t *testing.T) {
	closeFn, cjc, jc, informerSet, clientSet := setup(t)
	defer closeFn()

	cronJobName := "foo"
	namespaceName := "simple-cronjob-test"

	ns := framework.CreateNamespaceOrDie(clientSet, namespaceName, t)
	defer framework.DeleteNamespaceOrDie(clientSet, ns, t)

	cjClient := clientSet.BatchV1().CronJobs(ns.Name)

	stopCh := make(chan struct{})
	defer close(stopCh)

	informerSet.Start(stopCh)
	go cjc.Run(context.TODO(), 1)
	go jc.Run(context.TODO(), 1)

	_, err := cjClient.Create(context.TODO(), newCronJob(cronJobName, ns.Name, "* * * * ?"), metav1.CreateOptions{})
	if err != nil {
		t.Fatalf("Failed to create CronJob: %v", err)
	}
	defer cleanupCronJobs(t, cjClient, cronJobName)

	validateJobAndPod(t, clientSet, namespaceName)
}
<commit_msg>Clean shutdown of cronjob integration tests<commit_after>/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cronjob

import (
	"context"
	"fmt"
	"testing"
	"time"

	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/informers"
	clientset "k8s.io/client-go/kubernetes"
	clientbatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1"
	restclient "k8s.io/client-go/rest"
	kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
	"k8s.io/kubernetes/pkg/controller/cronjob"
	"k8s.io/kubernetes/pkg/controller/job"
	"k8s.io/kubernetes/test/integration/framework"
)

func setup(t *testing.T) (kubeapiservertesting.TearDownFunc, *cronjob.ControllerV2, *job.Controller, informers.SharedInformerFactory, clientset.Interface) {
	// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
	server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd())

	config := restclient.CopyConfig(server.ClientConfig)
	clientSet, err := clientset.NewForConfig(config)
	if err != nil {
		t.Fatalf("Error creating clientset: %v", err)
	}
	resyncPeriod := 12 * time.Hour
	informerSet := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(config, "cronjob-informers")), resyncPeriod)
	cjc, err := cronjob.NewControllerV2(informerSet.Batch().V1().Jobs(), informerSet.Batch().V1().CronJobs(), clientSet)
	if err != nil {
		t.Fatalf("Error creating CronJob controller: %v", err)
	}
	jc := job.NewController(informerSet.Core().V1().Pods(), informerSet.Batch().V1().Jobs(), clientSet)

	return server.TearDownFn, cjc, jc, informerSet, clientSet
}

func newCronJob(name, namespace, schedule string) *batchv1.CronJob {
	zero64 := int64(0)
	zero32 := int32(0)
	return &batchv1.CronJob{
		TypeMeta: metav1.TypeMeta{
			Kind:       "CronJob",
			APIVersion: "batch/v1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      name,
		},
		Spec: batchv1.CronJobSpec{
			Schedule:                   schedule,
			SuccessfulJobsHistoryLimit: &zero32,
			JobTemplate: batchv1.JobTemplateSpec{
				Spec: batchv1.JobSpec{
					Template: corev1.PodTemplateSpec{
						Spec: corev1.PodSpec{
							Containers:                    []corev1.Container{{Name: "foo", Image: "bar"}},
							TerminationGracePeriodSeconds: &zero64,
							RestartPolicy:                 "Never",
						},
					},
				},
			},
		},
	}
}

func cleanupCronJobs(t *testing.T, cjClient clientbatchv1.CronJobInterface, name string) {
	deletePropagation := metav1.DeletePropagationForeground
	err := cjClient.Delete(context.TODO(), name, metav1.DeleteOptions{PropagationPolicy: &deletePropagation})
	if err != nil {
		t.Errorf("Failed to delete CronJob: %v", err)
	}
}

func validateJobAndPod(t *testing.T, clientSet clientset.Interface, namespace string) {
	if err := wait.PollImmediate(1*time.Second, 120*time.Second, func() (bool, error) {
		jobs, err := clientSet.BatchV1().Jobs(namespace).List(context.TODO(), metav1.ListOptions{})
		if err != nil {
			t.Fatalf("Failed to list jobs: %v", err)
		}

		if len(jobs.Items) == 0 {
			return false, nil
		}

		for _, j := range jobs.Items {
			ownerReferences := j.ObjectMeta.OwnerReferences
			if refCount := len(ownerReferences); refCount != 1 {
				return false, fmt.Errorf("job %s has %d OwnerReferences, expected only 1", j.Name, refCount)
			}

			reference := ownerReferences[0]
			if reference.Kind != "CronJob" {
				return false, fmt.Errorf("job %s has OwnerReference with Kind %s, expected CronJob", j.Name, reference.Kind)
			}
		}

		pods, err := clientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
		if err != nil {
			t.Fatalf("Failed to list pods: %v", err)
		}

		if len(pods.Items) != 1 {
			return false, nil
		}

		for _, pod := range pods.Items {
			ownerReferences := pod.ObjectMeta.OwnerReferences
			if refCount := len(ownerReferences); refCount != 1 {
				return false, fmt.Errorf("pod %s has %d OwnerReferences, expected only 1", pod.Name, refCount)
			}

			reference := ownerReferences[0]
			if reference.Kind != "Job" {
				return false, fmt.Errorf("pod %s has OwnerReference with Kind %s, expected Job", pod.Name, reference.Kind)
			}
		}
		return true, nil
	}); err != nil {
		t.Fatal(err)
	}
}

func TestCronJobLaunchesPodAndCleansUp(t *testing.T) {
	closeFn, cjc, jc, informerSet, clientSet := setup(t)
	defer closeFn()

	cronJobName := "foo"
	namespaceName := "simple-cronjob-test"

	ns := framework.CreateNamespaceOrDie(clientSet, namespaceName, t)
	defer framework.DeleteNamespaceOrDie(clientSet, ns, t)

	cjClient := clientSet.BatchV1().CronJobs(ns.Name)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	informerSet.Start(ctx.Done())
	go cjc.Run(ctx, 1)
	go jc.Run(ctx, 1)

	_, err := cjClient.Create(context.TODO(), newCronJob(cronJobName, ns.Name, "* * * * ?"), metav1.CreateOptions{})
	if err != nil {
		t.Fatalf("Failed to create CronJob: %v", err)
	}
	defer cleanupCronJobs(t, cjClient, cronJobName)

	validateJobAndPod(t, clientSet, namespaceName)
}
<|endoftext|>


<commit_before>package scard

import (
	"bytes"
	"fmt"
	"syscall"
	"unsafe"
)

var (
	modwinscard          = syscall.NewLazyDLL("winscard.dll")
	procEstablishContext = modwinscard.NewProc("SCardEstablishContext")
	procRelease          = modwinscard.NewProc("SCardReleaseContext")
	procListReaders      = modwinscard.NewProc("SCardListReadersA")
	procConnect          = modwinscard.NewProc("SCardConnectA")
	procDisconnect	     = modwinscard.NewProc("SCardDisconnect")
	procStatus	     = modwinscard.NewProc("SCardStatusA")
	procGetAttrib	     = modwinscard.NewProc("SCardGetAttrib")
)

type Context struct {
	ctx uintptr
}

type Card struct {
	handle         uintptr
	activeProtocol uintptr
}

type scardError uintptr

func (e scardError) Error() string {
	//return "scard: " + C.GoString(C.pcsc_stringify_error(C.LONG(e)))
	err := syscall.Errno(e)
	return fmt.Sprintf("scard: error code %x: %s", uintptr(e), err.Error())
}

// wraps SCardEstablishContext
func EstablishContext() (*Context, error) {
	var ctx Context

	r, _, _ := procEstablishContext.Call(2, uintptr(0), uintptr(0), uintptr(unsafe.Pointer(&ctx.ctx)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	return &ctx, nil
}

// wraps SCardIsValidContext
func (ctx *Context) IsValid() (bool, error) {
	panic("scard: not implemented") // TODO
}

// wraps SCardCancel
func (ctx *Context) Cancel() error {
	panic("scard: not implemented") // TODO
}

// wraps SCardReleaseContext
func (ctx *Context) Release() error {
	r, _, _ := procRelease.Call(uintptr(ctx.ctx))
	if scardError(r) != S_SUCCESS {
		return scardError(r)
	}
	return nil
}

// wraps SCardListReaders
func (ctx *Context) ListReaders() ([]string, error) {
	var needed uint32

	r, _, _ := procListReaders.Call(
		ctx.ctx,
		0,
		0,
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	data := make([]byte, needed)

	r, _, _ = procListReaders.Call(
		ctx.ctx,
		0,
		uintptr(unsafe.Pointer(&data[0])),
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	var readers []string
	for _, b := range bytes.Split(data, []byte{0}) {
		if len(b) > 0 {
			readers = append(readers, string(b))
		}
	}

	return readers, nil
}

// wraps SCardListReaderGroups
func (ctx *Context) ListReaderGroups() ([]string, error) {
	panic("scard: not implemented")
}

// wraps SCardGetStatusChange
func (ctx *Context) GetStatusChange(readerStates []ReaderState, timeout Timeout) error {
	panic("scard: not implemented")
}

// wraps SCardConnect
func (ctx *Context) Connect(reader string, mode ShareMode, proto Protocol) (*Card, error) {
	var card Card

	creader := []byte(reader)
	creader = append(creader, 0)

	r, _, _ := procConnect.Call(
		ctx.ctx,
		uintptr(unsafe.Pointer(&creader[0])),
		uintptr(mode),
		uintptr(proto),
		uintptr(unsafe.Pointer(&card.handle)),
		uintptr(unsafe.Pointer(&card.activeProtocol)))

	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	return &card, nil
}

// wraps SCardDisconnect
func (card *Card) Disconnect(d Disposition) error {
	r, _, _ := procDisconnect.Call(card.handle, uintptr(d))
	if scardError(r) != S_SUCCESS {
		return scardError(r)
	}
	return nil
}

// wraps SCardReconnect
func (card *Card) Reconnect(mode ShareMode, protocol Protocol, init Disposition) error {
	panic("scard: not implemented")
}

// wraps SCardBeginTransaction
func (card *Card) BeginTransaction() error {
	panic("scard: not implemented")
}

// wraps SCardEndTransaction
func (card *Card) EndTransaction(d Disposition) error {
	panic("scard: not implemented")
}

// wraps SCardStatus
func (card *Card) Status() (*CardStatus, error) {
	var reader [MAX_READERNAME + 1]byte
	var readerLen = uint32(len(reader))
	var state, proto uint32
	var atr [MAX_ATR_SIZE]byte
	var atrLen = uint32(len(atr))

	r, _, _ := procStatus.Call(
		card.handle,
		uintptr(unsafe.Pointer(&reader[0])),
		uintptr(unsafe.Pointer(&readerLen)),
		uintptr(unsafe.Pointer(&state)),
		uintptr(unsafe.Pointer(&proto)),
		uintptr(unsafe.Pointer(&atr[0])),
		uintptr(unsafe.Pointer(&atrLen)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	status := &CardStatus {
		Reader:         string(reader[0:readerLen]),
		State:          State(state),
		ActiveProtocol: Protocol(proto),
		ATR:            atr[0:atrLen],
	}

	return status, nil
}

// wraps SCardTransmit
func (card *Card) Transmit(cmd []byte) ([]byte, error) {
	panic("scard: not implemented") // TODO
}

// wraps SCardControl
func (card *Card) Control(ctrl uint32, cmd []byte) ([]byte, error) {
	panic("scard: not implemented") // TODO
}

// wraps SCardGetAttrib
func (card *Card) GetAttrib(id uint32) ([]byte, error) {
	var needed uintptr

	r, _, _ := procGetAttrib.Call(
		card.handle,
		uintptr(id),
		0,
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	var attrib = make([]byte, needed)

	r, _, _ = procGetAttrib.Call(
		card.handle,
		uintptr(id),
		uintptr(unsafe.Pointer(&attrib[0])),
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	return attrib[0:needed], nil
}

// wraps SCardSetAttrib
func (card *Card) SetAttrib(id uint32, data []byte) error {
	panic("scard: not implemented") // TODO
}
<commit_msg>win: wip switch to unicode apis<commit_after>package scard

import (
	"fmt"
	"syscall"
	"unsafe"
)

var (
	modwinscard          = syscall.NewLazyDLL("winscard.dll")
	procEstablishContext = modwinscard.NewProc("SCardEstablishContext")
	procRelease          = modwinscard.NewProc("SCardReleaseContext")
	procListReaders      = modwinscard.NewProc("SCardListReadersW")
	procConnect          = modwinscard.NewProc("SCardConnectW")
	procDisconnect       = modwinscard.NewProc("SCardDisconnect")
	procStatus           = modwinscard.NewProc("SCardStatusW")
	procGetAttrib        = modwinscard.NewProc("SCardGetAttrib")
)

type Context struct {
	ctx uintptr
}

type Card struct {
	handle         uintptr
	activeProtocol uintptr
}

type scardError uintptr

func (e scardError) Error() string {
	//return "scard: " + C.GoString(C.pcsc_stringify_error(C.LONG(e)))
	err := syscall.Errno(e)
	return fmt.Sprintf("scard: error code %x: %s", uintptr(e), err.Error())
}

// wraps SCardEstablishContext
func EstablishContext() (*Context, error) {
	var ctx Context

	r, _, _ := procEstablishContext.Call(2, uintptr(0), uintptr(0), uintptr(unsafe.Pointer(&ctx.ctx)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	return &ctx, nil
}

// wraps SCardIsValidContext
func (ctx *Context) IsValid() (bool, error) {
	panic("scard: not implemented") // TODO
}

// wraps SCardCancel
func (ctx *Context) Cancel() error {
	panic("scard: not implemented") // TODO
}

// wraps SCardReleaseContext
func (ctx *Context) Release() error {
	r, _, _ := procRelease.Call(uintptr(ctx.ctx))
	if scardError(r) != S_SUCCESS {
		return scardError(r)
	}
	return nil
}

// wraps SCardListReaders
func (ctx *Context) ListReaders() ([]string, error) {
	var needed uintptr

	r, _, _ := procListReaders.Call(
		ctx.ctx,
		0,
		0,
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	data := make([]uint16, needed)
	needed <<= 1
	r, _, _ = procListReaders.Call(
		ctx.ctx,
		0,
		uintptr(unsafe.Pointer(&data[0])),
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

		fmt.Printf("% x\n", data)

	var readers []string
	for len(data) > 0 {
		pos := 0
		for ; pos < len(data); pos++ {
			if data[pos] == 0 {
				break
			}
		}
		reader := syscall.UTF16ToString(data[:pos])
		readers = append(readers, reader)
		data = data[pos+1:]
	}
	return readers, nil
}

// wraps SCardListReaderGroups
func (ctx *Context) ListReaderGroups() ([]string, error) {
	panic("scard: not implemented")
}

// wraps SCardGetStatusChange
func (ctx *Context) GetStatusChange(readerStates []ReaderState, timeout Timeout) error {
	panic("scard: not implemented")
}

// wraps SCardConnect
func (ctx *Context) Connect(reader string, mode ShareMode, proto Protocol) (*Card, error) {
	var card Card

	creader, err := syscall.UTF16PtrFromString(reader)
	if err != nil {
		return nil, err
	}

	r, _, _ := procConnect.Call(
		ctx.ctx,
		uintptr(unsafe.Pointer(creader)),
		uintptr(mode),
		uintptr(proto),
		uintptr(unsafe.Pointer(&card.handle)),
		uintptr(unsafe.Pointer(&card.activeProtocol)))

	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	return &card, nil
}

// wraps SCardDisconnect
func (card *Card) Disconnect(d Disposition) error {
	r, _, _ := procDisconnect.Call(card.handle, uintptr(d))
	if scardError(r) != S_SUCCESS {
		return scardError(r)
	}
	return nil
}

// wraps SCardReconnect
func (card *Card) Reconnect(mode ShareMode, protocol Protocol, init Disposition) error {
	panic("scard: not implemented")
}

// wraps SCardBeginTransaction
func (card *Card) BeginTransaction() error {
	panic("scard: not implemented")
}

// wraps SCardEndTransaction
func (card *Card) EndTransaction(d Disposition) error {
	panic("scard: not implemented")
}

// wraps SCardStatus
func (card *Card) Status() (*CardStatus, error) {
	var reader [MAX_READERNAME + 1]byte
	var readerLen = uint32(len(reader))
	var state, proto uint32
	var atr [MAX_ATR_SIZE]byte
	var atrLen = uint32(len(atr))

	r, _, _ := procStatus.Call(
		card.handle,
		uintptr(unsafe.Pointer(&reader[0])),
		uintptr(unsafe.Pointer(&readerLen)),
		uintptr(unsafe.Pointer(&state)),
		uintptr(unsafe.Pointer(&proto)),
		uintptr(unsafe.Pointer(&atr[0])),
		uintptr(unsafe.Pointer(&atrLen)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	status := &CardStatus{
		Reader:         string(reader[0:readerLen]),
		State:          State(state),
		ActiveProtocol: Protocol(proto),
		ATR:            atr[0:atrLen],
	}

	return status, nil
}

// wraps SCardTransmit
func (card *Card) Transmit(cmd []byte) ([]byte, error) {
	panic("scard: not implemented") // TODO
}

// wraps SCardControl
func (card *Card) Control(ctrl uint32, cmd []byte) ([]byte, error) {
	panic("scard: not implemented") // TODO
}

// wraps SCardGetAttrib
func (card *Card) GetAttrib(id uint32) ([]byte, error) {
	var needed uintptr

	r, _, _ := procGetAttrib.Call(
		card.handle,
		uintptr(id),
		0,
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	var attrib = make([]byte, needed)

	r, _, _ = procGetAttrib.Call(
		card.handle,
		uintptr(id),
		uintptr(unsafe.Pointer(&attrib[0])),
		uintptr(unsafe.Pointer(&needed)))
	if scardError(r) != S_SUCCESS {
		return nil, scardError(r)
	}

	return attrib[0:needed], nil
}

// wraps SCardSetAttrib
func (card *Card) SetAttrib(id uint32, data []byte) error {
	panic("scard: not implemented") // TODO
}
<|endoftext|>


<commit_before>package schema

import (
	"strings"

	"github.com/acsellers/inflections"
	"github.com/drone/sqlgen/parse"
)

func Load(tree *parse.Node) *Table {
	table := new(Table)

	// local map of indexes, used for quick
	// lookups and de-duping.
	indexs := map[string]*Index{}

	// pluralizes the table name and then
	// formats in snake case.
	table.Name = inflections.Underscore(tree.Type)
	table.Name = inflections.Pluralize(table.Name)

	// each edge node in the tree is a column
	// in the table. Convert each edge node to
	// a Field structure.
	for _, node := range tree.Edges() {

		field := new(Field)

		// Lookup the SQL column type
		// TODO: move this to a function
		t, ok := parse.Types[node.Type]
		if ok {
			tt, ok := types[t]
			if !ok {
				tt = BLOB
			}
			field.Type = tt
		} else {
			field.Type = BLOB
		}

		// substitute tag variables
		if node.Tags != nil {

			if node.Tags.Skip {
				continue
			}

			field.Auto = node.Tags.Auto
			field.Primary = node.Tags.Primary
			field.Size = node.Tags.Size

			if node.Tags.Primary {
				table.Primary = append(table.Primary, field)
			}

			if node.Tags.Index != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Index
					indexs[index.Name] = index
				}
				index.Fields = append(index.Fields, field)
			}

			if node.Tags.Unique != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Unique
					index.Unique = true
					indexs[index.Name] = index
					table.Index = append(table.Index, index)
				}
				index.Fields = append(index.Fields, field)
			}
		}

		// get the full path name
		path := node.Path()
		var parts []string
		for _, part := range path {
			parts = append(parts, part.Name)
		}
		field.Name = strings.Join(parts, "_")
		field.Name = inflections.Underscore(field.Name)

		table.Fields = append(table.Fields, field)
	}

	return table
}

// convert Go types to SQL types.
var types = map[uint8]int{
	parse.Bool:       BOOLEAN,
	parse.Int:        INTEGER,
	parse.Int8:       INTEGER,
	parse.Int16:      INTEGER,
	parse.Int32:      INTEGER,
	parse.Int64:      INTEGER,
	parse.Uint:       INTEGER,
	parse.Uint8:      INTEGER,
	parse.Uint16:     INTEGER,
	parse.Uint32:     INTEGER,
	parse.Uint64:     INTEGER,
	parse.Float32:    INTEGER,
	parse.Float64:    INTEGER,
	parse.Complex64:  INTEGER,
	parse.Complex128: INTEGER,
	parse.Interface:  BLOB,
	parse.Bytes:      BLOB,
	parse.String:     VARCHAR,
	parse.Map:        BLOB,
	parse.Slice:      BLOB,
}
<commit_msg>fixed an issue with regular indexes not being added to the tabe<commit_after>package schema

import (
	"strings"

	"github.com/acsellers/inflections"
	"github.com/drone/sqlgen/parse"
)

func Load(tree *parse.Node) *Table {
	table := new(Table)

	// local map of indexes, used for quick
	// lookups and de-duping.
	indexs := map[string]*Index{}

	// pluralizes the table name and then
	// formats in snake case.
	table.Name = inflections.Underscore(tree.Type)
	table.Name = inflections.Pluralize(table.Name)

	// each edge node in the tree is a column
	// in the table. Convert each edge node to
	// a Field structure.
	for _, node := range tree.Edges() {

		field := new(Field)

		// Lookup the SQL column type
		// TODO: move this to a function
		t, ok := parse.Types[node.Type]
		if ok {
			tt, ok := types[t]
			if !ok {
				tt = BLOB
			}
			field.Type = tt
		} else {
			field.Type = BLOB
		}

		// substitute tag variables
		if node.Tags != nil {

			if node.Tags.Skip {
				continue
			}

			field.Auto = node.Tags.Auto
			field.Primary = node.Tags.Primary
			field.Size = node.Tags.Size

			if node.Tags.Primary {
				table.Primary = append(table.Primary, field)
			}

			if node.Tags.Index != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Index
					indexs[index.Name] = index
					table.Index = append(table.Index, index)
				}
				index.Fields = append(index.Fields, field)
			}

			if node.Tags.Unique != "" {
				index, ok := indexs[node.Tags.Index]
				if !ok {
					index = new(Index)
					index.Name = node.Tags.Unique
					index.Unique = true
					indexs[index.Name] = index
					table.Index = append(table.Index, index)
				}
				index.Fields = append(index.Fields, field)
			}
		}

		// get the full path name
		path := node.Path()
		var parts []string
		for _, part := range path {
			parts = append(parts, part.Name)
		}
		field.Name = strings.Join(parts, "_")
		field.Name = inflections.Underscore(field.Name)

		table.Fields = append(table.Fields, field)
	}

	return table
}

// convert Go types to SQL types.
var types = map[uint8]int{
	parse.Bool:       BOOLEAN,
	parse.Int:        INTEGER,
	parse.Int8:       INTEGER,
	parse.Int16:      INTEGER,
	parse.Int32:      INTEGER,
	parse.Int64:      INTEGER,
	parse.Uint:       INTEGER,
	parse.Uint8:      INTEGER,
	parse.Uint16:     INTEGER,
	parse.Uint32:     INTEGER,
	parse.Uint64:     INTEGER,
	parse.Float32:    INTEGER,
	parse.Float64:    INTEGER,
	parse.Complex64:  INTEGER,
	parse.Complex128: INTEGER,
	parse.Interface:  BLOB,
	parse.Bytes:      BLOB,
	parse.String:     VARCHAR,
	parse.Map:        BLOB,
	parse.Slice:      BLOB,
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"time"
)

// gatewayConnectability will print an error to the log if the node has zero
// peers at any time.
func (j *JobRunner) gatewayConnectability() {
	for {
		time.Sleep(time.Second * 5)
		err := j.client.Get("/gateway", nil)
		if err != nil {
			log.Printf("[%v gatewayConnectability ERROR]: %v\n", j.siaDirectory, err)
			return
		}
	}
}
<commit_msg>print a warning in gateway job if node has zero peers<commit_after>package main

import (
	"log"
	"time"

	"github.com/NebulousLabs/Sia/api"
)

// gatewayConnectability will print an error to the log if the node has zero
// peers at any time.
func (j *JobRunner) gatewayConnectability() {
	for {
		time.Sleep(time.Second * 5)
		var gatewayInfo api.GatewayGET
		err := j.client.Get("/gateway", &gatewayInfo)
		if err != nil {
			log.Printf("[%v gatewayConnectability ERROR]: %v\n", j.siaDirectory, err)
			return
		}
		if len(gatewayInfo.Peers) == 0 {
			log.Printf("[%v gatewayConnectability WARN]: ant has zero peers", j.siaDirectory)
		}
	}
}
<|endoftext|>


<commit_before>package jsh

import (
	"fmt"
	"net/http"
	"strings"
)

/*
DefaultError can be customized in order to provide a more customized error
Detail message when an Internal Server Error occurs. Optionally, you can modify
a returned jsh.Error before sending it as a response as well.
*/
var DefaultErrorDetail = "Request failed, something went wrong."

// DefaultTitle can be customized to provide a more customized ISE Title
var DefaultErrorTitle = "Internal Server Error"

/*
ErrorType represents the common interface requirements that libraries may
specify if they would like to accept either a single error or a list.
*/
type ErrorType interface {
	// Error returns a formatted error and allows it to conform to the stdErr
	// interface.
	Error() string
	// Validate checks that the error is valid in the context of JSONAPI
	Validate(r *http.Request, response bool) *Error
	// StatusCode returns the first encountered HTTP Status Code for the error type.
	// Returns 0 if none is set.
	StatusCode() int
}

// ErrorList is wraps an Error Array so that it can implement Sendable
type ErrorList []*Error

// Validate checks all errors within the list to ensure that they are valid
func (e ErrorList) Validate(r *http.Request, response bool) *Error {
	for _, err := range e {
		validationErr := err.Validate(r, response)
		if validationErr != nil {
			return validationErr
		}
	}

	return nil
}

// Fulfills the default error interface
func (e ErrorList) Error() string {
	var msg string

	for _, err := range e {
		msg += fmt.Sprintf("%s\n", err.Error())
	}

	return msg
}

/*
StatusCode (HTTP) of the first error in the list. Defaults to 0 if the list is
empty or one has not yet been set for the first error.
*/
func (e ErrorList) StatusCode() int {
	if len(e) == 0 {
		return 0
	}

	return e[0].Status
}

/*
Error consists of a number of contextual attributes to make conveying
certain error type simpler as per the JSON API specification:
http://jsonapi.org/format/#error-objects

	error := &jsh.Error{
		Title: "Authentication Failure",
		Detail: "Category 4 Username Failure",
		Status: 401
	}

	jsh.Send(w, r, error)
*/
type Error struct {
	Title  string `json:"title"`
	Detail string `json:"detail"`
	Status int    `json:"status,string"`
	Source struct {
		Pointer string `json:"pointer"`
	} `json:"source"`
	ISE string `json:"-"`
}

/*
Error will print an internal server error if set, or default back to the SafeError()
format if not. As usual, err.Error() should not be considered safe for presentation
to the end user, use err.SafeError() instead.
*/
func (e *Error) Error() string {
	msg := fmt.Sprintf("%d: %s - %s", e.Status, e.Title, e.Detail)
	if e.Source.Pointer != "" {
		msg += fmt.Sprintf("(Source.Pointer: %s)", e.Source.Pointer)
	}

	if e.ISE != "" {
		msg += fmt.Sprintf("\nInternal Error: %s", e.ISE)
	}

	return msg
}

/*
Validate ensures that the an error meets all JSON API criteria.
*/
func (e *Error) Validate(r *http.Request, response bool) *Error {

	switch {
	case e.Status == 0:
		return ISE(fmt.Sprintf("No HTTP Status set for error %+v\n", e))
	case e.Status < 400 || e.Status > 600:
		return ISE(fmt.Sprintf("HTTP Status out of valid range for error %+v\n", e))
	case e.Status == 422 && e.Source.Pointer == "":
		return ISE(fmt.Sprintf("Source Pointer must be set for 422 Status error"))
	}

	return nil
}

/*
StatusCode (HTTP) for the error. Defaults to 0.
*/
func (e *Error) StatusCode() int {
	return e.Status
}

/*
ISE is a convenience function for creating a ready-to-go Internal Service Error
response. The message you pass in is set to the ErrorObject.ISE attribute so you
can gracefully log ISE's internally before sending them.
*/
func ISE(internalMessage string) *Error {
	return &Error{
		Title:  DefaultErrorTitle,
		Detail: DefaultErrorDetail,
		Status: http.StatusInternalServerError,
		ISE:    internalMessage,
	}
}

/*
InputError creates a properly formatted HTTP Status 422 error with an appropriate
user safe message. The parameter "attribute" will format err.Source.Pointer to be
"/data/attributes/<attribute>".
*/
func InputError(msg string, attribute string) *Error {
	err := &Error{
		Title:  "Invalid Attribute",
		Detail: msg,
		Status: 422,
	}

	// Assign this after the fact, easier to do
	err.Source.Pointer = fmt.Sprintf("/data/attributes/%s", strings.ToLower(attribute))

	return err
}

// SpecificationError is used whenever the Client violates the JSON API Spec
func SpecificationError(detail string) *Error {
	return &Error{
		Title:  "JSON API Specification Error",
		Detail: detail,
		Status: http.StatusNotAcceptable,
	}
}

// NotFound returns a 404 formatted error
func NotFound(resourceType string, id string) *Error {
	return &Error{
		Title:  "Not Found",
		Detail: fmt.Sprintf("No resource of type '%s' exists for ID: %s", resourceType, id),
		Status: http.StatusNotFound,
	}
}
<commit_msg>Fix typo<commit_after>package jsh

import (
	"fmt"
	"net/http"
	"strings"
)

/*
DefaultError can be customized in order to provide a more customized error
Detail message when an Internal Server Error occurs. Optionally, you can modify
a returned jsh.Error before sending it as a response as well.
*/
var DefaultErrorDetail = "Request failed, something went wrong."

// DefaultTitle can be customized to provide a more customized ISE Title
var DefaultErrorTitle = "Internal Server Error"

/*
ErrorType represents the common interface requirements that libraries may
specify if they would like to accept either a single error or a list.
*/
type ErrorType interface {
	// Error returns a formatted error and allows it to conform to the stdErr
	// interface.
	Error() string
	// Validate checks that the error is valid in the context of JSONAPI
	Validate(r *http.Request, response bool) *Error
	// StatusCode returns the first encountered HTTP Status Code for the error type.
	// Returns 0 if none is set.
	StatusCode() int
}

// ErrorList is wraps an Error Array so that it can implement Sendable
type ErrorList []*Error

// Validate checks all errors within the list to ensure that they are valid
func (e ErrorList) Validate(r *http.Request, response bool) *Error {
	for _, err := range e {
		validationErr := err.Validate(r, response)
		if validationErr != nil {
			return validationErr
		}
	}

	return nil
}

// Fulfills the default error interface
func (e ErrorList) Error() string {
	var msg string

	for _, err := range e {
		msg += fmt.Sprintf("%s\n", err.Error())
	}

	return msg
}

/*
StatusCode (HTTP) of the first error in the list. Defaults to 0 if the list is
empty or one has not yet been set for the first error.
*/
func (e ErrorList) StatusCode() int {
	if len(e) == 0 {
		return 0
	}

	return e[0].Status
}

/*
Error consists of a number of contextual attributes to make conveying
certain error type simpler as per the JSON API specification:
http://jsonapi.org/format/#error-objects

	error := &jsh.Error{
		Title: "Authentication Failure",
		Detail: "Category 4 Username Failure",
		Status: 401
	}

	jsh.Send(w, r, error)
*/
type Error struct {
	Title  string `json:"title"`
	Detail string `json:"detail"`
	Status int    `json:"status,string"`
	Source struct {
		Pointer string `json:"pointer"`
	} `json:"source"`
	ISE string `json:"-"`
}

/*
Error will print an internal server error if set, or default back to the SafeError()
format if not. As usual, err.Error() should not be considered safe for presentation
to the end user, use err.SafeError() instead.
*/
func (e *Error) Error() string {
	msg := fmt.Sprintf("%d: %s - %s", e.Status, e.Title, e.Detail)
	if e.Source.Pointer != "" {
		msg += fmt.Sprintf("(Source.Pointer: %s)", e.Source.Pointer)
	}

	if e.ISE != "" {
		msg += fmt.Sprintf("\nInternal Error: %s", e.ISE)
	}

	return msg
}

/*
Validate ensures that the error meets all JSON API criteria.
*/
func (e *Error) Validate(r *http.Request, response bool) *Error {

	switch {
	case e.Status == 0:
		return ISE(fmt.Sprintf("No HTTP Status set for error %+v\n", e))
	case e.Status < 400 || e.Status > 600:
		return ISE(fmt.Sprintf("HTTP Status out of valid range for error %+v\n", e))
	case e.Status == 422 && e.Source.Pointer == "":
		return ISE(fmt.Sprintf("Source Pointer must be set for 422 Status error"))
	}

	return nil
}

/*
StatusCode (HTTP) for the error. Defaults to 0.
*/
func (e *Error) StatusCode() int {
	return e.Status
}

/*
ISE is a convenience function for creating a ready-to-go Internal Service Error
response. The message you pass in is set to the ErrorObject.ISE attribute so you
can gracefully log ISE's internally before sending them.
*/
func ISE(internalMessage string) *Error {
	return &Error{
		Title:  DefaultErrorTitle,
		Detail: DefaultErrorDetail,
		Status: http.StatusInternalServerError,
		ISE:    internalMessage,
	}
}

/*
InputError creates a properly formatted HTTP Status 422 error with an appropriate
user safe message. The parameter "attribute" will format err.Source.Pointer to be
"/data/attributes/<attribute>".
*/
func InputError(msg string, attribute string) *Error {
	err := &Error{
		Title:  "Invalid Attribute",
		Detail: msg,
		Status: 422,
	}

	// Assign this after the fact, easier to do
	err.Source.Pointer = fmt.Sprintf("/data/attributes/%s", strings.ToLower(attribute))

	return err
}

// SpecificationError is used whenever the Client violates the JSON API Spec
func SpecificationError(detail string) *Error {
	return &Error{
		Title:  "JSON API Specification Error",
		Detail: detail,
		Status: http.StatusNotAcceptable,
	}
}

// NotFound returns a 404 formatted error
func NotFound(resourceType string, id string) *Error {
	return &Error{
		Title:  "Not Found",
		Detail: fmt.Sprintf("No resource of type '%s' exists for ID: %s", resourceType, id),
		Status: http.StatusNotFound,
	}
}
<|endoftext|>


<commit_before>package mapstructure

import (
	"fmt"
	"sort"
	"strings"
)

// Error implements the error interface and can represents multiple
// errors that occur in the course of a single decode.
type Error struct {
	Errors []string
}

func (e *Error) Error() string {
	points := make([]string, len(e.Errors))
	for i, err := range e.Errors {
		points[i] = fmt.Sprintf("* %s", err)
	}

	sort.Strings(points)
	return fmt.Sprintf(
		"%d error(s) decoding:\n\n%s",
		len(e.Errors), strings.Join(points, "\n"))
}

func appendErrors(errors []string, err error) []string {
	switch e := err.(type) {
	case *Error:
		return append(errors, e.Errors...)
	default:
		return append(errors, e.Error())
	}
}
<commit_msg>implement errwrap.Wrapper<commit_after>package mapstructure

import (
	"errors"
	"fmt"
	"sort"
	"strings"
)

// Error implements the error interface and can represents multiple
// errors that occur in the course of a single decode.
type Error struct {
	Errors []string
}

func (e *Error) Error() string {
	points := make([]string, len(e.Errors))
	for i, err := range e.Errors {
		points[i] = fmt.Sprintf("* %s", err)
	}

	sort.Strings(points)
	return fmt.Sprintf(
		"%d error(s) decoding:\n\n%s",
		len(e.Errors), strings.Join(points, "\n"))
}

// WrappedErrors implements the errwrap.Wrapper interface to make this
// return value more useful with the errwrap and go-multierror libraries.
func (e *Error) WrappedErrors() []error {
	if e == nil {
		return nil
	}

	result := make([]error, len(e.Errors))
	for i, e := range e.Errors {
		result[i] = errors.New(e)
	}

	return result
}

func appendErrors(errors []string, err error) []string {
	switch e := err.(type) {
	case *Error:
		return append(errors, e.Errors...)
	default:
		return append(errors, e.Error())
	}
}
<|endoftext|>


<commit_before>package goprocess

import (
	"sync"
)

// process implements Process
type process struct {
	children map[*processLink]struct{} // process to close with us
	waitfors map[*processLink]struct{} // process to only wait for
	waiters  []*processLink            // processes that wait for us. for gc.

	teardown TeardownFunc  // called to run the teardown logic.
	closing  chan struct{} // closed once close starts.
	closed   chan struct{} // closed once close is done.
	closeErr error         // error to return to clients of Close()

	sync.Mutex
}

// newProcess constructs and returns a Process.
// It will call tf TeardownFunc exactly once:
//  **after** all children have fully Closed,
//  **after** entering <-Closing(), and
//  **before** <-Closed().
func newProcess(tf TeardownFunc) *process {
	return &process{
		teardown: tf,
		closed:   make(chan struct{}),
		closing:  make(chan struct{}),
		waitfors: make(map[*processLink]struct{}),
		children: make(map[*processLink]struct{}),
	}
}

func (p *process) WaitFor(q Process) {
	if q == nil {
		panic("waiting for nil process")
	}

	p.Lock()
	defer p.Unlock()

	select {
	case <-p.Closed():
		panic("Process cannot wait after being closed")
	default:
	}

	pl := newProcessLink(p, q)
	if p.waitfors == nil {
		// This may be nil when we're closing. In close, we'll keep
		// reading this map till it stays nil.
		p.waitfors = make(map[*processLink]struct{}, 1)
	}
	p.waitfors[pl] = struct{}{}
	go pl.AddToChild()
}

func (p *process) AddChildNoWait(child Process) {
	if child == nil {
		panic("adding nil child process")
	}

	p.Lock()
	defer p.Unlock()

	select {
	case <-p.Closing():
		// Either closed or closing, close child immediately. This is
		// correct because we aren't asked to _wait_ on this child.
		go child.Close()
		// Wait for the child to start closing so the child is in the
		// "correct" state after this function finishes (see #17).
		<-child.Closing()
		return
	default:
	}

	pl := newProcessLink(p, child)
	p.children[pl] = struct{}{}
	go pl.AddToChild()
}

func (p *process) AddChild(child Process) {
	if child == nil {
		panic("adding nil child process")
	}

	p.Lock()
	defer p.Unlock()

	pl := newProcessLink(p, child)

	select {
	case <-p.Closed():
		// AddChild must not be called on a dead process. Maybe that's
		// too strict?
		panic("Process cannot add children after being closed")
	default:
	}

	select {
	case <-p.Closing():
		// Already closing, close child in background.
		go child.Close()
		// Wait for the child to start closing so the child is in the
		// "correct" state after this function finishes (see #17).
		<-child.Closing()
	default:
		// Only add the child when not closing. When closing, just add
		// it to the "waitfors" list.
		p.children[pl] = struct{}{}
	}

	if p.waitfors == nil {
		// This may be be nil when we're closing. In close, we'll keep
		// reading this map till it stays nil.
		p.waitfors = make(map[*processLink]struct{}, 1)
	}
	p.waitfors[pl] = struct{}{}
	go pl.AddToChild()
}

func (p *process) Go(f ProcessFunc) Process {
	child := newProcess(nil)
	waitFor := newProcess(nil)
	child.WaitFor(waitFor) // prevent child from closing

	// add child last, to prevent a closing parent from
	// closing all of them prematurely, before running the func.
	p.AddChild(child)
	go func() {
		f(child)
		waitFor.Close()            // allow child to close.
		child.CloseAfterChildren() // close to tear down.
	}()
	return child
}

// SetTeardown to assign a teardown function
func (p *process) SetTeardown(tf TeardownFunc) {
	if tf == nil {
		panic("cannot set nil TeardownFunc")
	}

	p.Lock()
	if p.teardown != nil {
		panic("cannot SetTeardown twice")
	}

	p.teardown = tf
	select {
	case <-p.Closed():
		p.closeErr = tf()
	default:
	}
	p.Unlock()
}

// Close is the external close function.
// it's a wrapper around internalClose that waits on Closed()
func (p *process) Close() error {
	p.Lock()

	// if already closing, or closed, get out. (but wait!)
	select {
	case <-p.Closing():
		p.Unlock()
		<-p.Closed()
		return p.closeErr
	default:
	}

	p.doClose()
	p.Unlock()
	return p.closeErr
}

func (p *process) Closing() <-chan struct{} {
	return p.closing
}

func (p *process) Closed() <-chan struct{} {
	return p.closed
}

func (p *process) Err() error {
	<-p.Closed()
	return p.closeErr
}

// the _actual_ close process.
func (p *process) doClose() {
	// this function is only be called once (protected by p.Lock()).
	// and it will panic (on closing channels) otherwise.

	close(p.closing) // signal that we're shutting down (Closing)

	// We won't add any children after we start closing so we can do this
	// once.
	for plc, _ := range p.children {
		child := plc.Child()
		if child != nil { // check because child may already have been removed.
			go child.Close() // force all children to shut down
		}

		// safe to call multiple times per link
		plc.ParentClear()
	}
	p.children = nil // clear them. release memory.

	// We may repeatedly continue to add waiters while we wait to close so
	// we have to do this in a loop.
	for len(p.waitfors) > 0 {
		// we must be careful not to iterate over waitfors directly, as it may
		// change under our feet.
		wf := p.waitfors
		p.waitfors = nil // clear them. release memory.
		for w, _ := range wf {
			// Here, we wait UNLOCKED, so that waitfors who are in the middle of
			// adding a child to us can finish. we will immediately close the child.
			p.Unlock()
			<-w.ChildClosed() // wait till all waitfors are fully closed (before teardown)
			p.Lock()

			// safe to call multiple times per link
			w.ParentClear()
		}
	}

	if p.teardown != nil {
		p.closeErr = p.teardown() // actually run the close logic (ok safe to teardown)
	}
	close(p.closed) // signal that we're shut down (Closed)

	// go remove all the parents from the process links. optimization.
	go func(waiters []*processLink) {
		for _, pl := range waiters {
			pl.ClearChild()
			pr, ok := pl.Parent().(*process)
			if !ok {
				// parent has already been called to close
				continue
			}
			pr.Lock()
			delete(pr.waitfors, pl)
			delete(pr.children, pl)
			pr.Unlock()
		}
	}(p.waiters) // pass in so
	p.waiters = nil // clear them. release memory.
}

// We will only wait on the children we have now.
// We will not wait on children added subsequently.
// this may change in the future.
func (p *process) CloseAfterChildren() error {
	p.Lock()
	select {
	case <-p.Closed():
		p.Unlock()
		return p.Close() // get error. safe, after p.Closed()
	default:
	}
	p.Unlock()

	// here only from one goroutine.

	nextToWaitFor := func() Process {
		p.Lock()
		defer p.Unlock()
		for e, _ := range p.waitfors {
			c := e.Child()
			if c == nil {
				continue
			}

			select {
			case <-c.Closed():
			default:
				return c
			}
		}
		return nil
	}

	// wait for all processes we're waiting for are closed.
	// the semantics here are simple: we will _only_ close
	// if there are no processes currently waiting for.
	for next := nextToWaitFor(); next != nil; next = nextToWaitFor() {
		<-next.Closed()
	}

	// YAY! we're done. close
	return p.Close()
}
<commit_msg>fix: don't set the close error after closing<commit_after>package goprocess

import (
	"sync"
)

// process implements Process
type process struct {
	children map[*processLink]struct{} // process to close with us
	waitfors map[*processLink]struct{} // process to only wait for
	waiters  []*processLink            // processes that wait for us. for gc.

	teardown TeardownFunc  // called to run the teardown logic.
	closing  chan struct{} // closed once close starts.
	closed   chan struct{} // closed once close is done.
	closeErr error         // error to return to clients of Close()

	sync.Mutex
}

// newProcess constructs and returns a Process.
// It will call tf TeardownFunc exactly once:
//  **after** all children have fully Closed,
//  **after** entering <-Closing(), and
//  **before** <-Closed().
func newProcess(tf TeardownFunc) *process {
	return &process{
		teardown: tf,
		closed:   make(chan struct{}),
		closing:  make(chan struct{}),
		waitfors: make(map[*processLink]struct{}),
		children: make(map[*processLink]struct{}),
	}
}

func (p *process) WaitFor(q Process) {
	if q == nil {
		panic("waiting for nil process")
	}

	p.Lock()
	defer p.Unlock()

	select {
	case <-p.Closed():
		panic("Process cannot wait after being closed")
	default:
	}

	pl := newProcessLink(p, q)
	if p.waitfors == nil {
		// This may be nil when we're closing. In close, we'll keep
		// reading this map till it stays nil.
		p.waitfors = make(map[*processLink]struct{}, 1)
	}
	p.waitfors[pl] = struct{}{}
	go pl.AddToChild()
}

func (p *process) AddChildNoWait(child Process) {
	if child == nil {
		panic("adding nil child process")
	}

	p.Lock()
	defer p.Unlock()

	select {
	case <-p.Closing():
		// Either closed or closing, close child immediately. This is
		// correct because we aren't asked to _wait_ on this child.
		go child.Close()
		// Wait for the child to start closing so the child is in the
		// "correct" state after this function finishes (see #17).
		<-child.Closing()
		return
	default:
	}

	pl := newProcessLink(p, child)
	p.children[pl] = struct{}{}
	go pl.AddToChild()
}

func (p *process) AddChild(child Process) {
	if child == nil {
		panic("adding nil child process")
	}

	p.Lock()
	defer p.Unlock()

	pl := newProcessLink(p, child)

	select {
	case <-p.Closed():
		// AddChild must not be called on a dead process. Maybe that's
		// too strict?
		panic("Process cannot add children after being closed")
	default:
	}

	select {
	case <-p.Closing():
		// Already closing, close child in background.
		go child.Close()
		// Wait for the child to start closing so the child is in the
		// "correct" state after this function finishes (see #17).
		<-child.Closing()
	default:
		// Only add the child when not closing. When closing, just add
		// it to the "waitfors" list.
		p.children[pl] = struct{}{}
	}

	if p.waitfors == nil {
		// This may be be nil when we're closing. In close, we'll keep
		// reading this map till it stays nil.
		p.waitfors = make(map[*processLink]struct{}, 1)
	}
	p.waitfors[pl] = struct{}{}
	go pl.AddToChild()
}

func (p *process) Go(f ProcessFunc) Process {
	child := newProcess(nil)
	waitFor := newProcess(nil)
	child.WaitFor(waitFor) // prevent child from closing

	// add child last, to prevent a closing parent from
	// closing all of them prematurely, before running the func.
	p.AddChild(child)
	go func() {
		f(child)
		waitFor.Close()            // allow child to close.
		child.CloseAfterChildren() // close to tear down.
	}()
	return child
}

// SetTeardown to assign a teardown function
func (p *process) SetTeardown(tf TeardownFunc) {
	if tf == nil {
		panic("cannot set nil TeardownFunc")
	}

	p.Lock()
	if p.teardown != nil {
		panic("cannot SetTeardown twice")
	}

	p.teardown = tf
	select {
	case <-p.Closed():
		// Call the teardown function, but don't set the error. We can't
		// change that after we shut down.
		tf()
	default:
	}
	p.Unlock()
}

// Close is the external close function.
// it's a wrapper around internalClose that waits on Closed()
func (p *process) Close() error {
	p.Lock()

	// if already closing, or closed, get out. (but wait!)
	select {
	case <-p.Closing():
		p.Unlock()
		<-p.Closed()
		return p.closeErr
	default:
	}

	p.doClose()
	p.Unlock()
	return p.closeErr
}

func (p *process) Closing() <-chan struct{} {
	return p.closing
}

func (p *process) Closed() <-chan struct{} {
	return p.closed
}

func (p *process) Err() error {
	<-p.Closed()
	return p.closeErr
}

// the _actual_ close process.
func (p *process) doClose() {
	// this function is only be called once (protected by p.Lock()).
	// and it will panic (on closing channels) otherwise.

	close(p.closing) // signal that we're shutting down (Closing)

	// We won't add any children after we start closing so we can do this
	// once.
	for plc, _ := range p.children {
		child := plc.Child()
		if child != nil { // check because child may already have been removed.
			go child.Close() // force all children to shut down
		}

		// safe to call multiple times per link
		plc.ParentClear()
	}
	p.children = nil // clear them. release memory.

	// We may repeatedly continue to add waiters while we wait to close so
	// we have to do this in a loop.
	for len(p.waitfors) > 0 {
		// we must be careful not to iterate over waitfors directly, as it may
		// change under our feet.
		wf := p.waitfors
		p.waitfors = nil // clear them. release memory.
		for w, _ := range wf {
			// Here, we wait UNLOCKED, so that waitfors who are in the middle of
			// adding a child to us can finish. we will immediately close the child.
			p.Unlock()
			<-w.ChildClosed() // wait till all waitfors are fully closed (before teardown)
			p.Lock()

			// safe to call multiple times per link
			w.ParentClear()
		}
	}

	if p.teardown != nil {
		p.closeErr = p.teardown() // actually run the close logic (ok safe to teardown)
	}
	close(p.closed) // signal that we're shut down (Closed)

	// go remove all the parents from the process links. optimization.
	go func(waiters []*processLink) {
		for _, pl := range waiters {
			pl.ClearChild()
			pr, ok := pl.Parent().(*process)
			if !ok {
				// parent has already been called to close
				continue
			}
			pr.Lock()
			delete(pr.waitfors, pl)
			delete(pr.children, pl)
			pr.Unlock()
		}
	}(p.waiters) // pass in so
	p.waiters = nil // clear them. release memory.
}

// We will only wait on the children we have now.
// We will not wait on children added subsequently.
// this may change in the future.
func (p *process) CloseAfterChildren() error {
	p.Lock()
	select {
	case <-p.Closed():
		p.Unlock()
		return p.Close() // get error. safe, after p.Closed()
	default:
	}
	p.Unlock()

	// here only from one goroutine.

	nextToWaitFor := func() Process {
		p.Lock()
		defer p.Unlock()
		for e, _ := range p.waitfors {
			c := e.Child()
			if c == nil {
				continue
			}

			select {
			case <-c.Closed():
			default:
				return c
			}
		}
		return nil
	}

	// wait for all processes we're waiting for are closed.
	// the semantics here are simple: we will _only_ close
	// if there are no processes currently waiting for.
	for next := nextToWaitFor(); next != nil; next = nextToWaitFor() {
		<-next.Closed()
	}

	// YAY! we're done. close
	return p.Close()
}
<|endoftext|>


<commit_before>package app

import (
	"github.com/murlokswarm/app/key"
)

// MouseEvent represents data fired when interacting with a pointing device
// (such as a mouse).
type MouseEvent struct {
	ClientX  float64
	ClientY  float64
	PageX    float64
	PageY    float64
	ScreenX  float64
	ScreenY  float64
	Button   int
	Detail   int
	AltKey   bool
	CtrlKey  bool
	MetaKey  bool
	ShiftKey bool
}

// WheelEvent represents data fired when a wheel button of a pointing device
// (usually a mouse) is rotated.
type WheelEvent struct {
	DeltaX    float64
	DeltaY    float64
	DeltaZ    float64
	DeltaMode DeltaMode
}

// DeltaMode is an indication of the units of measurement for a delta value.
type DeltaMode uint64

// KeyboardEvent represents data fired when the keyboard is used.
type KeyboardEvent struct {
	CharCode rune
	KeyCode  key.Code
	Location key.Location
	AltKey   bool
	CtrlKey  bool
	MetaKey  bool
	ShiftKey bool
}
<commit_msg>Add InnerText to MouseEvent and KeyEvent<commit_after>package app

import (
	"github.com/murlokswarm/app/key"
)

// MouseEvent represents data fired when interacting with a pointing device
// (such as a mouse).
type MouseEvent struct {
	ClientX   float64
	ClientY   float64
	PageX     float64
	PageY     float64
	ScreenX   float64
	ScreenY   float64
	Button    int
	Detail    int
	AltKey    bool
	CtrlKey   bool
	MetaKey   bool
	ShiftKey  bool
	InnerText string
}

// WheelEvent represents data fired when a wheel button of a pointing device
// (usually a mouse) is rotated.
type WheelEvent struct {
	DeltaX    float64
	DeltaY    float64
	DeltaZ    float64
	DeltaMode DeltaMode
}

// DeltaMode is an indication of the units of measurement for a delta value.
type DeltaMode uint64

// KeyboardEvent represents data fired when the keyboard is used.
type KeyboardEvent struct {
	CharCode  rune
	KeyCode   key.Code
	Location  key.Location
	AltKey    bool
	CtrlKey   bool
	MetaKey   bool
	ShiftKey  bool
	InnerText string
}
<|endoftext|>


<commit_before>package alerting

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/services/ngalert/models"
	"github.com/grafana/grafana/pkg/services/provisioning/values"
)

type RuleDelete struct {
	UID   string
	OrgID int64
}

type RuleDeleteV1 struct {
	UID   values.StringValue `json:"uid" yaml:"uid"`
	OrgID values.Int64Value  `json:"orgId" yaml:"orgId"`
}

type AlertRuleGroupV1 struct {
	OrgID    values.Int64Value  `json:"orgId" yaml:"orgId"`
	Name     values.StringValue `json:"name" yaml:"name"`
	Folder   values.StringValue `json:"folder" yaml:"folder"`
	Interval values.StringValue `json:"interval" yaml:"interval"`
	Rules    []AlertRuleV1      `json:"rules" yaml:"rules"`
}

func (ruleGroupV1 *AlertRuleGroupV1) MapToModel() (AlertRuleGroup, error) {
	ruleGroup := AlertRuleGroup{}
	ruleGroup.Name = ruleGroupV1.Name.Value()
	if strings.TrimSpace(ruleGroup.Name) == "" {
		return AlertRuleGroup{}, errors.New("rule group has no name set")
	}
	ruleGroup.OrgID = ruleGroupV1.OrgID.Value()
	if ruleGroup.OrgID < 1 {
		ruleGroup.OrgID = 1
	}
	interval, err := time.ParseDuration(ruleGroupV1.Interval.Value())
	if err != nil {
		return AlertRuleGroup{}, err
	}
	ruleGroup.Interval = interval
	ruleGroup.Folder = ruleGroupV1.Folder.Value()
	if strings.TrimSpace(ruleGroup.Folder) == "" {
		return AlertRuleGroup{}, errors.New("rule group has no folder set")
	}
	for _, ruleV1 := range ruleGroupV1.Rules {
		rule, err := ruleV1.mapToModel(ruleGroup.OrgID)
		if err != nil {
			return AlertRuleGroup{}, err
		}
		ruleGroup.Rules = append(ruleGroup.Rules, rule)
	}
	return ruleGroup, nil
}

type AlertRuleGroup struct {
	OrgID    int64
	Name     string
	Folder   string
	Interval time.Duration
	Rules    []models.AlertRule
}

type AlertRuleV1 struct {
	UID          values.StringValue    `json:"uid" yaml:"uid"`
	Title        values.StringValue    `json:"title" yaml:"title"`
	Condition    values.StringValue    `json:"condition" yaml:"condition"`
	Data         []QueryV1             `json:"data" yaml:"data"`
	DashboardUID values.StringValue    `json:"dasboardUid" yaml:"dashboardUid"`
	PanelID      values.Int64Value     `json:"panelId" yaml:"panelId"`
	NoDataState  values.StringValue    `json:"noDataState" yaml:"noDataState"`
	ExecErrState values.StringValue    `json:"execErrState" yaml:"execErrState"`
	For          values.StringValue    `json:"for" yaml:"for"`
	Annotations  values.StringMapValue `json:"annotations" yaml:"annotations"`
	Labels       values.StringMapValue `json:"labels" yaml:"labels"`
}

func (rule *AlertRuleV1) mapToModel(orgID int64) (models.AlertRule, error) {
	alertRule := models.AlertRule{}
	alertRule.Title = rule.Title.Value()
	if alertRule.Title == "" {
		return models.AlertRule{}, fmt.Errorf("rule has no title set")
	}
	alertRule.UID = rule.UID.Value()
	if alertRule.UID == "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: no UID set", alertRule.Title)
	}
	alertRule.OrgID = orgID
	duration, err := time.ParseDuration(rule.For.Value())
	if err != nil {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
	}
	alertRule.For = duration
	dashboardUID := rule.DashboardUID.Value()
	alertRule.DashboardUID = &dashboardUID
	panelID := rule.PanelID.Value()
	alertRule.PanelID = &panelID
	execErrStateValue := strings.TrimSpace(rule.ExecErrState.Value())
	execErrState, err := models.ErrStateFromString(execErrStateValue)
	if err != nil && execErrStateValue != "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
	}
	if execErrStateValue == "" {
		execErrState = models.AlertingErrState
	}
	alertRule.ExecErrState = execErrState
	noDataStateValue := strings.TrimSpace(rule.NoDataState.Value())
	noDataState, err := models.NoDataStateFromString(noDataStateValue)
	if err != nil && noDataStateValue != "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
	}
	if noDataStateValue == "" {
		noDataState = models.NoData
	}
	alertRule.NoDataState = noDataState
	alertRule.Condition = rule.Condition.Value()
	if alertRule.Condition == "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: no condition set", alertRule.Title)
	}
	alertRule.Annotations = rule.Annotations.Value()
	alertRule.Labels = rule.Labels.Value()
	for _, queryV1 := range rule.Data {
		query, err := queryV1.mapToModel()
		if err != nil {
			return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
		}
		alertRule.Data = append(alertRule.Data, query)
	}
	if len(alertRule.Data) == 0 {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: no data set", alertRule.Title)
	}
	return alertRule, nil
}

type QueryV1 struct {
	RefID             values.StringValue       `json:"refId" yaml:"refId"`
	QueryType         values.StringValue       `json:"queryType" yaml:"queryType"`
	RelativeTimeRange models.RelativeTimeRange `json:"relativeTimeRange" yaml:"relativeTimeRange"`
	DatasourceUID     values.StringValue       `json:"datasourceUid" yaml:"datasourceUid"`
	Model             values.JSONValue         `json:"model" yaml:"model"`
}

func (queryV1 *QueryV1) mapToModel() (models.AlertQuery, error) {
	// In order to get the model into the format we need,
	// we marshal it back to json and unmarshal it again
	// in json.RawMessage. We do this as we cannot use
	// json.RawMessage with a yaml files and have to use
	// JSONValue that supports both, json and yaml.
	encoded, err := json.Marshal(queryV1.Model.Value())
	if err != nil {
		return models.AlertQuery{}, err
	}
	var rawMessage json.RawMessage
	err = json.Unmarshal(encoded, &rawMessage)
	if err != nil {
		return models.AlertQuery{}, err
	}
	return models.AlertQuery{
		RefID:             queryV1.RefID.Value(),
		QueryType:         queryV1.QueryType.Value(),
		DatasourceUID:     queryV1.DatasourceUID.Value(),
		RelativeTimeRange: queryV1.RelativeTimeRange,
		Model:             rawMessage,
	}, nil
}
<commit_msg>Alerting: use raw query data in provisioning to bypass interpolation of macros (#54293)<commit_after>package alerting

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/grafana/grafana/pkg/services/ngalert/models"
	"github.com/grafana/grafana/pkg/services/provisioning/values"
)

type RuleDelete struct {
	UID   string
	OrgID int64
}

type RuleDeleteV1 struct {
	UID   values.StringValue `json:"uid" yaml:"uid"`
	OrgID values.Int64Value  `json:"orgId" yaml:"orgId"`
}

type AlertRuleGroupV1 struct {
	OrgID    values.Int64Value  `json:"orgId" yaml:"orgId"`
	Name     values.StringValue `json:"name" yaml:"name"`
	Folder   values.StringValue `json:"folder" yaml:"folder"`
	Interval values.StringValue `json:"interval" yaml:"interval"`
	Rules    []AlertRuleV1      `json:"rules" yaml:"rules"`
}

func (ruleGroupV1 *AlertRuleGroupV1) MapToModel() (AlertRuleGroup, error) {
	ruleGroup := AlertRuleGroup{}
	ruleGroup.Name = ruleGroupV1.Name.Value()
	if strings.TrimSpace(ruleGroup.Name) == "" {
		return AlertRuleGroup{}, errors.New("rule group has no name set")
	}
	ruleGroup.OrgID = ruleGroupV1.OrgID.Value()
	if ruleGroup.OrgID < 1 {
		ruleGroup.OrgID = 1
	}
	interval, err := time.ParseDuration(ruleGroupV1.Interval.Value())
	if err != nil {
		return AlertRuleGroup{}, err
	}
	ruleGroup.Interval = interval
	ruleGroup.Folder = ruleGroupV1.Folder.Value()
	if strings.TrimSpace(ruleGroup.Folder) == "" {
		return AlertRuleGroup{}, errors.New("rule group has no folder set")
	}
	for _, ruleV1 := range ruleGroupV1.Rules {
		rule, err := ruleV1.mapToModel(ruleGroup.OrgID)
		if err != nil {
			return AlertRuleGroup{}, err
		}
		ruleGroup.Rules = append(ruleGroup.Rules, rule)
	}
	return ruleGroup, nil
}

type AlertRuleGroup struct {
	OrgID    int64
	Name     string
	Folder   string
	Interval time.Duration
	Rules    []models.AlertRule
}

type AlertRuleV1 struct {
	UID          values.StringValue    `json:"uid" yaml:"uid"`
	Title        values.StringValue    `json:"title" yaml:"title"`
	Condition    values.StringValue    `json:"condition" yaml:"condition"`
	Data         []QueryV1             `json:"data" yaml:"data"`
	DashboardUID values.StringValue    `json:"dasboardUid" yaml:"dashboardUid"`
	PanelID      values.Int64Value     `json:"panelId" yaml:"panelId"`
	NoDataState  values.StringValue    `json:"noDataState" yaml:"noDataState"`
	ExecErrState values.StringValue    `json:"execErrState" yaml:"execErrState"`
	For          values.StringValue    `json:"for" yaml:"for"`
	Annotations  values.StringMapValue `json:"annotations" yaml:"annotations"`
	Labels       values.StringMapValue `json:"labels" yaml:"labels"`
}

func (rule *AlertRuleV1) mapToModel(orgID int64) (models.AlertRule, error) {
	alertRule := models.AlertRule{}
	alertRule.Title = rule.Title.Value()
	if alertRule.Title == "" {
		return models.AlertRule{}, fmt.Errorf("rule has no title set")
	}
	alertRule.UID = rule.UID.Value()
	if alertRule.UID == "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: no UID set", alertRule.Title)
	}
	alertRule.OrgID = orgID
	duration, err := time.ParseDuration(rule.For.Value())
	if err != nil {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
	}
	alertRule.For = duration
	dashboardUID := rule.DashboardUID.Value()
	alertRule.DashboardUID = &dashboardUID
	panelID := rule.PanelID.Value()
	alertRule.PanelID = &panelID
	execErrStateValue := strings.TrimSpace(rule.ExecErrState.Value())
	execErrState, err := models.ErrStateFromString(execErrStateValue)
	if err != nil && execErrStateValue != "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
	}
	if execErrStateValue == "" {
		execErrState = models.AlertingErrState
	}
	alertRule.ExecErrState = execErrState
	noDataStateValue := strings.TrimSpace(rule.NoDataState.Value())
	noDataState, err := models.NoDataStateFromString(noDataStateValue)
	if err != nil && noDataStateValue != "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
	}
	if noDataStateValue == "" {
		noDataState = models.NoData
	}
	alertRule.NoDataState = noDataState
	alertRule.Condition = rule.Condition.Value()
	if alertRule.Condition == "" {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: no condition set", alertRule.Title)
	}
	alertRule.Annotations = rule.Annotations.Value()
	alertRule.Labels = rule.Labels.Value()
	for _, queryV1 := range rule.Data {
		query, err := queryV1.mapToModel()
		if err != nil {
			return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: %w", alertRule.Title, err)
		}
		alertRule.Data = append(alertRule.Data, query)
	}
	if len(alertRule.Data) == 0 {
		return models.AlertRule{}, fmt.Errorf("rule '%s' failed to parse: no data set", alertRule.Title)
	}
	return alertRule, nil
}

type QueryV1 struct {
	RefID             values.StringValue       `json:"refId" yaml:"refId"`
	QueryType         values.StringValue       `json:"queryType" yaml:"queryType"`
	RelativeTimeRange models.RelativeTimeRange `json:"relativeTimeRange" yaml:"relativeTimeRange"`
	DatasourceUID     values.StringValue       `json:"datasourceUid" yaml:"datasourceUid"`
	Model             values.JSONValue         `json:"model" yaml:"model"`
}

func (queryV1 *QueryV1) mapToModel() (models.AlertQuery, error) {
	// In order to get the model into the format we need,
	// we marshal it back to json and unmarshal it again
	// in json.RawMessage. We do this as we cannot use
	// json.RawMessage with a yaml files and have to use
	// JSONValue that supports both, json and yaml.
	//
	// We have to use the Raw field here, as Value would
	// try to interpolate macros like `$__timeFilter`, resulting
	// in missing macros in the SQL queries as they would be
	// replaced by an empty string.
	encoded, err := json.Marshal(queryV1.Model.Raw)
	if err != nil {
		return models.AlertQuery{}, err
	}
	var rawMessage json.RawMessage
	err = json.Unmarshal(encoded, &rawMessage)
	if err != nil {
		return models.AlertQuery{}, err
	}
	return models.AlertQuery{
		RefID:             queryV1.RefID.Value(),
		QueryType:         queryV1.QueryType.Value(),
		DatasourceUID:     queryV1.DatasourceUID.Value(),
		RelativeTimeRange: queryV1.RelativeTimeRange,
		Model:             rawMessage,
	}, nil
}
<|endoftext|>


<commit_before>package golatch

import (
	"fmt"
	"net/url"
	t "time"
)

type Latch struct {
	AppID     string
	SecretKey string
	LatchAPI
}

//Constructs a new Latch struct
func NewLatch(appID string, secretKey string) *Latch {
	return &Latch{
		AppID:     appID,
		SecretKey: secretKey,
	}
}

//Pairs an account with the provided pairing token
func (l *Latch) Pair(token string) (response *LatchPairResponse, err error) {
	var resp *LatchResponse
	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_PAIR_ACTION, "/", token)), nil, nil, t.Now()), &LatchPairResponse{}); err == nil {
		response = (*resp).(*LatchPairResponse)
	}
	return response, err
}

//Unpairs an account, given it's account ID
func (l *Latch) Unpair(accountId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_UNPAIR_ACTION, "/", accountId)), nil, nil, t.Now()), nil)
	return err
}

//Locks an account, given it's account ID
func (l *Latch) Lock(accountId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_LOCK_ACTION, "/", accountId)), nil, nil, t.Now()), nil)
	return err
}

//Unlocks an account, given it's account ID
func (l *Latch) Unlock(accountId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_UNLOCK_ACTION, "/", accountId)), nil, nil, t.Now()), nil)
	return err
}

//Locks an operation, given it's account ID and oeration ID
func (l *Latch) LockOperation(accountId string, operationId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_LOCK_ACTION, "/", accountId, "/op/", operationId)), nil, nil, t.Now()), nil)
	return err
}

//Unlocks an operation, given it's account ID and oeration ID
func (l *Latch) UnlockOperation(accountId string, operationId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_UNLOCK_ACTION, "/", accountId, "/op/", operationId)), nil, nil, t.Now()), nil)
	return err
}

//Adds a new operation
func (l *Latch) AddOperation(parentId string, name string, twoFactor string, lockOnRequest string) (response *LatchAddOperationResponse, err error) {
	var resp *LatchResponse

	params := url.Values{}
	params.Set("parentId", parentId)
	params.Set("name", name)
	params.Set("two_factor", twoFactor)
	params.Set("lock_on_request", lockOnRequest)

	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_PUT, GetLatchURL(API_OPERATION_ACTION), nil, params, t.Now()), &LatchAddOperationResponse{}); err == nil {
		response = (*resp).(*LatchAddOperationResponse)
	}
	return response, err
}

//Updates an existing operation
func (l *Latch) UpdateOperation(operationId string, name string, twoFactor string, lockOnRequest string) (err error) {
	params := url.Values{}
	params.Set("name", name)
	if twoFactor != NOT_SET {
		params.Set("two_factor", twoFactor)
	}
	if lockOnRequest != NOT_SET {
		params.Set("lock_on_request", lockOnRequest)
	}

	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_POST, GetLatchURL(fmt.Sprint(API_OPERATION_ACTION, "/", operationId)), nil, params, t.Now()), nil)
	return err
}

//Deletes an existing operation
func (l *Latch) DeleteOperation(operationId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_DELETE, GetLatchURL(fmt.Sprint(API_OPERATION_ACTION, "/", operationId)), nil, nil, t.Now()), nil)
	return err
}

//Shows operations information
//If operationId is empty this function will retrieve all the operations of the app
func (l *Latch) ShowOperation(operationId string) (response *LatchShowOperationResponse, err error) {
	var resp *LatchResponse
	var operation string

	if operationId != "" {
		operation += "/" + operationId
	}

	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_OPERATION_ACTION, operation)), nil, nil, t.Now()), &LatchShowOperationResponse{}); err == nil {
		response = (*resp).(*LatchShowOperationResponse)
	}
	return response, err
}

//Gets the status of an account, given it's account ID
//If nootp is true, the one time password won't be included in the response
//If silent is true Latch will not send push notifications to the client (requires SILVER, GOLD or PLATINUM subscription)
func (l *Latch) Status(accountId string, nootp bool, silent bool) (response *LatchStatusResponse, err error) {
	query := fmt.Sprint(API_CHECK_STATUS_ACTION, "/", accountId)
	if nootp {
		query = fmt.Sprint(query, API_NOOTP_SUFFIX)
	}
	if silent {
		query = fmt.Sprint(query, API_SILENT_SUFFIX)
	}

	return l.StatusRequest(query)
}

//Gets the status of an operation, given it's account ID and operation ID
//If nootp is true, the one time password won't be included in the response
//If silent is true Latch will not send push notifications to the client (requires SILVER, GOLD or PLATINUM subscription)
func (l *Latch) OperationStatus(accountId string, operationId string, nootp bool, silent bool) (response *LatchStatusResponse, err error) {
	query := fmt.Sprint(API_CHECK_STATUS_ACTION, "/", accountId, "/op/", operationId)
	if nootp {
		query = fmt.Sprint(query, API_NOOTP_SUFFIX)
	}
	if silent {
		query = fmt.Sprint(query, API_SILENT_SUFFIX)
	}

	return l.StatusRequest(query)
}

//Performs a status request (application or operation) against the query URL provided
//Returns a LatchStatusResponse struct on success
func (l *Latch) StatusRequest(query string) (response *LatchStatusResponse, err error) {
	var resp *LatchResponse
	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(query), nil, nil, t.Now()), &LatchStatusResponse{}); err == nil {
		response = (*resp).(*LatchStatusResponse)
	}
	return response, err
}

//Gets the account's history between the from and to dates
func (l *Latch) History(accountId string, from t.Time, to t.Time) (response *LatchHistoryResponse, err error) {
	var resp *LatchResponse

	query := fmt.Sprintf("%s/%s", API_HISTORY_ACTION, accountId)
	if !from.IsZero() || !to.IsZero() {
		if !from.IsZero() {
			query = fmt.Sprint(query, fmt.Sprintf("/%d", from.UnixNano()/1000000))
		} else {
			query = fmt.Sprint(query, fmt.Sprintf("/%d", 0))
		}
	}
	if !to.IsZero() {
		query = fmt.Sprint(query, fmt.Sprintf("/%d", to.UnixNano()/1000000))
	}
	fmt.Println(query)
	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(query), nil, nil, t.Now()), &LatchHistoryResponse{AppID: l.AppID}); err == nil {
		response = (*resp).(*LatchHistoryResponse)
	}
	return response, err
}
<commit_msg>Removed unneeded Println.<commit_after>package golatch

import (
	"fmt"
	"net/url"
	t "time"
)

type Latch struct {
	AppID     string
	SecretKey string
	LatchAPI
}

//Constructs a new Latch struct
func NewLatch(appID string, secretKey string) *Latch {
	return &Latch{
		AppID:     appID,
		SecretKey: secretKey,
	}
}

//Pairs an account with the provided pairing token
func (l *Latch) Pair(token string) (response *LatchPairResponse, err error) {
	var resp *LatchResponse
	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_PAIR_ACTION, "/", token)), nil, nil, t.Now()), &LatchPairResponse{}); err == nil {
		response = (*resp).(*LatchPairResponse)
	}
	return response, err
}

//Unpairs an account, given it's account ID
func (l *Latch) Unpair(accountId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_UNPAIR_ACTION, "/", accountId)), nil, nil, t.Now()), nil)
	return err
}

//Locks an account, given it's account ID
func (l *Latch) Lock(accountId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_LOCK_ACTION, "/", accountId)), nil, nil, t.Now()), nil)
	return err
}

//Unlocks an account, given it's account ID
func (l *Latch) Unlock(accountId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_UNLOCK_ACTION, "/", accountId)), nil, nil, t.Now()), nil)
	return err
}

//Locks an operation, given it's account ID and oeration ID
func (l *Latch) LockOperation(accountId string, operationId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_LOCK_ACTION, "/", accountId, "/op/", operationId)), nil, nil, t.Now()), nil)
	return err
}

//Unlocks an operation, given it's account ID and oeration ID
func (l *Latch) UnlockOperation(accountId string, operationId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_UNLOCK_ACTION, "/", accountId, "/op/", operationId)), nil, nil, t.Now()), nil)
	return err
}

//Adds a new operation
func (l *Latch) AddOperation(parentId string, name string, twoFactor string, lockOnRequest string) (response *LatchAddOperationResponse, err error) {
	var resp *LatchResponse

	params := url.Values{}
	params.Set("parentId", parentId)
	params.Set("name", name)
	params.Set("two_factor", twoFactor)
	params.Set("lock_on_request", lockOnRequest)

	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_PUT, GetLatchURL(API_OPERATION_ACTION), nil, params, t.Now()), &LatchAddOperationResponse{}); err == nil {
		response = (*resp).(*LatchAddOperationResponse)
	}
	return response, err
}

//Updates an existing operation
func (l *Latch) UpdateOperation(operationId string, name string, twoFactor string, lockOnRequest string) (err error) {
	params := url.Values{}
	params.Set("name", name)
	if twoFactor != NOT_SET {
		params.Set("two_factor", twoFactor)
	}
	if lockOnRequest != NOT_SET {
		params.Set("lock_on_request", lockOnRequest)
	}

	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_POST, GetLatchURL(fmt.Sprint(API_OPERATION_ACTION, "/", operationId)), nil, params, t.Now()), nil)
	return err
}

//Deletes an existing operation
func (l *Latch) DeleteOperation(operationId string) (err error) {
	_, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_DELETE, GetLatchURL(fmt.Sprint(API_OPERATION_ACTION, "/", operationId)), nil, nil, t.Now()), nil)
	return err
}

//Shows operations information
//If operationId is empty this function will retrieve all the operations of the app
func (l *Latch) ShowOperation(operationId string) (response *LatchShowOperationResponse, err error) {
	var resp *LatchResponse
	var operation string

	if operationId != "" {
		operation += "/" + operationId
	}

	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(fmt.Sprint(API_OPERATION_ACTION, operation)), nil, nil, t.Now()), &LatchShowOperationResponse{}); err == nil {
		response = (*resp).(*LatchShowOperationResponse)
	}
	return response, err
}

//Gets the status of an account, given it's account ID
//If nootp is true, the one time password won't be included in the response
//If silent is true Latch will not send push notifications to the client (requires SILVER, GOLD or PLATINUM subscription)
func (l *Latch) Status(accountId string, nootp bool, silent bool) (response *LatchStatusResponse, err error) {
	query := fmt.Sprint(API_CHECK_STATUS_ACTION, "/", accountId)
	if nootp {
		query = fmt.Sprint(query, API_NOOTP_SUFFIX)
	}
	if silent {
		query = fmt.Sprint(query, API_SILENT_SUFFIX)
	}

	return l.StatusRequest(query)
}

//Gets the status of an operation, given it's account ID and operation ID
//If nootp is true, the one time password won't be included in the response
//If silent is true Latch will not send push notifications to the client (requires SILVER, GOLD or PLATINUM subscription)
func (l *Latch) OperationStatus(accountId string, operationId string, nootp bool, silent bool) (response *LatchStatusResponse, err error) {
	query := fmt.Sprint(API_CHECK_STATUS_ACTION, "/", accountId, "/op/", operationId)
	if nootp {
		query = fmt.Sprint(query, API_NOOTP_SUFFIX)
	}
	if silent {
		query = fmt.Sprint(query, API_SILENT_SUFFIX)
	}

	return l.StatusRequest(query)
}

//Performs a status request (application or operation) against the query URL provided
//Returns a LatchStatusResponse struct on success
func (l *Latch) StatusRequest(query string) (response *LatchStatusResponse, err error) {
	var resp *LatchResponse
	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(query), nil, nil, t.Now()), &LatchStatusResponse{}); err == nil {
		response = (*resp).(*LatchStatusResponse)
	}
	return response, err
}

//Gets the account's history between the from and to dates
func (l *Latch) History(accountId string, from t.Time, to t.Time) (response *LatchHistoryResponse, err error) {
	var resp *LatchResponse

	query := fmt.Sprintf("%s/%s", API_HISTORY_ACTION, accountId)
	if !from.IsZero() || !to.IsZero() {
		if !from.IsZero() {
			query = fmt.Sprint(query, fmt.Sprintf("/%d", from.UnixNano()/1000000))
		} else {
			query = fmt.Sprint(query, fmt.Sprintf("/%d", 0))
		}
	}
	if !to.IsZero() {
		query = fmt.Sprint(query, fmt.Sprintf("/%d", to.UnixNano()/1000000))
	}

	if resp, err = l.DoRequest(NewLatchRequest(l.AppID, l.SecretKey, HTTP_METHOD_GET, GetLatchURL(query), nil, nil, t.Now()), &LatchHistoryResponse{AppID: l.AppID}); err == nil {
		response = (*resp).(*LatchHistoryResponse)
	}
	return response, err
}
<|endoftext|>


<commit_before>package lclip

import (
	"encoding/json"
	"os"
)

type Clipboard struct {
	storage map[string]string
}

func NewClipboard(path string) (*Clipboard, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	c := &Clipboard{}
	if err = json.NewDecoder(f).Decode(&c.storage); err != nil {
		return nil, err
	}
	return c, nil
}

func (c *Clipboard) Get(label string) string {
	return c.storage[label]
}
<commit_msg>Implement Set<commit_after>package lclip

import (
	"encoding/json"
	"os"
)

type Clipboard struct {
	storage map[string]string
}

func NewClipboard(path string) (*Clipboard, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	c := &Clipboard{}
	if err = json.NewDecoder(f).Decode(&c.storage); err != nil {
		return nil, err
	}
	return c, nil
}

func (c *Clipboard) Get(label string) string {
	return c.storage[label]
}

func (c *Clipboard) Set(label, data string) {
	c.storage[label] = data
}
<|endoftext|>


<commit_before>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"errors"
	"unicode"
)

// eol indicates the end of an expression
const eol rune = -1

// lexer holds the lexer's state while scanning an expression. If any error
// occurs, the scanning stops immediately and returns the error.
type lexer struct {
	expr   []rune   // the input expression
	ch     rune     // current character
	pos    int      // current character position
	start  int      // current read offset
	tokens []*Token // tokenized lexemes
}

// https://en.wikipedia.org/wiki/Whitespace_character
var whitespaceChars = []rune{
	'\t', ' ', '\r', '\n', '\u0009', '\u000A', '\u000B', '\u000C', '\u000D',
	'\u0020', '\u0085', '\u00A0', '\u1680', '\u2000', '\u2001', '\u2002',
	'\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009',
	'\u200A', '\u2028', '\u2029', '\u202F', '\u205F', '\u3000', '\u180E',
	'\u200B', '\u200C', '\u200D', '\u2060', '\uFEFF',
}

func isIdent(c rune) bool {
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= 0x80 && unicode.IsLetter(c))
}

func isNumber(c rune) bool {
	return (c >= '0' && c <= '9') || c == '.'
}

func isHex(c rune) bool {
	return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}

func isBinary(c rune) bool {
	return c == '0' || c == '1'
}

func isOctal(c rune) bool {
	return c >= '0' && c <= '7'
}

func isWhitespace(c rune) bool {
	for _, v := range whitespaceChars {
		if v == c {
			return true
		}
	}

	return false
}

// Lex starts lexing an expression, converting an input string into a stream
// of tokens later passed on to the parser.
//
// Returns the generated tokens and any error found.
func Lex(expr string) ([]*Token, error) {
	l := &lexer{
		expr:  append([]rune(expr), eol), // add eol as padding
		pos:   0,
		start: 0,
	}

	return l.lex()
}

func (l *lexer) lex() ([]*Token, error) {
loop:
	for l.ch != eol {
		l.start = l.pos

		l.eat()

		switch {
		case isIdent(l.ch):
			l.readIdent()
		case isNumber(l.ch):
			l.readNumber()
		case isWhitespace(l.ch):
			l.skipWhitespace()
		default:
			switch l.ch {
			case '+':
				l.switchEq(ADD, ADD_EQ)
			case '-':
				// Check for unary minus. We decide unaryness at lexer level to
				// make it easier for the parser to know the difference.
				if l.isNegation() && l.peek() != '=' {
					l.emit(UNARY_MIN)
					break
				}
				l.switchEq(SUB, SUB_EQ)
			case '/':
				l.switchEq(DIV, DIV_EQ)
			case '*':
				if l.peek() == '*' {
					l.eat()
					l.switchEq(POW, POW_EQ)
				} else {
					l.switchEq(MUL, MUL_EQ)
				}
			case '%':
				l.switchEq(REM, REM_EQ)
			case '&':
				l.switchEq(AND, AND_EQ)
			case '|':
				l.switchEq(OR, OR_EQ)
			case '^':
				l.switchEq(XOR, XOR_EQ)
			case '<':
				if l.peek() == '<' {
					l.eat()
					l.switchEq(LSH, LSH_EQ)
				} else {
					l.switchEq(LT, LT_EQ)
				}
			case '>':
				if l.peek() == '>' {
					l.eat()
					l.switchEq(RSH, RSH_EQ)
				} else {
					l.switchEq(GT, GT_EQ)
				}
			case '~':
				l.emit(NOT)
			case '=':
				l.switchEq(EQ, EQ_EQ)
			case '!':
				if l.peek() != '=' {
					return nil, errors.New("Invalid operation " + string(l.ch))
				}
				l.eat()
				l.emit(BANG_EQ)
			case '(':
				l.emit(LPAREN)
			case ')':
				l.emit(RPAREN)
			case ',':
				l.emit(COMMA)
			case '#':
				// Comment, stop scanning for tokens
				l.emit(EOL)
				break loop
			case eol:
				l.emit(EOL)
			default:
				l.emit(ILLEGAL)
				return nil, errors.New("Invalid token " + string(l.ch))
			}
		}
	}

	return l.tokens, nil
}

func (l *lexer) peek() rune {
	return l.expr[l.pos]
}

func (l *lexer) prev() *Token {
	return l.tokens[len(l.tokens)-1]
}

func (l *lexer) eat() rune {
	l.ch = l.peek()
	l.pos++
	return l.ch
}

func (l *lexer) emit(toktype tokenType) {
	l.tokens = append(l.tokens, newToken(toktype, string(l.expr[l.start:l.pos]), l.start))
}

func (l *lexer) skipWhitespace() {
	for isWhitespace(l.peek()) {
		l.eat()
	}
}

func (l *lexer) readIdent() {
	for isIdent(l.peek()) || isNumber(l.peek()) {
		l.eat()
	}

	l.emit(IDENT)
}

func (l *lexer) readNumber() {
	// Hex literals
	if l.ch == '0' && (l.peek() == 'x' || l.peek() == 'X') {
		l.eat()

		for isHex(l.peek()) {
			l.eat()
		}

		l.emit(HEX)
		return
	}

	// Binary literals
	if l.ch == '0' && (l.peek() == 'b' || l.peek() == 'B') {
		l.eat()

		for isBinary(l.peek()) {
			l.eat()
		}

		l.emit(BINARY)
		return
	}

	// Octal literals
	if l.ch == '0' && (l.peek() == 'o' || l.peek() == 'O') {
		l.eat()

		for isOctal(l.peek()) {
			l.eat()
		}

		l.emit(OCTAL)
		return
	}

	// Numeral literals
	for isNumber(l.peek()) || l.peek() == 'e' || l.peek() == 'E' {
		l.eat()
		if (l.ch == 'e' || l.ch == 'E') && l.peek() == '-' {
			l.eat()
		}
	}

	l.emit(NUMBER)
}

func (l *lexer) isNegation() bool {
	return l.tokens == nil || l.prev().Type == LPAREN || l.prev().IsOperator()
}

func (l *lexer) switchEq(tokA, tokB tokenType) {
	if l.peek() == '=' {
		l.eat()
		l.emit(tokB)
	} else {
		l.emit(tokA)
	}
}
<commit_msg>Dont check ALL possible whitespace characters<commit_after>// Copyright 2016 Steven Oud. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.

package mathcat

import (
	"errors"
	"unicode"
)

// eol indicates the end of an expression
const eol rune = -1

// lexer holds the lexer's state while scanning an expression. If any error
// occurs, the scanning stops immediately and returns the error.
type lexer struct {
	expr   []rune   // the input expression
	ch     rune     // current character
	pos    int      // current character position
	start  int      // current read offset
	tokens []*Token // tokenized lexemes
}

func isIdent(c rune) bool {
	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= 0x80 && unicode.IsLetter(c))
}

func isNumber(c rune) bool {
	return (c >= '0' && c <= '9') || c == '.'
}

func isHex(c rune) bool {
	return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}

func isBinary(c rune) bool {
	return c == '0' || c == '1'
}

func isOctal(c rune) bool {
	return c >= '0' && c <= '7'
}

func isWhitespace(c rune) bool {
	return c == '\t' || c == ' ' || c == '\r' || c == '\n'
}

// Lex starts lexing an expression, converting an input string into a stream
// of tokens later passed on to the parser.
//
// Returns the generated tokens and any error found.
func Lex(expr string) ([]*Token, error) {
	l := &lexer{
		expr:  append([]rune(expr), eol), // add eol as padding
		pos:   0,
		start: 0,
	}

	return l.lex()
}

func (l *lexer) lex() ([]*Token, error) {
loop:
	for l.ch != eol {
		l.start = l.pos

		l.eat()

		switch {
		case isIdent(l.ch):
			l.readIdent()
		case isNumber(l.ch):
			l.readNumber()
		case isWhitespace(l.ch):
			l.skipWhitespace()
		default:
			switch l.ch {
			case '+':
				l.switchEq(ADD, ADD_EQ)
			case '-':
				// Check for unary minus. We decide unaryness at lexer level to
				// make it easier for the parser to know the difference.
				if l.isNegation() && l.peek() != '=' {
					l.emit(UNARY_MIN)
					break
				}
				l.switchEq(SUB, SUB_EQ)
			case '/':
				l.switchEq(DIV, DIV_EQ)
			case '*':
				if l.peek() == '*' {
					l.eat()
					l.switchEq(POW, POW_EQ)
				} else {
					l.switchEq(MUL, MUL_EQ)
				}
			case '%':
				l.switchEq(REM, REM_EQ)
			case '&':
				l.switchEq(AND, AND_EQ)
			case '|':
				l.switchEq(OR, OR_EQ)
			case '^':
				l.switchEq(XOR, XOR_EQ)
			case '<':
				if l.peek() == '<' {
					l.eat()
					l.switchEq(LSH, LSH_EQ)
				} else {
					l.switchEq(LT, LT_EQ)
				}
			case '>':
				if l.peek() == '>' {
					l.eat()
					l.switchEq(RSH, RSH_EQ)
				} else {
					l.switchEq(GT, GT_EQ)
				}
			case '~':
				l.emit(NOT)
			case '=':
				l.switchEq(EQ, EQ_EQ)
			case '!':
				if l.peek() != '=' {
					return nil, errors.New("Invalid operation " + string(l.ch))
				}
				l.eat()
				l.emit(BANG_EQ)
			case '(':
				l.emit(LPAREN)
			case ')':
				l.emit(RPAREN)
			case ',':
				l.emit(COMMA)
			case '#':
				// Comment, stop scanning for tokens
				l.emit(EOL)
				break loop
			case eol:
				l.emit(EOL)
			default:
				l.emit(ILLEGAL)
				return nil, errors.New("Invalid token " + string(l.ch))
			}
		}
	}

	return l.tokens, nil
}

func (l *lexer) peek() rune {
	return l.expr[l.pos]
}

func (l *lexer) prev() *Token {
	return l.tokens[len(l.tokens)-1]
}

func (l *lexer) eat() rune {
	l.ch = l.peek()
	l.pos++
	return l.ch
}

func (l *lexer) emit(toktype tokenType) {
	l.tokens = append(l.tokens, newToken(toktype, string(l.expr[l.start:l.pos]), l.start))
}

func (l *lexer) skipWhitespace() {
	for isWhitespace(l.peek()) {
		l.eat()
	}
}

func (l *lexer) readIdent() {
	for isIdent(l.peek()) || isNumber(l.peek()) {
		l.eat()
	}

	l.emit(IDENT)
}

func (l *lexer) readNumber() {
	// Hex literals
	if l.ch == '0' && (l.peek() == 'x' || l.peek() == 'X') {
		l.eat()

		for isHex(l.peek()) {
			l.eat()
		}

		l.emit(HEX)
		return
	}

	// Binary literals
	if l.ch == '0' && (l.peek() == 'b' || l.peek() == 'B') {
		l.eat()

		for isBinary(l.peek()) {
			l.eat()
		}

		l.emit(BINARY)
		return
	}

	// Octal literals
	if l.ch == '0' && (l.peek() == 'o' || l.peek() == 'O') {
		l.eat()

		for isOctal(l.peek()) {
			l.eat()
		}

		l.emit(OCTAL)
		return
	}

	// Numeral literals
	for isNumber(l.peek()) || l.peek() == 'e' || l.peek() == 'E' {
		l.eat()
		if (l.ch == 'e' || l.ch == 'E') && l.peek() == '-' {
			l.eat()
		}
	}

	l.emit(NUMBER)
}

func (l *lexer) isNegation() bool {
	return l.tokens == nil || l.prev().Type == LPAREN || l.prev().IsOperator()
}

func (l *lexer) switchEq(tokA, tokB tokenType) {
	if l.peek() == '=' {
		l.eat()
		l.emit(tokB)
	} else {
		l.emit(tokA)
	}
}
<|endoftext|>


<commit_before>// Package instructor is
package instructor

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// Finder is a function type that is used to load an object, serialized into a struct
// from the integrating-applications list of structs
type Finder func(string) (interface{}, error)

// Converter is a function type that is used to convert a string to an associated type
// You'd wrap whatever logic you needed, including something like just JSON Unmarshalling
// to turn a string representation of a value into a concrete instance of it's type.
// Four come out of the box for you: string, bool, int, and float64
type Converter func(string) (interface{}, error)

// Internal types used to be more explicit about the purposes of these maps
type instanceTable map[string]string
type heap map[string]interface{}
type cache map[string]heap
type finders map[string]Finder
type converters map[string]Converter
type arguments []interface{}

// Version is the current semver for this tool
const Version = "0.0.5"

// Instructor is an instance of the object which will allow you to inspect structs
type Instructor struct {
	interpreter *Interpreter
}

// New returns a new Instructor
func New() *Instructor {
	return &Instructor{
		interpreter: NewInterpreter(),
	}
}

// RegisterFinder is for registering one of your custom finders to look up your structs
func (i *Instructor) RegisterFinder(name string, f Finder) {
	i.interpreter.RegisterFinder(name, f)
}

// RegisterConverter is for registering one of your custom converters to convert cli arguments to typed values
func (i *Instructor) RegisterConverter(name string, c Converter) {
	i.interpreter.RegisterConverter(name, c)
}

// REPL will enter the read eval print loop, blocking the main thread until it exits
func (i *Instructor) REPL() error {
	// Buffered reader off of STDIN
	reader := bufio.NewReader(os.Stdin)
	input := ""
	stop := false
	var err error
	// Print welcome message
	fmt.Printf("Welcome to Inspector v%s\n", Version)
	fmt.Printf("For a list of commands, type help\n")
	for !stop {
		fmt.Printf("instructor %s >>", Version)
		if input, err = reader.ReadString('\n'); err != nil {
			fmt.Printf("Error reading from STDIN: %s\n", err.Error())
		}
		input = strings.TrimSpace(input)
		switch input {
		case "quit":
			stop = true
		case "help":
			fmt.Println("You can call the following commands:")
			fmt.Println("quit : exits the REPL")
			fmt.Println("help : prints this screen")
			fmt.Println("find : Looks up an object by it's type and ID")
			fmt.Println("\t\tEx: u = find(User,123456789)")
			fmt.Println("You can call methods or invoke Properties on an object. You can provide arguments by giving their type and value, in the order they're defined on the method")
			fmt.Println("\t\tEx: u.Strawmethod(false bool,50 int)")
			fmt.Println("\t\tEc: u.Strawproperty")
		default:
			l := newLexer(strings.NewReader(input))
			var f fragment
			statement := make([]fragment, 0)
			for f.token != EOF {
				f = l.scan()
				statement = append(statement, f)
			}
			i.interpreter.Evaluate(statement)

		}
	}
	return nil
}
<commit_msg>version bump to v0.1.0<commit_after>// Package instructor is
package instructor

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// Finder is a function type that is used to load an object, serialized into a struct
// from the integrating-applications list of structs
type Finder func(string) (interface{}, error)

// Converter is a function type that is used to convert a string to an associated type
// You'd wrap whatever logic you needed, including something like just JSON Unmarshalling
// to turn a string representation of a value into a concrete instance of it's type.
// Four come out of the box for you: string, bool, int, and float64
type Converter func(string) (interface{}, error)

// Internal types used to be more explicit about the purposes of these maps
type instanceTable map[string]string
type heap map[string]interface{}
type cache map[string]heap
type finders map[string]Finder
type converters map[string]Converter
type arguments []interface{}

// Version is the current semver for this tool
const Version = "0.1.0"

// Instructor is an instance of the object which will allow you to inspect structs
type Instructor struct {
	interpreter *Interpreter
}

// New returns a new Instructor
func New() *Instructor {
	return &Instructor{
		interpreter: NewInterpreter(),
	}
}

// RegisterFinder is for registering one of your custom finders to look up your structs
func (i *Instructor) RegisterFinder(name string, f Finder) {
	i.interpreter.RegisterFinder(name, f)
}

// RegisterConverter is for registering one of your custom converters to convert cli arguments to typed values
func (i *Instructor) RegisterConverter(name string, c Converter) {
	i.interpreter.RegisterConverter(name, c)
}

// REPL will enter the read eval print loop, blocking the main thread until it exits
func (i *Instructor) REPL() error {
	// Buffered reader off of STDIN
	reader := bufio.NewReader(os.Stdin)
	input := ""
	stop := false
	var err error
	// Print welcome message
	fmt.Printf("Welcome to Inspector v%s\n", Version)
	fmt.Printf("For a list of commands, type help\n")
	for !stop {
		fmt.Printf("instructor %s >>", Version)
		if input, err = reader.ReadString('\n'); err != nil {
			fmt.Printf("Error reading from STDIN: %s\n", err.Error())
		}
		input = strings.TrimSpace(input)
		switch input {
		case "quit":
			stop = true
		case "help":
			fmt.Println("You can call the following commands:")
			fmt.Println("quit : exits the REPL")
			fmt.Println("help : prints this screen")
			fmt.Println("find : Looks up an object by it's type and ID")
			fmt.Println("\t\tEx: u = find(User,123456789)")
			fmt.Println("You can call methods or invoke Properties on an object. You can provide arguments by giving their type and value, in the order they're defined on the method")
			fmt.Println("\t\tEx: u.Strawmethod(false bool,50 int)")
			fmt.Println("\t\tEc: u.Strawproperty")
		default:
			l := newLexer(strings.NewReader(input))
			var f fragment
			statement := make([]fragment, 0)
			for f.token != EOF {
				f = l.scan()
				statement = append(statement, f)
			}
			i.interpreter.Evaluate(statement)

		}
	}
	return nil
}
<|endoftext|>