<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"regexp"
	"strings"
	"time"

	"github.com/dfordsoft/golib/httputil"
	"github.com/dfordsoft/golib/ic"
)

func init() {
	registerNovelSiteHandler(&novelSiteHandler{
		Title: `飘天`,
		MatchPatterns: []string{
			`http://www\.piaotian\.com/html/[0-9]/[0-9]+/`,
			`http://www\.piaotian\.com/bookinfo/[0-9]/[0-9]+\.html`,
		},
		Download: func(u string) {
			dlPage := func(u string) (c []byte) {
				var err error
				headers := map[string]string{
					"Referer":                   "http://www.piaotian.com/",
					"User-Agent":                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0",
					"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
					"Accept-Language":           `en-US,en;q=0.8`,
					"Upgrade-Insecure-Requests": "1",
				}
				c, err = httputil.GetBytes(u, headers, time.Duration(opts.Timeout)*time.Second, opts.RetryCount)
				if err != nil {
					return
				}
				c = ic.Convert("gbk", "utf-8", c)
				c = bytes.Replace(c, []byte("\r\n"), []byte(""), -1)
				c = bytes.Replace(c, []byte("\r"), []byte(""), -1)
				c = bytes.Replace(c, []byte("\n"), []byte(""), -1)
				c = bytes.Replace(c, []byte(`更多更快章节请到。`), []byte(""), -1)
				c = bytes.Replace(c, []byte(`第一时间更新`), []byte(""), -1)
				c = bytes.Replace(c, []byte(`本书首发来自17K小说网，第一时间看正版内容！`), []byte(""), -1)
				c = bytes.Replace(c, []byte(`手机用户请访问http://m.piaotian.net`), []byte(""), -1)
				idx := bytes.Index(c, []byte(`    `))
				if idx > 1 {
					c = c[idx:]
				}

				idx = bytes.Index(c, []byte("
"))
				if idx > 1 {
					c = c[:idx]
				}
				c = bytes.Replace(c, []byte("

    "), []byte("

"), -1)
				c = bytes.Replace(c, []byte("    "), []byte(""), -1)
				return
			}
			tocURL := u
			r, _ := regexp.Compile(`http://www\.piaotian\.com/bookinfo/([0-9])/([0-9]+)\.html`)
			if r.MatchString(u) {
				ss := r.FindAllStringSubmatch(u, -1)
				s := ss[0]
				tocURL = fmt.Sprintf("http://www.piaotian.com/html/%s/%s/", s[1], s[2])
			}
			fmt.Println("download book from", tocURL)

			headers := map[string]string{
				"Referer":                   "http://www.piaotian.com/",
				"User-Agent":                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0",
				"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
				"Accept-Language":           `en-US,en;q=0.8`,
				"Upgrade-Insecure-Requests": "1",
			}
			b, err := httputil.GetBytes(tocURL, headers, time.Duration(opts.Timeout)*time.Second, opts.RetryCount)
			if err != nil {
				return
			}

			gen.Begin()

			dlutil := newDownloadUtil(dlPage, gen)
			dlutil.process()

			var title string
			index := 0
			r, _ = regexp.Compile(`^<li><a\shref="([0-9]+\.html)">([^<]+)</a></li>$`)
			re, _ := regexp.Compile(`^<h1>([^<]+)</h1>$`)
			scanner := bufio.NewScanner(bytes.NewReader(b))
			scanner.Split(bufio.ScanLines)
			for scanner.Scan() {
				line := scanner.Text()
				// convert from gbk to UTF-8
				l := ic.ConvertString("gbk", "utf-8", line)
				if title == "" {
					ss := re.FindAllStringSubmatch(l, -1)
					if len(ss) > 0 && len(ss[0]) > 0 {
						s := ss[0]
						title = s[1]
						idx := strings.Index(title, `最新章节`)
						if idx > 0 {
							title = title[:idx]
						}
						gen.SetTitle(title)
						continue
					}
				}
				if r.MatchString(l) {
					ss := r.FindAllStringSubmatch(l, -1)
					s := ss[0]
					finalURL := fmt.Sprintf("%s%s", tocURL, s[1])
					index++
					if dlutil.addURL(index, s[2], finalURL) {
						break
					}
				}
			}
			dlutil.wait()
			gen.End()
		},
	})
}
<commit_msg>(*)fix piaotian data wash<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"regexp"
	"strings"
	"time"

	"github.com/dfordsoft/golib/httputil"
	"github.com/dfordsoft/golib/ic"
)

func init() {
	registerNovelSiteHandler(&novelSiteHandler{
		Title: `飘天`,
		MatchPatterns: []string{
			`http://www\.piaotian\.com/html/[0-9]/[0-9]+/`,
			`http://www\.piaotian\.com/bookinfo/[0-9]/[0-9]+\.html`,
		},
		Download: func(u string) {
			dlPage := func(u string) (c []byte) {
				var err error
				headers := map[string]string{
					"Referer":                   "http://www.piaotian.com/",
					"User-Agent":                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0",
					"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
					"Accept-Language":           `en-US,en;q=0.8`,
					"Upgrade-Insecure-Requests": "1",
				}
				c, err = httputil.GetBytes(u, headers, time.Duration(opts.Timeout)*time.Second, opts.RetryCount)
				if err != nil {
					return
				}
				c = ic.Convert("gbk", "utf-8", c)
				c = bytes.Replace(c, []byte("\r\n"), []byte(""), -1)
				c = bytes.Replace(c, []byte("\r"), []byte(""), -1)
				c = bytes.Replace(c, []byte("\n"), []byte(""), -1)
				c = bytes.Replace(c, []byte(`更多更快章节请到。`), []byte(""), -1)
				c = bytes.Replace(c, []byte(`第一时间更新`), []byte(""), -1)
				c = bytes.Replace(c, []byte(`本书首发来自17K小说网，第一时间看正版内容！`), []byte(""), -1)
				c = bytes.Replace(c, []byte(`手机用户请访问http://m.piaotian.net`), []byte(""), -1)
				idx := bytes.Index(c, []byte(`    `))
				if idx > 1 {
					c = c[idx:]
				} else {
					leadingStr := `</tr></table><br>`
					idx = bytes.Index(c, []byte(leadingStr))
					if idx > 1 {
						c = c[idx+len(leadingStr):]
					}
				}

				idx = bytes.Index(c, []byte("
"))
				if idx > 1 {
					c = c[:idx]
				}
				c = bytes.Replace(c, []byte("

    "), []byte("

"), -1)
				c = bytes.Replace(c, []byte("    "), []byte(""), -1)
				return
			}
			tocURL := u
			r, _ := regexp.Compile(`http://www\.piaotian\.com/bookinfo/([0-9])/([0-9]+)\.html`)
			if r.MatchString(u) {
				ss := r.FindAllStringSubmatch(u, -1)
				s := ss[0]
				tocURL = fmt.Sprintf("http://www.piaotian.com/html/%s/%s/", s[1], s[2])
			}
			fmt.Println("download book from", tocURL)

			headers := map[string]string{
				"Referer":                   "http://www.piaotian.com/",
				"User-Agent":                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0",
				"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
				"Accept-Language":           `en-US,en;q=0.8`,
				"Upgrade-Insecure-Requests": "1",
			}
			b, err := httputil.GetBytes(tocURL, headers, time.Duration(opts.Timeout)*time.Second, opts.RetryCount)
			if err != nil {
				return
			}

			gen.Begin()

			dlutil := newDownloadUtil(dlPage, gen)
			dlutil.process()

			var title string
			index := 0
			r, _ = regexp.Compile(`^<li><a\shref="([0-9]+\.html)">([^<]+)</a></li>$`)
			re, _ := regexp.Compile(`^<h1>([^<]+)</h1>$`)
			scanner := bufio.NewScanner(bytes.NewReader(b))
			scanner.Split(bufio.ScanLines)
			for scanner.Scan() {
				line := scanner.Text()
				// convert from gbk to UTF-8
				l := ic.ConvertString("gbk", "utf-8", line)
				if title == "" {
					ss := re.FindAllStringSubmatch(l, -1)
					if len(ss) > 0 && len(ss[0]) > 0 {
						s := ss[0]
						title = s[1]
						idx := strings.Index(title, `最新章节`)
						if idx > 0 {
							title = title[:idx]
						}
						gen.SetTitle(title)
						continue
					}
				}
				if r.MatchString(l) {
					ss := r.FindAllStringSubmatch(l, -1)
					s := ss[0]
					finalURL := fmt.Sprintf("%s%s", tocURL, s[1])
					index++
					if dlutil.addURL(index, s[2], finalURL) {
						break
					}
				}
			}
			dlutil.wait()
			gen.End()
		},
	})
}
<|endoftext|>


<commit_before>package internal

import (
	"archive/tar"
	"errors"
	"fmt"

	"github.com/cloudfoundry-incubator/executor"
	"github.com/pivotal-golang/lager"
)

const MAX_RESULT_SIZE = 1024 * 10

var ErrResultFileTooLarge = errors.New(
	fmt.Sprintf("result file is too large (over %d bytes)", MAX_RESULT_SIZE),
)

//go:generate counterfeiter -o fake_internal/fake_container_delegate.go container_delegate.go ContainerDelegate

type ContainerDelegate interface {
	GetContainer(logger lager.Logger, guid string) (executor.Container, bool)
	RunContainer(logger lager.Logger, req *executor.RunRequest) bool
	StopContainer(logger lager.Logger, guid string) bool
	DeleteContainer(logger lager.Logger, guid string) bool
	FetchContainerResultFile(logger lager.Logger, guid string, filename string) (string, error)
}

type containerDelegate struct {
	client executor.Client
}

func NewContainerDelegate(client executor.Client) ContainerDelegate {
	return &containerDelegate{
		client: client,
	}
}

func (d *containerDelegate) GetContainer(logger lager.Logger, guid string) (executor.Container, bool) {
	logger.Info("fetch-container")
	container, err := d.client.GetContainer(logger, guid)
	if err != nil {
		logInfoOrError(logger, "failed-fetch-container", err)
		return container, false
	}
	logger.Info("succeeded-fetch-container")
	return container, true
}

func (d *containerDelegate) RunContainer(logger lager.Logger, req *executor.RunRequest) bool {
	logger.Info("running-container")
	err := d.client.RunContainer(logger, req)
	if err != nil {
		logInfoOrError(logger, "failed-running-container", err)
		d.DeleteContainer(logger, req.Guid)
		return false
	}
	logger.Info("succeeded-running-container")
	return true
}

func (d *containerDelegate) StopContainer(logger lager.Logger, guid string) bool {
	logger.Info("stopping-container")
	err := d.client.StopContainer(logger, guid)
	if err != nil {
		logInfoOrError(logger, "failed-stopping-container", err)
		return false
	}
	logger.Info("succeeded-stopping-container")
	return true
}

func (d *containerDelegate) DeleteContainer(logger lager.Logger, guid string) bool {
	logger.Info("deleting-container")
	err := d.client.DeleteContainer(logger, guid)
	if err != nil {
		logInfoOrError(logger, "failed-deleting-container", err)
		return false
	}
	logger.Info("succeeded-deleting-container")
	return true
}

func (d *containerDelegate) FetchContainerResultFile(logger lager.Logger, guid string, filename string) (string, error) {
	logger.Info("fetching-container-result")
	stream, err := d.client.GetFiles(logger, guid, filename)
	if err != nil {
		logInfoOrError(logger, "failed-fetching-container-result-stream-from-executor", err)
		return "", err
	}

	defer stream.Close()

	tarReader := tar.NewReader(stream)

	_, err = tarReader.Next()
	if err != nil {
		return "", err
	}

	buf := make([]byte, MAX_RESULT_SIZE+1)
	n, err := tarReader.Read(buf)
	if n > MAX_RESULT_SIZE {
		logInfoOrError(logger, "failed-fetching-container-result-too-large", err)
		return "", ErrResultFileTooLarge
	}

	logger.Info("succeeded-fetching-container-result")
	return string(buf[:n]), nil
}

func logInfoOrError(logger lager.Logger, msg string, err error) {
	if err == executor.ErrContainerNotFound {
		logger.Info(msg, lager.Data{"error": err.Error()})
	} else {
		logger.Error(msg, err)
	}
}
<commit_msg>Reduce noise in logs by changing some log lines to Debug<commit_after>package internal

import (
	"archive/tar"
	"errors"
	"fmt"

	"github.com/cloudfoundry-incubator/executor"
	"github.com/pivotal-golang/lager"
)

const MAX_RESULT_SIZE = 1024 * 10

var ErrResultFileTooLarge = errors.New(
	fmt.Sprintf("result file is too large (over %d bytes)", MAX_RESULT_SIZE),
)

//go:generate counterfeiter -o fake_internal/fake_container_delegate.go container_delegate.go ContainerDelegate

type ContainerDelegate interface {
	GetContainer(logger lager.Logger, guid string) (executor.Container, bool)
	RunContainer(logger lager.Logger, req *executor.RunRequest) bool
	StopContainer(logger lager.Logger, guid string) bool
	DeleteContainer(logger lager.Logger, guid string) bool
	FetchContainerResultFile(logger lager.Logger, guid string, filename string) (string, error)
}

type containerDelegate struct {
	client executor.Client
}

func NewContainerDelegate(client executor.Client) ContainerDelegate {
	return &containerDelegate{
		client: client,
	}
}

func (d *containerDelegate) GetContainer(logger lager.Logger, guid string) (executor.Container, bool) {
	logger.Debug("fetch-container")
	container, err := d.client.GetContainer(logger, guid)
	if err != nil {
		logInfoOrError(logger, "failed-fetch-container", err)
		return container, false
	}
	logger.Debug("succeeded-fetch-container")
	return container, true
}

func (d *containerDelegate) RunContainer(logger lager.Logger, req *executor.RunRequest) bool {
	logger.Info("running-container")
	err := d.client.RunContainer(logger, req)
	if err != nil {
		logInfoOrError(logger, "failed-running-container", err)
		d.DeleteContainer(logger, req.Guid)
		return false
	}
	logger.Info("succeeded-running-container")
	return true
}

func (d *containerDelegate) StopContainer(logger lager.Logger, guid string) bool {
	logger.Info("stopping-container")
	err := d.client.StopContainer(logger, guid)
	if err != nil {
		logInfoOrError(logger, "failed-stopping-container", err)
		return false
	}
	logger.Info("succeeded-stopping-container")
	return true
}

func (d *containerDelegate) DeleteContainer(logger lager.Logger, guid string) bool {
	logger.Info("deleting-container")
	err := d.client.DeleteContainer(logger, guid)
	if err != nil {
		logInfoOrError(logger, "failed-deleting-container", err)
		return false
	}
	logger.Info("succeeded-deleting-container")
	return true
}

func (d *containerDelegate) FetchContainerResultFile(logger lager.Logger, guid string, filename string) (string, error) {
	logger.Info("fetching-container-result")
	stream, err := d.client.GetFiles(logger, guid, filename)
	if err != nil {
		logInfoOrError(logger, "failed-fetching-container-result-stream-from-executor", err)
		return "", err
	}

	defer stream.Close()

	tarReader := tar.NewReader(stream)

	_, err = tarReader.Next()
	if err != nil {
		return "", err
	}

	buf := make([]byte, MAX_RESULT_SIZE+1)
	n, err := tarReader.Read(buf)
	if n > MAX_RESULT_SIZE {
		logInfoOrError(logger, "failed-fetching-container-result-too-large", err)
		return "", ErrResultFileTooLarge
	}

	logger.Info("succeeded-fetching-container-result")
	return string(buf[:n]), nil
}

func logInfoOrError(logger lager.Logger, msg string, err error) {
	if err == executor.ErrContainerNotFound {
		logger.Info(msg, lager.Data{"error": err.Error()})
	} else {
		logger.Error(msg, err)
	}
}
<|endoftext|>


<commit_before>package digits

import "sort"

func seqDigits(low, high int) []int {
	return useStraight(low, high)
}

// useStraight time complexity O(N) where N is the max digits, space complexity O(1)
func useStraight(low, high int) []int {
	var lnd, hnd int
	num := low
	for num > 0 {
		num /= 10
		lnd++
	}
	num = high
	for num > 0 {
		num /= 10
		hnd++
	}
	var ans []int
	for i := 1; i < 9; i++ {
		gen(&ans, i, low, high, hnd)
	}
	sort.Ints(ans)
	return ans
}

func gen(ans *[]int, startNum, low, high, hnd int) {
	var idx, num int
	for idx < hnd {
		if startNum+idx < 10 {
			num = num*10 + startNum + idx
			idx++
			if num >= low && num <= high {
				*ans = append((*ans), num)
			}
		} else {
			break
		}
	}
}
<commit_msg>solve 1129 use bfs<commit_after>package digits

import (
	"sort"

	"github.com/catorpilor/leetcode/utils"
)

func seqDigits(low, high int) []int {
	return useStraight(low, high)
}

// useStraight time complexity O(N) where N is the max digits, space complexity O(1)
func useStraight(low, high int) []int {
	var lnd, hnd int
	num := low
	for num > 0 {
		num /= 10
		lnd++
	}
	num = high
	for num > 0 {
		num /= 10
		hnd++
	}
	var ans []int
	for i := 1; i < 9; i++ {
		gen(&ans, i, low, high, hnd)
	}
	sort.Ints(ans)
	return ans
}

func gen(ans *[]int, startNum, low, high, hnd int) {
	var idx, num int
	for idx < hnd {
		if startNum+idx < 10 {
			num = num*10 + startNum + idx
			idx++
			if num >= low && num <= high {
				*ans = append((*ans), num)
			}
		} else {
			break
		}
	}
}

// useBfs time complexity O(lg(high)), space complexity O(N)
func useBfs(low, high int) []int {
	queue := utils.NewQueue()
	for i := 1; i <= 9; i++ {
		queue.Enroll(i)
	}
	var ans []int
	for !queue.IsEmpty() {
		f := queue.Pull().(int)
		if f <= low && f >= high {
			ans = append(ans, f)
		}
		if f > high {
			break
		}
		ld := f % 10
		if ld < 9 {
			queue.Enroll(f*10 + ld + 1)
		}
	}
	return ans
}
<|endoftext|>


<commit_before>//go:build linux
// +build linux

// This program demonstrates how to attach an eBPF program to a uretprobe.
// The program will be attached to the 'readline' symbol in the binary '/bin/bash' and print out
// the line which 'readline' functions returns to the caller.
package main

import (
	"bytes"
	"encoding/binary"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/cilium/ebpf/link"
	"github.com/cilium/ebpf/perf"
	"golang.org/x/sys/unix"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang-11 UretProbeExample ./bpf/uretprobe_example.c -- -I../headers -O2

// An Event represents a perf event sent to userspace from the eBPF program
// running in the kernel. Note that this must match the C event_t structure,
// and that both C and Go structs must be aligned same way.
type Event struct {
	PID  uint32
	Line [80]byte
}

const (
	// The path to the ELF binary containing the function to trace.
	// On some distributions, the 'readline' function is provided by a
	// dynamically-linked library, so the path of the library will need
	// to be specified instead, e.g. /usr/lib/libreadline.so.8.
	// Use `ldd /bin/bash` to find these paths.
	binPath = "/bin/bash"
	symbol  = "readline"
)

func main() {
	stopper := make(chan os.Signal, 1)
	signal.Notify(stopper, os.Interrupt, syscall.SIGTERM)

	// Increase rlimit so the eBPF map and program can be loaded.
	if err := unix.Setrlimit(unix.RLIMIT_MEMLOCK, &unix.Rlimit{
		Cur: unix.RLIM_INFINITY,
		Max: unix.RLIM_INFINITY,
	}); err != nil {
		log.Fatalf("failed to set temporary rlimit: %v", err)
	}

	// Load pre-compiled programs and maps into the kernel.
	objs := UretProbeExampleObjects{}
	if err := LoadUretProbeExampleObjects(&objs, nil); err != nil {
		log.Fatalf("loading objects: %s", err)
	}
	defer objs.Close()

	// Open an ELF binary and read its symbols.
	ex, err := link.OpenExecutable(binPath)
	if err != nil {
		log.Fatalf("opening executable: %s", err)
	}

	// Open a Uretprobe at the exit point of the symbol and attach
	// the pre-compiled eBPF program to it.
	up, err := ex.Uretprobe(symbol, objs.UretprobeBashReadline)
	if err != nil {
		log.Fatalf("creating uretprobe: %s", err)
	}
	defer up.Close()

	// Open a perf event reader from userspace on the PERF_EVENT_ARRAY map
	// described in the eBPF C program.
	rd, err := perf.NewReader(objs.Events, os.Getpagesize())
	if err != nil {
		log.Fatalf("creating perf event reader: %s", err)
	}
	defer rd.Close()

	go func() {
		// Wait for a signal and close the perf reader,
		// which will interrupt rd.Read() and make the program exit.
		<-stopper
		log.Println("Received signal, exiting program..")

		if err := rd.Close(); err != nil {
			log.Fatalf("closing perf event reader: %s", err)
		}
	}()

	log.Printf("Listening for events..")

	var event Event
	for {
		record, err := rd.Read()
		if err != nil {
			if perf.IsClosed(err) {
				return
			}
			log.Printf("reading from perf event reader: %s", err)
		}

		if record.LostSamples != 0 {
			log.Printf("perf event ring buffer full, dropped %d samples", record.LostSamples)
			continue
		}

		// Parse the perf event entry into an Event structure.
		if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil {
			log.Printf("parsing perf event: %s", err)
			continue
		}

		log.Printf("%s:%s return value: %s", binPath, symbol, unix.ByteSliceToString(event.Line[:]))
	}
}
<commit_msg>examples: adapt uretprobe example to the new library version<commit_after>//go:build linux
// +build linux

// This program demonstrates how to attach an eBPF program to a uretprobe.
// The program will be attached to the 'readline' symbol in the binary '/bin/bash' and print out
// the line which 'readline' functions returns to the caller.
package main

import (
	"bytes"
	"encoding/binary"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/cilium/ebpf/link"
	"github.com/cilium/ebpf/perf"
	"golang.org/x/sys/unix"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang-11 UretProbeExample ./bpf/uretprobe_example.c -- -I../headers -O2

// An Event represents a perf event sent to userspace from the eBPF program
// running in the kernel. Note that this must match the C event_t structure,
// and that both C and Go structs must be aligned same way.
type Event struct {
	PID  uint32
	Line [80]byte
}

const (
	// The path to the ELF binary containing the function to trace.
	// On some distributions, the 'readline' function is provided by a
	// dynamically-linked library, so the path of the library will need
	// to be specified instead, e.g. /usr/lib/libreadline.so.8.
	// Use `ldd /bin/bash` to find these paths.
	binPath = "/bin/bash"
	symbol  = "readline"
)

func main() {
	stopper := make(chan os.Signal, 1)
	signal.Notify(stopper, os.Interrupt, syscall.SIGTERM)

	// Increase rlimit so the eBPF map and program can be loaded.
	if err := unix.Setrlimit(unix.RLIMIT_MEMLOCK, &unix.Rlimit{
		Cur: unix.RLIM_INFINITY,
		Max: unix.RLIM_INFINITY,
	}); err != nil {
		log.Fatalf("failed to set temporary rlimit: %v", err)
	}

	// Load pre-compiled programs and maps into the kernel.
	objs := UretProbeExampleObjects{}
	if err := LoadUretProbeExampleObjects(&objs, nil); err != nil {
		log.Fatalf("loading objects: %s", err)
	}
	defer objs.Close()

	// Open an ELF binary and read its symbols.
	ex, err := link.OpenExecutable(binPath)
	if err != nil {
		log.Fatalf("opening executable: %s", err)
	}

	// Open a Uretprobe at the exit point of the symbol and attach
	// the pre-compiled eBPF program to it.
	up, err := ex.Uretprobe(symbol, objs.UretprobeBashReadline, nil)
	if err != nil {
		log.Fatalf("creating uretprobe: %s", err)
	}
	defer up.Close()

	// Open a perf event reader from userspace on the PERF_EVENT_ARRAY map
	// described in the eBPF C program.
	rd, err := perf.NewReader(objs.Events, os.Getpagesize())
	if err != nil {
		log.Fatalf("creating perf event reader: %s", err)
	}
	defer rd.Close()

	go func() {
		// Wait for a signal and close the perf reader,
		// which will interrupt rd.Read() and make the program exit.
		<-stopper
		log.Println("Received signal, exiting program..")

		if err := rd.Close(); err != nil {
			log.Fatalf("closing perf event reader: %s", err)
		}
	}()

	log.Printf("Listening for events..")

	var event Event
	for {
		record, err := rd.Read()
		if err != nil {
			if perf.IsClosed(err) {
				return
			}
			log.Printf("reading from perf event reader: %s", err)
		}

		if record.LostSamples != 0 {
			log.Printf("perf event ring buffer full, dropped %d samples", record.LostSamples)
			continue
		}

		// Parse the perf event entry into an Event structure.
		if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil {
			log.Printf("parsing perf event: %s", err)
			continue
		}

		log.Printf("%s:%s return value: %s", binPath, symbol, unix.ByteSliceToString(event.Line[:]))
	}
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 go-diameter authors.  All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Sn🔍 op agent can sit in between two diameter peers and snoop all messages
// in real time, printing them to the console.
//
// It's a simple 1:1 proxy.

package main

import (
	"flag"
	"log"
	"runtime"
	"strings"
	"sync"

	"github.com/fiorix/go-diameter/diam"
	"github.com/fiorix/go-diameter/diam/dict"
)

// A Bridge between two peers.
type Bridge struct {
	Client chan *diam.Message // Remote client connecting to this server
	Server chan *diam.Message // Upstream connection (real server)
}

var (
	upstreamAddr string
	liveMu       sync.RWMutex
	liveBridge   = make(map[string]*Bridge) // ip:bridge
)

func main() {
	local := flag.String("local", ":3868", "set local addr")
	remote := flag.String("remote", "", "set remote addr")
	files := flag.String("dict", "", "comma separated list of dictionaries")
	flag.Parse()
	upstreamAddr = *remote
	log.Println("Diameter sn🔍 op agent")
	if len(*remote) == 0 {
		log.Fatal("Missing argument -remote")
	}
	if *local == *remote {
		log.Fatal("Local and remote address are the same. Duh?")
	}
	// Load dictionary files onto the default (base protocol) dict.
	if *files != "" {
		for _, f := range strings.Split(*files, ",") {
			log.Println("Loading dictionary", f)
			if err := dict.Default.LoadFile(f); err != nil {
				log.Fatal(err)
			}
		}
	}
	// Use all CPUs.
	runtime.GOMAXPROCS(runtime.NumCPU())
	// Prepare the server.
	diam.HandleFunc("ALL", func(c diam.Conn, m *diam.Message) {
		// Forward incoming messages to the upstream server.
		if b := GetBridge(c); b != nil {
			b.Server <- m
		} else {
			// Upstream server unavailable, bye.
			c.Close()
		}
	})
	// Start the server using default handler and dict.
	log.Printf("Starting server on %s", *local)
	diam.ListenAndServe(*local, nil, nil)
}

// GetBridge returns the Bridge object for a given client, if it exists.
// Otherwise GetBridge connects to the upstream server and set up the
// bridge with the client, returning the newly created Bridge object.
func GetBridge(c diam.Conn) *Bridge {
	liveMu.RLock()
	if b, ok := liveBridge[c.RemoteAddr().String()]; ok {
		liveMu.RUnlock()
		return b
	}
	liveMu.RUnlock()
	liveMu.Lock()
	defer liveMu.Unlock()
	b := &Bridge{
		Client: make(chan *diam.Message),
		Server: make(chan *diam.Message),
	}
	liveBridge[c.RemoteAddr().String()] = b
	// Prepare for the upstream connection.
	mux := diam.NewServeMux()
	mux.HandleFunc("ALL", func(c diam.Conn, m *diam.Message) {
		// Forward incoming messages to the client.
		b.Client <- m
	})
	// Connect to upstream server.
	s, err := diam.Dial(upstreamAddr, mux, nil)
	if err != nil {
		return nil
	}
	log.Printf("Creating bridge from %s to %s",
		c.RemoteAddr().String(), s.RemoteAddr().String())
	go Pump(c, s, b.Client, b.Server)
	go Pump(s, c, b.Server, b.Client)
	return b
}

// Pump messages from one side to the other.
func Pump(src, dst diam.Conn, srcChan, dstChan chan *diam.Message) {
	for {
		select {
		case m := <-srcChan:
			if m == nil {
				src.Close()
				return
			}
			log.Printf(
				"Message from %s to %s\n%s",
				src.RemoteAddr().String(),
				dst.RemoteAddr().String(),
				m,
			)
			if _, err := m.WriteTo(src); err != nil {
				src.Close() // triggers the case below
			}
		case <-src.(diam.CloseNotifier).CloseNotify():
			liveMu.Lock()
			defer liveMu.Unlock()
			if _, ok := liveBridge[src.RemoteAddr().String()]; ok {
				delete(liveBridge, src.RemoteAddr().String())
				log.Printf(
					"Destroying bridge from %s to %s",
					src.RemoteAddr().String(),
					dst.RemoteAddr().String(),
				)
			} else {
				delete(liveBridge, dst.RemoteAddr().String())
				log.Printf(
					"Destroying bridge from %s to %s",
					dst.RemoteAddr().String(),
					src.RemoteAddr().String(),
				)
			}
			src.Close()
			dstChan <- nil
			return
		}
	}
}
<commit_msg>Updated docs<commit_after>// Copyright 2013-2014 go-diameter authors.  All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Snoop agent can sit in between two diameter peers and snoop all messages
// in real time, printing them to the console. By default it only
// supports the default dictionaries of go-diameter, so if you're testing
// a custom application use the -dict command line flag to load your
// dictionary from a file.
//
// This agent is a simple 1:1 proxy.

package main

import (
	"flag"
	"log"
	"runtime"
	"strings"
	"sync"

	"github.com/fiorix/go-diameter/diam"
	"github.com/fiorix/go-diameter/diam/dict"
)

// A Bridge between two peers.
type Bridge struct {
	Client chan *diam.Message // Remote client connecting to this server
	Server chan *diam.Message // Upstream connection (real server)
}

var (
	upstreamAddr string
	liveMu       sync.RWMutex
	liveBridge   = make(map[string]*Bridge) // ip:bridge
)

func main() {
	local := flag.String("local", ":3868", "set local addr")
	remote := flag.String("remote", "", "set remote addr")
	files := flag.String("dict", "", "comma separated list of dictionaries")
	flag.Parse()
	upstreamAddr = *remote
	log.Println("Diameter sn🔍 op agent")
	if len(*remote) == 0 {
		log.Fatal("Missing argument -remote")
	}
	if *local == *remote {
		log.Fatal("Local and remote address are the same. Duh?")
	}
	// Load dictionary files onto the default (base protocol) dict.
	if *files != "" {
		for _, f := range strings.Split(*files, ",") {
			log.Println("Loading dictionary", f)
			if err := dict.Default.LoadFile(f); err != nil {
				log.Fatal(err)
			}
		}
	}
	// Use all CPUs.
	runtime.GOMAXPROCS(runtime.NumCPU())
	// Prepare the server.
	diam.HandleFunc("ALL", func(c diam.Conn, m *diam.Message) {
		// Forward incoming messages to the upstream server.
		if b := GetBridge(c); b != nil {
			b.Server <- m
		} else {
			// Upstream server unavailable, bye.
			c.Close()
		}
	})
	// Start the server using default handler and dict.
	log.Printf("Starting server on %s", *local)
	diam.ListenAndServe(*local, nil, nil)
}

// GetBridge returns the Bridge object for a given client, if it exists.
// Otherwise GetBridge connects to the upstream server and set up the
// bridge with the client, returning the newly created Bridge object.
func GetBridge(c diam.Conn) *Bridge {
	liveMu.RLock()
	if b, ok := liveBridge[c.RemoteAddr().String()]; ok {
		liveMu.RUnlock()
		return b
	}
	liveMu.RUnlock()
	liveMu.Lock()
	defer liveMu.Unlock()
	b := &Bridge{
		Client: make(chan *diam.Message),
		Server: make(chan *diam.Message),
	}
	liveBridge[c.RemoteAddr().String()] = b
	// Prepare for the upstream connection.
	mux := diam.NewServeMux()
	mux.HandleFunc("ALL", func(c diam.Conn, m *diam.Message) {
		// Forward incoming messages to the client.
		b.Client <- m
	})
	// Connect to upstream server.
	s, err := diam.Dial(upstreamAddr, mux, nil)
	if err != nil {
		return nil
	}
	log.Printf("Creating bridge from %s to %s",
		c.RemoteAddr().String(), s.RemoteAddr().String())
	go Pump(c, s, b.Client, b.Server)
	go Pump(s, c, b.Server, b.Client)
	return b
}

// Pump messages from one side to the other.
func Pump(src, dst diam.Conn, srcChan, dstChan chan *diam.Message) {
	for {
		select {
		case m := <-srcChan:
			if m == nil {
				src.Close()
				return
			}
			log.Printf(
				"Message from %s to %s\n%s",
				src.RemoteAddr().String(),
				dst.RemoteAddr().String(),
				m,
			)
			if _, err := m.WriteTo(src); err != nil {
				src.Close() // triggers the case below
			}
		case <-src.(diam.CloseNotifier).CloseNotify():
			liveMu.Lock()
			defer liveMu.Unlock()
			if _, ok := liveBridge[src.RemoteAddr().String()]; ok {
				delete(liveBridge, src.RemoteAddr().String())
				log.Printf(
					"Destroying bridge from %s to %s",
					src.RemoteAddr().String(),
					dst.RemoteAddr().String(),
				)
			} else {
				delete(liveBridge, dst.RemoteAddr().String())
				log.Printf(
					"Destroying bridge from %s to %s",
					dst.RemoteAddr().String(),
					src.RemoteAddr().String(),
				)
			}
			src.Close()
			dstChan <- nil
			return
		}
	}
}
<|endoftext|>


<commit_before>package easyvk

type WallUploadServer struct {
	Response struct {
		UploadURL string `json:"upload_url"`
		AlbumID   int `json:"aid"`
		UserID    int `json:"mid"`
	} `json:"response"`
}
<commit_msg>Refactor with golint<commit_after>package easyvk

// WallUploadServer describes the server address
// for photo upload onto a user's wall.
type WallUploadServer struct {
	Response struct {
		UploadURL string `json:"upload_url"`
		AlbumID   int `json:"aid"`
		UserID    int `json:"mid"`
	} `json:"response"`
}
<|endoftext|>


<commit_before>package torrent

import (
	"crypto/rand"
	"errors"
	"io"
	"sync"

	"github.com/cenkalti/rain/internal/announcer"
	"github.com/cenkalti/rain/internal/downloader"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/internal/metainfo"
	"github.com/cenkalti/rain/internal/peerlist"
	"github.com/cenkalti/rain/internal/peermanager"
	"github.com/cenkalti/rain/internal/torrentdata"
	"github.com/cenkalti/rain/internal/uploader"
	"github.com/cenkalti/rain/internal/worker"
)

var (
	// Version of client. Set during build.
	Version = "0000" // zero means development version

	// http://www.bittorrent.org/beps/bep_0020.html
	peerIDPrefix = []byte("-RN" + Version + "-")
)

// Torrent connect to peers and downloads files from swarm.
type Torrent struct {
	peerID   [20]byte           // unique id per torrent
	metainfo *metainfo.MetaInfo // parsed torrent file
	data     *torrentdata.Data  // provides access to files on disk
	dest     string             // path of files on disk
	port     int                // listen for peer connections
	running  bool               // true after Start() is called
	closed   bool               // true after Close() is called
	m        sync.Mutex         // protects running and closed state
	errC     chan error         // downlaoder sends critical error to this channel
	workers  worker.Workers
	log      logger.Logger
}

// New returns a new torrent by reading a metainfo file.
//
// Files are read from disk. If there are existing files, hash check will be done.
//
// Returned torrent is in stopped state.
//
// Close must be called before discarding the torrent.
func New(r io.Reader, dest string, port int) (*Torrent, error) {
	if port <= 0 {
		return nil, errors.New("invalid port number")
	}
	m, err := metainfo.New(r)
	if err != nil {
		return nil, err
	}
	logName := m.Info.Name
	if len(logName) > 8 {
		logName = logName[:8]
	}
	var peerID [20]byte
	copy(peerID[:], peerIDPrefix)
	_, err = rand.Read(peerID[len(peerIDPrefix):]) // nolint: gosec
	if err != nil {
		return nil, err
	}
	data, err := torrentdata.New(m.Info, dest)
	if err != nil {
		return nil, err
	}
	err = data.Verify()
	if err != nil {
		return nil, err
	}
	return &Torrent{
		peerID:   peerID,
		metainfo: m,
		data:     data,
		dest:     dest,
		port:     port,
		log:      logger.New("download " + logName),
	}, nil
}

// Start listening peer port, accepting incoming peer connections and download missing pieces.
//
// Seeding continues after all files are donwloaded.
func (t *Torrent) Start() {
	t.m.Lock()
	defer t.m.Unlock()
	if t.closed {
		panic("torrent is closed")
	}
	if t.running {
		return
	}

	t.errC = make(chan error, 1)

	// keep list of peer addresses to connect
	pl := peerlist.New()
	t.workers.Start(pl)

	// get peers from tracker
	an := announcer.New(t.metainfo.Announce, t, t.data.Completed, pl, t.log)
	t.workers.Start(an)

	// manage peer connections
	pm := peermanager.New(t.port, pl, t.peerID, t.metainfo.Info.Hash, t.data, t.log)
	t.workers.Start(pm)

	// request missing pieces from peers
	do := downloader.New(t.data, pm.PeerMessages(), t.errC, t.log)
	t.workers.StartWithOnFinishHandler(do, func() { t.Stop() })

	// send requested blocks
	up := uploader.New()
	t.workers.Start(up)
}

// Stop downloading and uploading, disconnect all peers and close peer port.
func (t *Torrent) Stop() {
	t.m.Lock()
	defer t.m.Unlock()
	if t.closed {
		panic("torrent is closed")
	}
	if !t.running {
		return
	}
	t.workers.Stop()
}

// Close this torrent and release all resources.
func (t *Torrent) Close() error {
	t.m.Lock()
	defer t.m.Unlock()
	if t.closed {
		return nil
	}
	if t.running {
		t.Stop()
	}
	return t.data.Close()
}

// Port returns the port number that the client is listening.
func (t *Torrent) Port() int {
	return t.port
}

// BytesCompleted returns the number of bytes downlaoded and passed hash check.
func (t *Torrent) BytesCompleted() int64 {
	bf := t.data.Bitfield()
	sum := int64(bf.Count() * t.metainfo.Info.PieceLength)

	// Last piece usually not in full size.
	lastPiece := len(t.data.Pieces) - 1
	if bf.Test(uint32(lastPiece)) {
		sum -= int64(t.metainfo.Info.PieceLength)
		sum += int64(t.data.Pieces[lastPiece].Length)
	}
	return sum
}

// PeerID is unique per torrent.
func (t *Torrent) PeerID() [20]byte { return t.peerID }

// InfoHash identifies the torrent file that is being downloaded.
func (t *Torrent) InfoHash() [20]byte { return t.metainfo.Info.Hash }

// NotifyComplete returns a channel that is closed once all pieces are downloaded successfully.
func (t *Torrent) NotifyComplete() chan struct{} { return t.data.Completed }

// NotifyError returns a new channel for waiting download errors.
// When error is sent to the channel, torrent is stopped automatically.
func (t *Torrent) NotifyError() chan error { return t.errC }

// BytesDownloaded is the number of bytes downloaded from swarm.
//
// Because some pieces may be downloaded more than once, this number may be greater than BytesCompleted returns.
func (t *Torrent) BytesDownloaded() int64 { return t.BytesCompleted() } // TODO not the same thing

// BytesUploaded is the number of bytes uploaded to the swarm.
func (t *Torrent) BytesUploaded() int64 { return 0 } // TODO count uploaded bytes

// BytesLeft is the number of bytes that is needed to complete all missing pieces.
func (t *Torrent) BytesLeft() int64 { return t.BytesTotal() - t.BytesCompleted() }

// BytesTotal is the number of total bytes of files in torrent.
func (t *Torrent) BytesTotal() int64 { return t.metainfo.Info.TotalLength }
<commit_msg>chan direction<commit_after>package torrent

import (
	"crypto/rand"
	"errors"
	"io"
	"sync"

	"github.com/cenkalti/rain/internal/announcer"
	"github.com/cenkalti/rain/internal/downloader"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/internal/metainfo"
	"github.com/cenkalti/rain/internal/peerlist"
	"github.com/cenkalti/rain/internal/peermanager"
	"github.com/cenkalti/rain/internal/torrentdata"
	"github.com/cenkalti/rain/internal/uploader"
	"github.com/cenkalti/rain/internal/worker"
)

var (
	// Version of client. Set during build.
	Version = "0000" // zero means development version

	// http://www.bittorrent.org/beps/bep_0020.html
	peerIDPrefix = []byte("-RN" + Version + "-")
)

// Torrent connect to peers and downloads files from swarm.
type Torrent struct {
	peerID   [20]byte           // unique id per torrent
	metainfo *metainfo.MetaInfo // parsed torrent file
	data     *torrentdata.Data  // provides access to files on disk
	dest     string             // path of files on disk
	port     int                // listen for peer connections
	running  bool               // true after Start() is called
	closed   bool               // true after Close() is called
	m        sync.Mutex         // protects running and closed state
	errC     chan error         // downlaoder sends critical error to this channel
	workers  worker.Workers
	log      logger.Logger
}

// New returns a new torrent by reading a metainfo file.
//
// Files are read from disk. If there are existing files, hash check will be done.
//
// Returned torrent is in stopped state.
//
// Close must be called before discarding the torrent.
func New(r io.Reader, dest string, port int) (*Torrent, error) {
	if port <= 0 {
		return nil, errors.New("invalid port number")
	}
	m, err := metainfo.New(r)
	if err != nil {
		return nil, err
	}
	logName := m.Info.Name
	if len(logName) > 8 {
		logName = logName[:8]
	}
	var peerID [20]byte
	copy(peerID[:], peerIDPrefix)
	_, err = rand.Read(peerID[len(peerIDPrefix):]) // nolint: gosec
	if err != nil {
		return nil, err
	}
	data, err := torrentdata.New(m.Info, dest)
	if err != nil {
		return nil, err
	}
	err = data.Verify()
	if err != nil {
		return nil, err
	}
	return &Torrent{
		peerID:   peerID,
		metainfo: m,
		data:     data,
		dest:     dest,
		port:     port,
		log:      logger.New("download " + logName),
	}, nil
}

// Start listening peer port, accepting incoming peer connections and download missing pieces.
//
// Seeding continues after all files are donwloaded.
func (t *Torrent) Start() {
	t.m.Lock()
	defer t.m.Unlock()
	if t.closed {
		panic("torrent is closed")
	}
	if t.running {
		return
	}

	t.errC = make(chan error, 1)

	// keep list of peer addresses to connect
	pl := peerlist.New()
	t.workers.Start(pl)

	// get peers from tracker
	an := announcer.New(t.metainfo.Announce, t, t.data.Completed, pl, t.log)
	t.workers.Start(an)

	// manage peer connections
	pm := peermanager.New(t.port, pl, t.peerID, t.metainfo.Info.Hash, t.data, t.log)
	t.workers.Start(pm)

	// request missing pieces from peers
	do := downloader.New(t.data, pm.PeerMessages(), t.errC, t.log)
	t.workers.StartWithOnFinishHandler(do, func() { t.Stop() })

	// send requested blocks
	up := uploader.New()
	t.workers.Start(up)
}

// Stop downloading and uploading, disconnect all peers and close peer port.
func (t *Torrent) Stop() {
	t.m.Lock()
	defer t.m.Unlock()
	if t.closed {
		panic("torrent is closed")
	}
	if !t.running {
		return
	}
	t.workers.Stop()
}

// Close this torrent and release all resources.
func (t *Torrent) Close() error {
	t.m.Lock()
	defer t.m.Unlock()
	if t.closed {
		return nil
	}
	if t.running {
		t.Stop()
	}
	return t.data.Close()
}

// Port returns the port number that the client is listening.
func (t *Torrent) Port() int {
	return t.port
}

// BytesCompleted returns the number of bytes downlaoded and passed hash check.
func (t *Torrent) BytesCompleted() int64 {
	bf := t.data.Bitfield()
	sum := int64(bf.Count() * t.metainfo.Info.PieceLength)

	// Last piece usually not in full size.
	lastPiece := len(t.data.Pieces) - 1
	if bf.Test(uint32(lastPiece)) {
		sum -= int64(t.metainfo.Info.PieceLength)
		sum += int64(t.data.Pieces[lastPiece].Length)
	}
	return sum
}

// PeerID is unique per torrent.
func (t *Torrent) PeerID() [20]byte { return t.peerID }

// InfoHash identifies the torrent file that is being downloaded.
func (t *Torrent) InfoHash() [20]byte { return t.metainfo.Info.Hash }

// NotifyComplete returns a channel that is closed once all pieces are downloaded successfully.
func (t *Torrent) NotifyComplete() <-chan struct{} { return t.data.Completed }

// NotifyError returns a new channel for waiting download errors.
// When error is sent to the channel, torrent is stopped automatically.
func (t *Torrent) NotifyError() <-chan error { return t.errC }

// BytesDownloaded is the number of bytes downloaded from swarm.
//
// Because some pieces may be downloaded more than once, this number may be greater than BytesCompleted returns.
func (t *Torrent) BytesDownloaded() int64 { return t.BytesCompleted() } // TODO not the same thing

// BytesUploaded is the number of bytes uploaded to the swarm.
func (t *Torrent) BytesUploaded() int64 { return 0 } // TODO count uploaded bytes

// BytesLeft is the number of bytes that is needed to complete all missing pieces.
func (t *Torrent) BytesLeft() int64 { return t.BytesTotal() - t.BytesCompleted() }

// BytesTotal is the number of total bytes of files in torrent.
func (t *Torrent) BytesTotal() int64 { return t.metainfo.Info.TotalLength }
<|endoftext|>


<commit_before>// Copyright 2014, Truveris Inc. All Rights Reserved.
// Use of this source code is governed by the ISC license in the LICENSE file.

package ygor

import (
	"log"
	"os"
	"os/signal"
	"runtime"
	"syscall"
)

func WaitForTraceRequest() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGUSR1)

	for _ = range ch {
		log.Printf("Received USR1 signal, printing stack trace:")
		buf := make([]byte, 4096)
		runtime.Stack(buf, true)
		log.Printf("%s", buf)
	}
}
<commit_msg>You need more than 4kB of stack trace.<commit_after>// Copyright 2014, Truveris Inc. All Rights Reserved.
// Use of this source code is governed by the ISC license in the LICENSE file.

package ygor

import (
	"log"
	"os"
	"os/signal"
	"runtime"
	"syscall"
)

func WaitForTraceRequest() {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGUSR1)

	for _ = range ch {
		log.Printf("Received USR1 signal, printing stack trace:")
		buf := make([]byte, 40960)
		i := runtime.Stack(buf, true)
		log.Printf("%s", buf[:i])
	}
}
<|endoftext|>


<commit_before>package ts

import (
	"testing"
	"regifted/ts"
)

func TestReadVideo(t *testing.T) {
	in := []byte{2, 5, 6, 3, 4, 5, 6, 5, 4, 3, 4, 0, 0, 0, 1, 8, 8, 4, 6, 5, 8, 3, 9, 2, 0, 4, 9, 5, 8, 0, 0, 0, 1, 9, 8, 2, 7, 4, 5, 2, 7, 4, 8, 9, 3}
	out := []byte{ 2, 5, 6, 3, 4, 5, 6, 5, 4, 3, 4, 8, 8, 4, 6, 5, 8, 3, 9, 2, 0, 4, 9, 5, 8, 9, 8, 2, 7, 4, 5, 2, 7, 4, 8, 9, 3 }

	n := new(Nal)

	if x := n.readVideo(in); x != out {
		t.Fail()
	}

}<commit_msg>temp commented out because it errors<commit_after>package ts

// import (
// 	"testing"
// )

// func TestReadVideo(t *testing.T) {
// 	in := []byte{2, 5, 6, 3, 4, 5, 6, 5, 4, 3, 4, 0, 0, 0, 1, 8, 8, 4, 6, 5, 8, 3, 9, 2, 0, 4, 9, 5, 8, 0, 0, 0, 1, 9, 8, 2, 7, 4, 5, 2, 7, 4, 8, 9, 3}
// 	out := []byte{ 2, 5, 6, 3, 4, 5, 6, 5, 4, 3, 4, 8, 8, 4, 6, 5, 8, 3, 9, 2, 0, 4, 9, 5, 8, 9, 8, 2, 7, 4, 5, 2, 7, 4, 8, 9, 3 }

// 	n := new(Nal)

// 	if x := n.readVideo(in); x != out {
// 		t.Fail()
// 	}
// }
<|endoftext|>


<commit_before>// Copyright 2019 Istio 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.

// packages used for load balancer setting
package loadbalancer

import (
	"math"
	"sort"

	apiv2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
	core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
	"github.com/golang/protobuf/ptypes/wrappers"

	"istio.io/api/networking/v1alpha3"
	"istio.io/istio/pilot/pkg/networking/util"
)

func GetLocalityLbSetting(
	mesh *v1alpha3.LocalityLoadBalancerSetting,
	destrule *v1alpha3.LocalityLoadBalancerSetting,
) *v1alpha3.LocalityLoadBalancerSetting {
	// Locality lb is enabled if its defined in mesh config
	enabled := mesh != nil
	// Unless we explicitly override this in destination rule
	if destrule != nil && destrule.Enabled != nil {
		enabled = destrule.Enabled.GetValue()
	}
	if !enabled {
		return nil
	}

	// Destination Rule overrides mesh config. If its defined, use that
	if destrule != nil {
		return destrule
	}
	// Otherwise fall back to mesh default
	return mesh
}

func ApplyLocalityLBSetting(
	locality *core.Locality,
	loadAssignment *apiv2.ClusterLoadAssignment,
	localityLB *v1alpha3.LocalityLoadBalancerSetting,
	enableFailover bool,
) {
	if locality == nil || loadAssignment == nil {
		return
	}

	// one of Distribute or Failover settings can be applied.
	if localityLB.GetDistribute() != nil {
		applyLocalityWeight(locality, loadAssignment, localityLB.GetDistribute())
	} else if enableFailover {
		// Failover needs outlier detection, otherwise Envoy will never drop down to a lower priority.
		applyLocalityFailover(locality, loadAssignment, localityLB.GetFailover())
	}
}

// set locality loadbalancing weight
func applyLocalityWeight(
	locality *core.Locality,
	loadAssignment *apiv2.ClusterLoadAssignment,
	distribute []*v1alpha3.LocalityLoadBalancerSetting_Distribute) {
	if distribute == nil {
		return
	}

	// Support Locality weighted load balancing
	// (https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/load_balancing/locality_weight.html)
	// by providing weights in LocalityLbEndpoints via load_balancing_weight.
	// By setting weights across different localities, it can allow
	// Envoy to weight assignments across different zones and geographical locations.
	for _, localityWeightSetting := range distribute {
		if localityWeightSetting != nil &&
			util.LocalityMatch(locality, localityWeightSetting.From) {
			misMatched := map[int]struct{}{}
			for i := range loadAssignment.Endpoints {
				misMatched[i] = struct{}{}
			}
			for locality, weight := range localityWeightSetting.To {
				// index -> original weight
				destLocMap := map[int]uint32{}
				totalWeight := uint32(0)
				for i, ep := range loadAssignment.Endpoints {
					if _, exist := misMatched[i]; exist {
						if util.LocalityMatch(ep.Locality, locality) {
							delete(misMatched, i)
							if ep.LoadBalancingWeight != nil {
								destLocMap[i] = ep.LoadBalancingWeight.Value
							} else {
								destLocMap[i] = 1
							}
							totalWeight += destLocMap[i]
						}
					}
				}
				// in case wildcard dest matching multi groups of endpoints
				// the load balancing weight for a locality is divided by the sum of the weights of all localities
				for index, originalWeight := range destLocMap {
					weight := float64(originalWeight*weight) / float64(totalWeight)
					loadAssignment.Endpoints[index].LoadBalancingWeight = &wrappers.UInt32Value{
						Value: uint32(math.Ceil(weight)),
					}
				}
			}

			// remove groups of endpoints in a locality that miss matched
			for i := range misMatched {
				loadAssignment.Endpoints[i].LbEndpoints = nil
			}
			break
		}
	}
}

// set locality loadbalancing priority
func applyLocalityFailover(
	locality *core.Locality,
	loadAssignment *apiv2.ClusterLoadAssignment,
	failover []*v1alpha3.LocalityLoadBalancerSetting_Failover) {
	// key is priority, value is the index of the LocalityLbEndpoints in ClusterLoadAssignment
	priorityMap := map[int][]int{}

	// 1. calculate the LocalityLbEndpoints.Priority compared with proxy locality
	for i, localityEndpoint := range loadAssignment.Endpoints {
		// if region/zone/subZone all match, the priority is 0.
		// if region/zone match, the priority is 1.
		// if region matches, the priority is 2.
		// if locality not match, the priority is 3.
		priority := util.LbPriority(locality, localityEndpoint.Locality)
		// region not match, apply failover settings when specified
		// update localityLbEndpoints' priority to 4 if failover not match
		if priority == 3 {
			for _, failoverSetting := range failover {
				if failoverSetting.From == locality.Region {
					if localityEndpoint.Locality == nil || localityEndpoint.Locality.Region != failoverSetting.To {
						priority = 4
					}
					break
				}
			}
		}
		loadAssignment.Endpoints[i].Priority = uint32(priority)
		priorityMap[priority] = append(priorityMap[priority], i)
	}

	// since Priorities should range from 0 (highest) to N (lowest) without skipping.
	// 2. adjust the priorities in order
	// 2.1 sort all priorities in increasing order.
	priorities := []int{}
	for priority := range priorityMap {
		priorities = append(priorities, priority)
	}
	sort.Ints(priorities)
	// 2.2 adjust LocalityLbEndpoints priority
	// if the index and value of priorities array is not equal.
	for i, priority := range priorities {
		if i != priority {
			// the LocalityLbEndpoints index in ClusterLoadAssignment.Endpoints
			for _, index := range priorityMap[priority] {
				loadAssignment.Endpoints[index].Priority = uint32(i)
			}
		}
	}

}
<commit_msg>set load balancing weight only if it is greater than zero (#21631)<commit_after>// Copyright 2019 Istio 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.

// packages used for load balancer setting
package loadbalancer

import (
	"math"
	"sort"

	apiv2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
	core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
	"github.com/golang/protobuf/ptypes/wrappers"

	"istio.io/api/networking/v1alpha3"
	"istio.io/istio/pilot/pkg/networking/util"
)

func GetLocalityLbSetting(
	mesh *v1alpha3.LocalityLoadBalancerSetting,
	destrule *v1alpha3.LocalityLoadBalancerSetting,
) *v1alpha3.LocalityLoadBalancerSetting {
	// Locality lb is enabled if its defined in mesh config
	enabled := mesh != nil
	// Unless we explicitly override this in destination rule
	if destrule != nil && destrule.Enabled != nil {
		enabled = destrule.Enabled.GetValue()
	}
	if !enabled {
		return nil
	}

	// Destination Rule overrides mesh config. If its defined, use that
	if destrule != nil {
		return destrule
	}
	// Otherwise fall back to mesh default
	return mesh
}

func ApplyLocalityLBSetting(
	locality *core.Locality,
	loadAssignment *apiv2.ClusterLoadAssignment,
	localityLB *v1alpha3.LocalityLoadBalancerSetting,
	enableFailover bool,
) {
	if locality == nil || loadAssignment == nil {
		return
	}

	// one of Distribute or Failover settings can be applied.
	if localityLB.GetDistribute() != nil {
		applyLocalityWeight(locality, loadAssignment, localityLB.GetDistribute())
	} else if enableFailover {
		// Failover needs outlier detection, otherwise Envoy will never drop down to a lower priority.
		applyLocalityFailover(locality, loadAssignment, localityLB.GetFailover())
	}
}

// set locality loadbalancing weight
func applyLocalityWeight(
	locality *core.Locality,
	loadAssignment *apiv2.ClusterLoadAssignment,
	distribute []*v1alpha3.LocalityLoadBalancerSetting_Distribute) {
	if distribute == nil {
		return
	}

	// Support Locality weighted load balancing
	// (https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/load_balancing/locality_weight.html)
	// by providing weights in LocalityLbEndpoints via load_balancing_weight.
	// By setting weights across different localities, it can allow
	// Envoy to weight assignments across different zones and geographical locations.
	for _, localityWeightSetting := range distribute {
		if localityWeightSetting != nil &&
			util.LocalityMatch(locality, localityWeightSetting.From) {
			misMatched := map[int]struct{}{}
			for i := range loadAssignment.Endpoints {
				misMatched[i] = struct{}{}
			}
			for locality, weight := range localityWeightSetting.To {
				// index -> original weight
				destLocMap := map[int]uint32{}
				totalWeight := uint32(0)
				for i, ep := range loadAssignment.Endpoints {
					if _, exist := misMatched[i]; exist {
						if util.LocalityMatch(ep.Locality, locality) {
							delete(misMatched, i)
							if ep.LoadBalancingWeight != nil {
								destLocMap[i] = ep.LoadBalancingWeight.Value
							} else {
								destLocMap[i] = 1
							}
							totalWeight += destLocMap[i]
						}
					}
				}
				// in case wildcard dest matching multi groups of endpoints
				// the load balancing weight for a locality is divided by the sum of the weights of all localities
				for index, originalWeight := range destLocMap {
					destWeight := float64(originalWeight*weight) / float64(totalWeight)
					if destWeight > 0 {
						loadAssignment.Endpoints[index].LoadBalancingWeight = &wrappers.UInt32Value{
							Value: uint32(math.Ceil(destWeight)),
						}
					}
				}
			}

			// remove groups of endpoints in a locality that miss matched
			for i := range misMatched {
				loadAssignment.Endpoints[i].LbEndpoints = nil
			}
			break
		}
	}
}

// set locality loadbalancing priority
func applyLocalityFailover(
	locality *core.Locality,
	loadAssignment *apiv2.ClusterLoadAssignment,
	failover []*v1alpha3.LocalityLoadBalancerSetting_Failover) {
	// key is priority, value is the index of the LocalityLbEndpoints in ClusterLoadAssignment
	priorityMap := map[int][]int{}

	// 1. calculate the LocalityLbEndpoints.Priority compared with proxy locality
	for i, localityEndpoint := range loadAssignment.Endpoints {
		// if region/zone/subZone all match, the priority is 0.
		// if region/zone match, the priority is 1.
		// if region matches, the priority is 2.
		// if locality not match, the priority is 3.
		priority := util.LbPriority(locality, localityEndpoint.Locality)
		// region not match, apply failover settings when specified
		// update localityLbEndpoints' priority to 4 if failover not match
		if priority == 3 {
			for _, failoverSetting := range failover {
				if failoverSetting.From == locality.Region {
					if localityEndpoint.Locality == nil || localityEndpoint.Locality.Region != failoverSetting.To {
						priority = 4
					}
					break
				}
			}
		}
		loadAssignment.Endpoints[i].Priority = uint32(priority)
		priorityMap[priority] = append(priorityMap[priority], i)
	}

	// since Priorities should range from 0 (highest) to N (lowest) without skipping.
	// 2. adjust the priorities in order
	// 2.1 sort all priorities in increasing order.
	priorities := []int{}
	for priority := range priorityMap {
		priorities = append(priorities, priority)
	}
	sort.Ints(priorities)
	// 2.2 adjust LocalityLbEndpoints priority
	// if the index and value of priorities array is not equal.
	for i, priority := range priorities {
		if i != priority {
			// the LocalityLbEndpoints index in ClusterLoadAssignment.Endpoints
			for _, index := range priorityMap[priority] {
				loadAssignment.Endpoints[index].Priority = uint32(i)
			}
		}
	}

}
<|endoftext|>


<commit_before>package ecies

import (
	"crypto/cipher"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/hmac"
	"crypto/subtle"
	"fmt"
	"hash"
	"io"
	"math/big"
)

var (
	ErrImport                     = fmt.Errorf("ecies: failed to import key")
	ErrInvalidCurve               = fmt.Errorf("ecies: invalid elliptic curve")
	ErrInvalidParams              = fmt.Errorf("ecies: invalid ECIES parameters")
	ErrInvalidPublicKey           = fmt.Errorf("ecies: invalid public key")
	ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity")
	ErrSharedKeyTooBig            = fmt.Errorf("ecies: shared key params are too big")
)

// PublicKey is a representation of an elliptic curve public key.
type PublicKey struct {
	X *big.Int
	Y *big.Int
	elliptic.Curve
	Params *ECIESParams
}

// Export an ECIES public key as an ECDSA public key.
func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey {
	return &ecdsa.PublicKey{pub.Curve, pub.X, pub.Y}
}

// Import an ECDSA public key as an ECIES public key.
func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey {
	return &PublicKey{
		X:      pub.X,
		Y:      pub.Y,
		Curve:  pub.Curve,
		Params: ParamsFromCurve(pub.Curve),
	}
}

// PrivateKey is a representation of an elliptic curve private key.
type PrivateKey struct {
	PublicKey
	D *big.Int
}

// Export an ECIES private key as an ECDSA private key.
func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey {
	pub := &prv.PublicKey
	pubECDSA := pub.ExportECDSA()
	return &ecdsa.PrivateKey{*pubECDSA, prv.D}
}

// Import an ECDSA private key as an ECIES private key.
func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
	pub := ImportECDSAPublic(&prv.PublicKey)
	return &PrivateKey{*pub, prv.D}
}

// Generate an elliptic curve public / private keypair. If params is nil,
// the recommended default paramters for the key will be chosen.
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
	pb, x, y, err := elliptic.GenerateKey(curve, rand)
	if err != nil {
		return
	}
	prv = new(PrivateKey)
	prv.PublicKey.X = x
	prv.PublicKey.Y = y
	prv.PublicKey.Curve = curve
	prv.D = new(big.Int).SetBytes(pb)
	if params == nil {
		params = ParamsFromCurve(curve)
	}
	prv.PublicKey.Params = params
	return
}

// MaxSharedKeyLength returns the maximum length of the shared key the
// public key can produce.
func MaxSharedKeyLength(pub *PublicKey) int {
	return (pub.Curve.Params().BitSize + 7) / 8
}

// ECDH key agreement method used to establish secret keys for encryption.
func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
	if prv.PublicKey.Curve != pub.Curve {
		return nil, ErrInvalidCurve
	}
	if skLen+macLen > MaxSharedKeyLength(pub) {
		return nil, ErrSharedKeyTooBig
	}
	x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes())
	if x == nil {
		return nil, ErrSharedKeyIsPointAtInfinity
	}

	sk = make([]byte, skLen+macLen)
	skBytes := x.Bytes()
	copy(sk[len(sk)-len(skBytes):], skBytes)
	return sk, nil
}

var (
	ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data")
	ErrSharedTooLong  = fmt.Errorf("ecies: shared secret is too long")
	ErrInvalidMessage = fmt.Errorf("ecies: invalid message")
)

var (
	big2To32   = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil)
	big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1))
)

func incCounter(ctr []byte) {
	if ctr[3]++; ctr[3] != 0 {
		return
	} else if ctr[2]++; ctr[2] != 0 {
		return
	} else if ctr[1]++; ctr[1] != 0 {
		return
	} else if ctr[0]++; ctr[0] != 0 {
		return
	}
	return
}

// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).
func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
	if s1 == nil {
		s1 = make([]byte, 0)
	}

	reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8)
	if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 {
		fmt.Println(big2To32M1)
		return nil, ErrKeyDataTooLong
	}

	counter := []byte{0, 0, 0, 1}
	k = make([]byte, 0)

	for i := 0; i <= reps; i++ {
		hash.Write(counter)
		hash.Write(z)
		hash.Write(s1)
		k = append(k, hash.Sum(nil)...)
		hash.Reset()
		incCounter(counter)
	}

	k = k[:kdLen]
	return
}

// messageTag computes the MAC of a message (called the tag) as per
// SEC 1, 3.5.
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
	if shared == nil {
		shared = make([]byte, 0)
	}
	mac := hmac.New(hash, km)
	mac.Write(msg)
	tag := mac.Sum(nil)
	return tag
}

// Generate an initialisation vector for CTR mode.
func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) {
	iv = make([]byte, params.BlockSize)
	_, err = io.ReadFull(rand, iv)
	return
}

// symEncrypt carries out CTR encryption using the block cipher specified in the
// parameters.
func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) {
	c, err := params.Cipher(key)
	if err != nil {
		return
	}

	iv, err := generateIV(params, rand)
	if err != nil {
		return
	}
	ctr := cipher.NewCTR(c, iv)

	ct = make([]byte, len(m)+params.BlockSize)
	copy(ct, iv)
	ctr.XORKeyStream(ct[params.BlockSize:], m)
	return
}

// symDecrypt carries out CTR decryption using the block cipher specified in
// the parameters
func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, err error) {
	c, err := params.Cipher(key)
	if err != nil {
		return
	}

	ctr := cipher.NewCTR(c, ct[:params.BlockSize])

	m = make([]byte, len(ct)-params.BlockSize)
	ctr.XORKeyStream(m, ct[params.BlockSize:])
	return
}

// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
// the shared information parameters aren't being used, they should be
// nil.
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
	params := pub.Params
	if params == nil {
		if params = ParamsFromCurve(pub.Curve); params == nil {
			err = ErrUnsupportedECIESParameters
			return
		}
	}
	R, err := GenerateKey(rand, pub.Curve, params)
	if err != nil {
		return
	}

	hash := params.Hash()
	z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen)
	if err != nil {
		return
	}
	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
	if err != nil {
		return
	}
	Ke := K[:params.KeyLen]
	Km := K[params.KeyLen:]
	hash.Write(Km)
	Km = hash.Sum(nil)
	hash.Reset()

	em, err := symEncrypt(rand, params, Ke, m)
	if err != nil || len(em) <= params.BlockSize {
		return
	}

	d := messageTag(params.Hash, Km, em, s2)

	Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
	ct = make([]byte, len(Rb)+len(em)+len(d))
	copy(ct, Rb)
	copy(ct[len(Rb):], em)
	copy(ct[len(Rb)+len(em):], d)
	return
}

// Decrypt decrypts an ECIES ciphertext.
func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) {
	if c == nil || len(c) == 0 {
		err = ErrInvalidMessage
		return
	}
	params := prv.PublicKey.Params
	if params == nil {
		if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil {
			err = ErrUnsupportedECIESParameters
			return
		}
	}
	hash := params.Hash()

	var (
		rLen   int
		hLen   int = hash.Size()
		mStart int
		mEnd   int
	)

	switch c[0] {
	case 2, 3, 4:
		rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4)
		if len(c) < (rLen + hLen + 1) {
			err = ErrInvalidMessage
			return
		}
	default:
		err = ErrInvalidPublicKey
		return
	}

	mStart = rLen
	mEnd = len(c) - hLen

	R := new(PublicKey)
	R.Curve = prv.PublicKey.Curve
	R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
	if R.X == nil {
		err = ErrInvalidPublicKey
		return
	}

	z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
	if err != nil {
		return
	}

	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
	if err != nil {
		return
	}

	Ke := K[:params.KeyLen]
	Km := K[params.KeyLen:]
	hash.Write(Km)
	Km = hash.Sum(nil)
	hash.Reset()

	d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
	if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
		err = ErrInvalidMessage
		return
	}

	m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd])
	return
}
<commit_msg>Add IsOnCurve check to EC unmarshalling in ECIES decryption<commit_after>package ecies

import (
	"crypto/cipher"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/hmac"
	"crypto/subtle"
	"fmt"
	"hash"
	"io"
	"math/big"
)

var (
	ErrImport                     = fmt.Errorf("ecies: failed to import key")
	ErrInvalidCurve               = fmt.Errorf("ecies: invalid elliptic curve")
	ErrInvalidParams              = fmt.Errorf("ecies: invalid ECIES parameters")
	ErrInvalidPublicKey           = fmt.Errorf("ecies: invalid public key")
	ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity")
	ErrSharedKeyTooBig            = fmt.Errorf("ecies: shared key params are too big")
)

// PublicKey is a representation of an elliptic curve public key.
type PublicKey struct {
	X *big.Int
	Y *big.Int
	elliptic.Curve
	Params *ECIESParams
}

// Export an ECIES public key as an ECDSA public key.
func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey {
	return &ecdsa.PublicKey{pub.Curve, pub.X, pub.Y}
}

// Import an ECDSA public key as an ECIES public key.
func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey {
	return &PublicKey{
		X:      pub.X,
		Y:      pub.Y,
		Curve:  pub.Curve,
		Params: ParamsFromCurve(pub.Curve),
	}
}

// PrivateKey is a representation of an elliptic curve private key.
type PrivateKey struct {
	PublicKey
	D *big.Int
}

// Export an ECIES private key as an ECDSA private key.
func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey {
	pub := &prv.PublicKey
	pubECDSA := pub.ExportECDSA()
	return &ecdsa.PrivateKey{*pubECDSA, prv.D}
}

// Import an ECDSA private key as an ECIES private key.
func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
	pub := ImportECDSAPublic(&prv.PublicKey)
	return &PrivateKey{*pub, prv.D}
}

// Generate an elliptic curve public / private keypair. If params is nil,
// the recommended default paramters for the key will be chosen.
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
	pb, x, y, err := elliptic.GenerateKey(curve, rand)
	if err != nil {
		return
	}
	prv = new(PrivateKey)
	prv.PublicKey.X = x
	prv.PublicKey.Y = y
	prv.PublicKey.Curve = curve
	prv.D = new(big.Int).SetBytes(pb)
	if params == nil {
		params = ParamsFromCurve(curve)
	}
	prv.PublicKey.Params = params
	return
}

// MaxSharedKeyLength returns the maximum length of the shared key the
// public key can produce.
func MaxSharedKeyLength(pub *PublicKey) int {
	return (pub.Curve.Params().BitSize + 7) / 8
}

// ECDH key agreement method used to establish secret keys for encryption.
func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) {
	if prv.PublicKey.Curve != pub.Curve {
		return nil, ErrInvalidCurve
	}
	if skLen+macLen > MaxSharedKeyLength(pub) {
		return nil, ErrSharedKeyTooBig
	}
	x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes())
	if x == nil {
		return nil, ErrSharedKeyIsPointAtInfinity
	}

	sk = make([]byte, skLen+macLen)
	skBytes := x.Bytes()
	copy(sk[len(sk)-len(skBytes):], skBytes)
	return sk, nil
}

var (
	ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data")
	ErrSharedTooLong  = fmt.Errorf("ecies: shared secret is too long")
	ErrInvalidMessage = fmt.Errorf("ecies: invalid message")
)

var (
	big2To32   = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil)
	big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1))
)

func incCounter(ctr []byte) {
	if ctr[3]++; ctr[3] != 0 {
		return
	} else if ctr[2]++; ctr[2] != 0 {
		return
	} else if ctr[1]++; ctr[1] != 0 {
		return
	} else if ctr[0]++; ctr[0] != 0 {
		return
	}
	return
}

// NIST SP 800-56 Concatenation Key Derivation Function (see section 5.8.1).
func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) {
	if s1 == nil {
		s1 = make([]byte, 0)
	}

	reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8)
	if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 {
		fmt.Println(big2To32M1)
		return nil, ErrKeyDataTooLong
	}

	counter := []byte{0, 0, 0, 1}
	k = make([]byte, 0)

	for i := 0; i <= reps; i++ {
		hash.Write(counter)
		hash.Write(z)
		hash.Write(s1)
		k = append(k, hash.Sum(nil)...)
		hash.Reset()
		incCounter(counter)
	}

	k = k[:kdLen]
	return
}

// messageTag computes the MAC of a message (called the tag) as per
// SEC 1, 3.5.
func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte {
	if shared == nil {
		shared = make([]byte, 0)
	}
	mac := hmac.New(hash, km)
	mac.Write(msg)
	tag := mac.Sum(nil)
	return tag
}

// Generate an initialisation vector for CTR mode.
func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) {
	iv = make([]byte, params.BlockSize)
	_, err = io.ReadFull(rand, iv)
	return
}

// symEncrypt carries out CTR encryption using the block cipher specified in the
// parameters.
func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) {
	c, err := params.Cipher(key)
	if err != nil {
		return
	}

	iv, err := generateIV(params, rand)
	if err != nil {
		return
	}
	ctr := cipher.NewCTR(c, iv)

	ct = make([]byte, len(m)+params.BlockSize)
	copy(ct, iv)
	ctr.XORKeyStream(ct[params.BlockSize:], m)
	return
}

// symDecrypt carries out CTR decryption using the block cipher specified in
// the parameters
func symDecrypt(rand io.Reader, params *ECIESParams, key, ct []byte) (m []byte, err error) {
	c, err := params.Cipher(key)
	if err != nil {
		return
	}

	ctr := cipher.NewCTR(c, ct[:params.BlockSize])

	m = make([]byte, len(ct)-params.BlockSize)
	ctr.XORKeyStream(m, ct[params.BlockSize:])
	return
}

// Encrypt encrypts a message using ECIES as specified in SEC 1, 5.1. If
// the shared information parameters aren't being used, they should be
// nil.
func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) {
	params := pub.Params
	if params == nil {
		if params = ParamsFromCurve(pub.Curve); params == nil {
			err = ErrUnsupportedECIESParameters
			return
		}
	}
	R, err := GenerateKey(rand, pub.Curve, params)
	if err != nil {
		return
	}

	hash := params.Hash()
	z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen)
	if err != nil {
		return
	}
	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
	if err != nil {
		return
	}
	Ke := K[:params.KeyLen]
	Km := K[params.KeyLen:]
	hash.Write(Km)
	Km = hash.Sum(nil)
	hash.Reset()

	em, err := symEncrypt(rand, params, Ke, m)
	if err != nil || len(em) <= params.BlockSize {
		return
	}

	d := messageTag(params.Hash, Km, em, s2)

	Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
	ct = make([]byte, len(Rb)+len(em)+len(d))
	copy(ct, Rb)
	copy(ct[len(Rb):], em)
	copy(ct[len(Rb)+len(em):], d)
	return
}

// Decrypt decrypts an ECIES ciphertext.
func (prv *PrivateKey) Decrypt(rand io.Reader, c, s1, s2 []byte) (m []byte, err error) {
	if c == nil || len(c) == 0 {
		err = ErrInvalidMessage
		return
	}
	params := prv.PublicKey.Params
	if params == nil {
		if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil {
			err = ErrUnsupportedECIESParameters
			return
		}
	}
	hash := params.Hash()

	var (
		rLen   int
		hLen   int = hash.Size()
		mStart int
		mEnd   int
	)

	switch c[0] {
	case 2, 3, 4:
		rLen = ((prv.PublicKey.Curve.Params().BitSize + 7) / 4)
		if len(c) < (rLen + hLen + 1) {
			err = ErrInvalidMessage
			return
		}
	default:
		err = ErrInvalidPublicKey
		return
	}

	mStart = rLen
	mEnd = len(c) - hLen

	R := new(PublicKey)
	R.Curve = prv.PublicKey.Curve
	R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
	if R.X == nil {
		err = ErrInvalidPublicKey
		return
	}
	if !R.Curve.IsOnCurve(R.X, R.Y) {
		err = ErrInvalidCurve
		return
	}

	z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
	if err != nil {
		return
	}

	K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen)
	if err != nil {
		return
	}

	Ke := K[:params.KeyLen]
	Km := K[params.KeyLen:]
	hash.Write(Km)
	Km = hash.Sum(nil)
	hash.Reset()

	d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
	if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
		err = ErrInvalidMessage
		return
	}

	m, err = symDecrypt(rand, params, Ke, c[mStart:mEnd])
	return
}
<|endoftext|>


<commit_before>package melrose

import "time"

type Playable interface {
	Play(Player, time.Duration)
}

type Player interface {
	PlayNote(Note, time.Duration)
	PlaySequence(Sequence, singleNoteDuration time.Duration)
}
<commit_msg>Fix typo in Player interface<commit_after>package melrose

import "time"

type Playable interface {
	Play(Player, time.Duration)
}

type Player interface {
	PlayNote(Note, time.Duration)
	PlaySequence(Sequence, time.Duration)
}
<|endoftext|>


<commit_before>package sort

func sortColors(nums []int) {
	return
}
<commit_msg>solve 74 use counting sort<commit_after>package sort

func sortColors(nums []int) {
	useCountSort(nums)
}

// useCountSort time complexity O(N), space complexity O(1)
func useCountSort(nums []int) {
	n := len(nums)
	if n <= 1 {
		return
	}
	counts := [3]int{}
	for _, num := range nums {
		counts[num]++
	}
	prev := 0
	for i, count := range counts {
		if count != 0 {
			for j := prev; j < prev+count; j++ {
				nums[j] = i
			}
		}
		prev += count
	}
}
<|endoftext|>


<commit_before>package treap

type Treap struct {
	compare Compare
	root    *node
}

// Compare returns an integer comparing the two items
// lexicographically. The result will be 0 if a==b, -1 if a < b, and
// +1 if a > b.
type Compare func(a, b Item) int

// Key and Item can be anything.
type Item interface{}

type node struct {
	item     Item
	priority int
	left     *node
	right    *node
}

func NewTreap(c Compare) *Treap {
	return &Treap{compare: c, root: nil}
}

func (t *Treap) Get(target Item) Item {
	if t.root == nil {
		return nil
	}
	n := t.root
	for {
		if n == nil {
			break
		}
		c := t.compare(target, n.item)
		if c < 0 {
			n = n.left
		} else if c > 0 {
			n = n.right
		} else {
			return n.item
		}
	}
	return nil
}

func (t *Treap) Upsert(item Item, itemPriority int) *Treap {
	r := t.union(t.root, &node{item: item, priority: itemPriority})
	return &Treap{compare: t.compare, root: r}
}

func (t *Treap) union(this *node, that *node) *node {
	if this == nil {
		return that
	}
	if that == nil {
		return this
	}
	if this.priority > that.priority {
		left, middle, right := t.split(that, this.item)
		if middle == nil {
			return &node{
				item:     this.item,
				priority: this.priority,
				left:     t.union(this.left, left),
				right:    t.union(this.right, right),
			}
		}
		return &node{
			item:     middle.item,
			priority: middle.priority,
			left:     t.union(this.left, left),
			right:    t.union(this.right, right),
		}
	}
	// We don't use middle because that has precendence.
	left, _, right := t.split(this, that.item)
	return &node{
		item:     that.item,
		priority: that.priority,
		left:     t.union(left, that.left),
		right:    t.union(right, that.right),
	}
}

// Splits a treap into two treaps based on a split item "s".
// The result tuple-3 means (left, X, right), where X is either...
// nil - meaning the item s was not in the original treap.
// non-null - returning the node that had item s.
// The tuple-3's left result has items < s,
// and the tuple-3's right result has items > s.
func (t *Treap) split(n *node, s Item) (*node, *node, *node) {
	if n == nil {
		return nil, nil, nil
	}
	c := t.compare(s, n.item)
	if c == 0 {
		return n.left, n, n.right
	}
	if c < 0 {
		left, middle, right := t.split(n.left, s)
		return left, middle, &node{
			item:     n.item,
			priority: n.priority,
			left:     right,
			right:    n.right,
		}
	}
	left, middle, right := t.split(n.right, s)
	return &node{
		item:     n.item,
		priority: n.priority,
		left:     n.left,
		right:    left,
	}, middle, right
}
<commit_msg>Update comment.<commit_after>package treap

type Treap struct {
	compare Compare
	root    *node
}

// Compare returns an integer comparing the two items
// lexicographically. The result will be 0 if a==b, -1 if a < b, and
// +1 if a > b.
type Compare func(a, b Item) int

// Key and Item can be anything.
type Item interface{}

type node struct {
	item     Item
	priority int
	left     *node
	right    *node
}

func NewTreap(c Compare) *Treap {
	return &Treap{compare: c, root: nil}
}

func (t *Treap) Get(target Item) Item {
	if t.root == nil {
		return nil
	}
	n := t.root
	for {
		if n == nil {
			break
		}
		c := t.compare(target, n.item)
		if c < 0 {
			n = n.left
		} else if c > 0 {
			n = n.right
		} else {
			return n.item
		}
	}
	return nil
}

func (t *Treap) Upsert(item Item, itemPriority int) *Treap {
	r := t.union(t.root, &node{item: item, priority: itemPriority})
	return &Treap{compare: t.compare, root: r}
}

func (t *Treap) union(this *node, that *node) *node {
	if this == nil {
		return that
	}
	if that == nil {
		return this
	}
	if this.priority > that.priority {
		left, middle, right := t.split(that, this.item)
		if middle == nil {
			return &node{
				item:     this.item,
				priority: this.priority,
				left:     t.union(this.left, left),
				right:    t.union(this.right, right),
			}
		}
		return &node{
			item:     middle.item,
			priority: middle.priority,
			left:     t.union(this.left, left),
			right:    t.union(this.right, right),
		}
	}
	// We don't use middle because the "that" has precendence.
	left, _, right := t.split(this, that.item)
	return &node{
		item:     that.item,
		priority: that.priority,
		left:     t.union(left, that.left),
		right:    t.union(right, that.right),
	}
}

// Splits a treap into two treaps based on a split item "s".
// The result tuple-3 means (left, X, right), where X is either...
// nil - meaning the item s was not in the original treap.
// non-null - returning the node that had item s.
// The tuple-3's left result has items < s,
// and the tuple-3's right result has items > s.
func (t *Treap) split(n *node, s Item) (*node, *node, *node) {
	if n == nil {
		return nil, nil, nil
	}
	c := t.compare(s, n.item)
	if c == 0 {
		return n.left, n, n.right
	}
	if c < 0 {
		left, middle, right := t.split(n.left, s)
		return left, middle, &node{
			item:     n.item,
			priority: n.priority,
			left:     right,
			right:    n.right,
		}
	}
	left, middle, right := t.split(n.right, s)
	return &node{
		item:     n.item,
		priority: n.priority,
		left:     n.left,
		right:    left,
	}, middle, right
}
<|endoftext|>


<commit_before>package tvmaze

import (
	"encoding/json"
	"fmt"
	"reflect"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
)

// ShowResponse wraps a TV Maze search response
type ShowResponse struct {
	Score float64
	Show  Show
}

// Show wraps a TV Maze show object
type Show struct {
	ID        int
	Name      string
	Type      string
	Genres    []string
	Status    string
	Runtime   int
	Premiered Date
	Summary   string
	Network   network
	Embeds    struct {
		Episodes []Episode
	} `json:"_embedded"`
	Remotes map[string]*json.RawMessage `json:"externals"`
	Image   struct {
		Medium   string
		Original string
	}
}

// GetTitle return the show title
func (s Show) GetTitle() string {
	return s.Name
}

// GetDescription returns a summary of the show
func (s Show) GetDescription() string {
	return s.Summary
}

// GetNetwork returns the network that currently broadcasts the show
func (s Show) GetNetwork() string {
	return s.Network.Name
}

// GetFirstAired return the time the first episode was aired
func (s Show) GetFirstAired() time.Time {
	if s.Premiered.Valid {
		return s.Premiered.Time
	}
	return time.Time{}
}

// GetMediumPoster returns the URL to a medium sized poster
func (s Show) GetMediumPoster() string {
	return s.Image.Medium
}

// GetOriginalPoster returns the URL to an original sized poster
func (s Show) GetOriginalPoster() string {
	return s.Image.Original
}

// GetTVRageID returns the show's ID on tvrage.com
func (s Show) GetTVRageID() int {
	if s.Remotes["tvrage"] == nil {
		return 0
	}
	var val int
	if err := json.Unmarshal(*s.Remotes["tvrage"], &val); err != nil {
		log.WithError(err).WithField("tvrage_id", s.Remotes["tvrage"]).Error("failed to parse tvrage id")
	}
	return val
}

// GetTVDBID returns the show's ID on thetvdb.com
func (s Show) GetTVDBID() int {
	if s.Remotes["thetvdb"] == nil {
		return 0
	}
	var val int
	if err := json.Unmarshal(*s.Remotes["thetvdb"], &val); err != nil {
		log.WithError(err).WithField("thetvdb_id", s.Remotes["thetvdb"]).Error("failed to parse thetvdb id")
	}
	return val
}

// GetIMDBID returns the show's ID on imdb.com
func (s Show) GetIMDBID() string {
	if s.Remotes["imdb"] == nil {
		return ""
	}
	var val string
	if err := json.Unmarshal(*s.Remotes["imdb"], &val); err != nil {
		log.WithError(err).WithField("imdb_id", s.Remotes["imdb"]).Error("failed to parse imdb id")
	}
	return val
}

// FindShows finds all matches for a given search string
func (c Client) FindShows(name string) (s []ShowResponse, err error) {
	url := baseURLWithPathQuery("search/shows", "q", name)

	if err := c.get(url, &s); err != nil {
		return nil, err
	}

	return s, nil
}

// GetShow finds all matches for a given search string
func (c Client) GetShow(name string) (*Show, error) {
	url := baseURLWithPathQuery("singlesearch/shows", "q", name)

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// GetShowWithID finds a show by its TVMaze ID
func (c Client) GetShowWithID(tvMazeID string) (*Show, error) {
	url := baseURLWithPath(fmt.Sprintf("shows/%s", tvMazeID))

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// GetShowWithTVRageID finds a show by its TVRage ID
func (c Client) GetShowWithTVRageID(tvRageID string) (*Show, error) {
	url := baseURLWithPathQuery("lookup/shows", "tvrage", tvRageID)

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// GetShowWithTVDBID finds a show by its TVDB ID
func (c Client) GetShowWithTVDBID(TVDBID string) (*Show, error) {
	url := baseURLWithPathQuery("lookup/shows", "thetvdb", TVDBID)

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// RefreshShow refreshes a show from the server
func (c Client) RefreshShow(show *Show) (err error) {
	url := baseURLWithPath(fmt.Sprintf("shows/%d", show.ID))
	return c.get(url, &show)
}

// Date represents a date from tvmaze, supporting nullability
type Date struct {
	time.Time
	Valid bool
}

// MarshalJSON implements json.Marshaler.
// It will encode null if this Date is null.
func (d *Date) MarshalJSON() ([]byte, error) {
	if !d.Valid {
		return []byte("null"), nil
	}
	return d.Time.MarshalJSON()
}

// UnmarshalJSON implements json.Unmarshaler.
// It supports string and null input.
func (d *Date) UnmarshalJSON(data []byte) error {
	var err error
	var v interface{}
	if err = json.Unmarshal(data, &v); err != nil {
		return errors.Wrap(err, "failed to unmarshal JSON response")
	}
	switch x := v.(type) {
	case string:
		var parsedTime time.Time
		parsedTime, err = time.Parse(time.RFC3339[:10], x)
		*d = Date{parsedTime, true}
	case nil:
		d.Valid = false
		return nil
	default:
		err = errors.Errorf("json: cannot unmarshal %v into Go value of type tvmaze.Date", reflect.TypeOf(v).Name())
	}
	d.Valid = err == nil
	return err
}
<commit_msg>Rename of Sirupsen -> sirupsen<commit_after>package tvmaze

import (
	"encoding/json"
	"fmt"
	"reflect"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/pkg/errors"
)

// ShowResponse wraps a TV Maze search response
type ShowResponse struct {
	Score float64
	Show  Show
}

// Show wraps a TV Maze show object
type Show struct {
	ID        int
	Name      string
	Type      string
	Genres    []string
	Status    string
	Runtime   int
	Premiered Date
	Summary   string
	Network   network
	Embeds    struct {
		Episodes []Episode
	} `json:"_embedded"`
	Remotes map[string]*json.RawMessage `json:"externals"`
	Image   struct {
		Medium   string
		Original string
	}
}

// GetTitle return the show title
func (s Show) GetTitle() string {
	return s.Name
}

// GetDescription returns a summary of the show
func (s Show) GetDescription() string {
	return s.Summary
}

// GetNetwork returns the network that currently broadcasts the show
func (s Show) GetNetwork() string {
	return s.Network.Name
}

// GetFirstAired return the time the first episode was aired
func (s Show) GetFirstAired() time.Time {
	if s.Premiered.Valid {
		return s.Premiered.Time
	}
	return time.Time{}
}

// GetMediumPoster returns the URL to a medium sized poster
func (s Show) GetMediumPoster() string {
	return s.Image.Medium
}

// GetOriginalPoster returns the URL to an original sized poster
func (s Show) GetOriginalPoster() string {
	return s.Image.Original
}

// GetTVRageID returns the show's ID on tvrage.com
func (s Show) GetTVRageID() int {
	if s.Remotes["tvrage"] == nil {
		return 0
	}
	var val int
	if err := json.Unmarshal(*s.Remotes["tvrage"], &val); err != nil {
		log.WithError(err).WithField("tvrage_id", s.Remotes["tvrage"]).Error("failed to parse tvrage id")
	}
	return val
}

// GetTVDBID returns the show's ID on thetvdb.com
func (s Show) GetTVDBID() int {
	if s.Remotes["thetvdb"] == nil {
		return 0
	}
	var val int
	if err := json.Unmarshal(*s.Remotes["thetvdb"], &val); err != nil {
		log.WithError(err).WithField("thetvdb_id", s.Remotes["thetvdb"]).Error("failed to parse thetvdb id")
	}
	return val
}

// GetIMDBID returns the show's ID on imdb.com
func (s Show) GetIMDBID() string {
	if s.Remotes["imdb"] == nil {
		return ""
	}
	var val string
	if err := json.Unmarshal(*s.Remotes["imdb"], &val); err != nil {
		log.WithError(err).WithField("imdb_id", s.Remotes["imdb"]).Error("failed to parse imdb id")
	}
	return val
}

// FindShows finds all matches for a given search string
func (c Client) FindShows(name string) (s []ShowResponse, err error) {
	url := baseURLWithPathQuery("search/shows", "q", name)

	if err := c.get(url, &s); err != nil {
		return nil, err
	}

	return s, nil
}

// GetShow finds all matches for a given search string
func (c Client) GetShow(name string) (*Show, error) {
	url := baseURLWithPathQuery("singlesearch/shows", "q", name)

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// GetShowWithID finds a show by its TVMaze ID
func (c Client) GetShowWithID(tvMazeID string) (*Show, error) {
	url := baseURLWithPath(fmt.Sprintf("shows/%s", tvMazeID))

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// GetShowWithTVRageID finds a show by its TVRage ID
func (c Client) GetShowWithTVRageID(tvRageID string) (*Show, error) {
	url := baseURLWithPathQuery("lookup/shows", "tvrage", tvRageID)

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// GetShowWithTVDBID finds a show by its TVDB ID
func (c Client) GetShowWithTVDBID(TVDBID string) (*Show, error) {
	url := baseURLWithPathQuery("lookup/shows", "thetvdb", TVDBID)

	show := &Show{}
	if err := c.get(url, show); err != nil {
		return nil, err
	}

	return show, nil
}

// RefreshShow refreshes a show from the server
func (c Client) RefreshShow(show *Show) (err error) {
	url := baseURLWithPath(fmt.Sprintf("shows/%d", show.ID))
	return c.get(url, &show)
}

// Date represents a date from tvmaze, supporting nullability
type Date struct {
	time.Time
	Valid bool
}

// MarshalJSON implements json.Marshaler.
// It will encode null if this Date is null.
func (d *Date) MarshalJSON() ([]byte, error) {
	if !d.Valid {
		return []byte("null"), nil
	}
	return d.Time.MarshalJSON()
}

// UnmarshalJSON implements json.Unmarshaler.
// It supports string and null input.
func (d *Date) UnmarshalJSON(data []byte) error {
	var err error
	var v interface{}
	if err = json.Unmarshal(data, &v); err != nil {
		return errors.Wrap(err, "failed to unmarshal JSON response")
	}
	switch x := v.(type) {
	case string:
		var parsedTime time.Time
		parsedTime, err = time.Parse(time.RFC3339[:10], x)
		*d = Date{parsedTime, true}
	case nil:
		d.Valid = false
		return nil
	default:
		err = errors.Errorf("json: cannot unmarshal %v into Go value of type tvmaze.Date", reflect.TypeOf(v).Name())
	}
	d.Valid = err == nil
	return err
}
<|endoftext|>


<commit_before>package types

import (
	"fmt"
)

// Type describes all type structs
type Type interface {
	Equals(other Type) bool
	IsError() bool
	String() string
	isType()
}

// Error signals that whatever expression was supposed to produce this type
// had a semantic error that made proper evaluation impossible
type Error struct{}

// Equals returns true for every other type
func (t Error) Equals(other Type) bool {
	if _, ok := other.(Error); ok {
		return true
	}

	return false
}

// IsError returns true because TypeError is an error
func (t Error) IsError() bool  { return true }
func (t Error) String() string { return "ERROR" }
func (t Error) isType()        {}

// Void descirbes the return type of a function that returns no value
type Void struct{}

// Equals returns true if another type has an identical structure and identical names
func (t Void) Equals(other Type) bool {
	if _, ok := other.(Void); ok {
		return true
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Void) IsError() bool  { return false }
func (t Void) String() string { return "Void" }
func (t Void) isType()        {}

// Function describes mappings of 0+ parameter types to a return type
type Function struct {
	Params Tuple
	Ret    Type
}

// Equals returns true if another type has an identical structure and identical names
func (t Function) Equals(other Type) bool {
	if t2, ok := other.(Function); ok {
		return t.Params.Equals(t2.Params) && t.Ret.Equals(t2.Ret)
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Function) IsError() bool  { return false }
func (t Function) String() string { return fmt.Sprintf("%s => %s", t.Params, t.Ret) }
func (t Function) isType()        {}

// Tuple describes a group of types
type Tuple struct {
	Children []Type
}

// Equals returns true if another type has an identical structure and identical names
func (t Tuple) Equals(other Type) bool {
	if t2, ok := other.(Tuple); ok {
		if len(t.Children) != len(t2.Children) {
			return false
		}

		for i, child := range t.Children {
			child2 := t2.Children[i]
			if child.Equals(child2) == false {
				return false
			}
		}

		return true
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Tuple) IsError() bool  { return false }
func (t Tuple) String() string { return fmt.Sprintf("(%s)", concatTypes(t.Children)) }
func (t Tuple) isType()        {}

// List describes an array of a common type
type List struct {
	Child Type
}

// Equals returns true if another type has an identical structure and identical names
func (t List) Equals(other Type) bool {
	if t2, ok := other.(List); ok {
		return t.Child.Equals(t2.Child)
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t List) IsError() bool  { return false }
func (t List) String() string { return fmt.Sprintf("[%s]", t.Child) }
func (t List) isType()        {}

// Optional describes a type that may resolve to a value or nothing
type Optional struct {
	Child Type
}

// Equals returns true if another type has an identical structure and identical names
func (t Optional) Equals(other Type) bool {
	if t2, ok := other.(Optional); ok {
		return t.Child.Equals(t2.Child)
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Optional) IsError() bool  { return false }
func (t Optional) String() string { return fmt.Sprintf("%s?", t.Child) }
func (t Optional) isType()        {}

// Ident describes a type aliased to an identifier
type Ident struct {
	Name string
}

// Equals returns true if another type has an identical structure and identical names
func (t Ident) Equals(other Type) bool {
	if t2, ok := other.(Ident); ok {
		return t.Name == t2.Name
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Ident) IsError() bool  { return false }
func (t Ident) String() string { return t.Name }
func (t Ident) isType()        {}

func concatTypes(types []Type) string {
	out := ""
	for i, typ := range types {
		if i > 0 {
			out += " "
		}
		out += typ.String()
	}
	return out
}
<commit_msg>fix typo<commit_after>package types

import (
	"fmt"
)

// Type describes all type structs
type Type interface {
	Equals(other Type) bool
	IsError() bool
	String() string
	isType()
}

// Error signals that whatever expression was supposed to produce this type
// had a semantic error that made proper evaluation impossible
type Error struct{}

// Equals returns false for every other type
func (t Error) Equals(other Type) bool {
	if _, ok := other.(Error); ok {
		return true
	}

	return false
}

// IsError returns true because TypeError is an error
func (t Error) IsError() bool  { return true }
func (t Error) String() string { return "ERROR" }
func (t Error) isType()        {}

// Void descirbes the return type of a function that returns no value
type Void struct{}

// Equals returns true if another type has an identical structure and identical names
func (t Void) Equals(other Type) bool {
	if _, ok := other.(Void); ok {
		return true
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Void) IsError() bool  { return false }
func (t Void) String() string { return "Void" }
func (t Void) isType()        {}

// Function describes mappings of 0+ parameter types to a return type
type Function struct {
	Params Tuple
	Ret    Type
}

// Equals returns true if another type has an identical structure and identical names
func (t Function) Equals(other Type) bool {
	if t2, ok := other.(Function); ok {
		return t.Params.Equals(t2.Params) && t.Ret.Equals(t2.Ret)
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Function) IsError() bool  { return false }
func (t Function) String() string { return fmt.Sprintf("%s => %s", t.Params, t.Ret) }
func (t Function) isType()        {}

// Tuple describes a group of types
type Tuple struct {
	Children []Type
}

// Equals returns true if another type has an identical structure and identical names
func (t Tuple) Equals(other Type) bool {
	if t2, ok := other.(Tuple); ok {
		if len(t.Children) != len(t2.Children) {
			return false
		}

		for i, child := range t.Children {
			child2 := t2.Children[i]
			if child.Equals(child2) == false {
				return false
			}
		}

		return true
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Tuple) IsError() bool  { return false }
func (t Tuple) String() string { return fmt.Sprintf("(%s)", concatTypes(t.Children)) }
func (t Tuple) isType()        {}

// List describes an array of a common type
type List struct {
	Child Type
}

// Equals returns true if another type has an identical structure and identical names
func (t List) Equals(other Type) bool {
	if t2, ok := other.(List); ok {
		return t.Child.Equals(t2.Child)
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t List) IsError() bool  { return false }
func (t List) String() string { return fmt.Sprintf("[%s]", t.Child) }
func (t List) isType()        {}

// Optional describes a type that may resolve to a value or nothing
type Optional struct {
	Child Type
}

// Equals returns true if another type has an identical structure and identical names
func (t Optional) Equals(other Type) bool {
	if t2, ok := other.(Optional); ok {
		return t.Child.Equals(t2.Child)
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Optional) IsError() bool  { return false }
func (t Optional) String() string { return fmt.Sprintf("%s?", t.Child) }
func (t Optional) isType()        {}

// Ident describes a type aliased to an identifier
type Ident struct {
	Name string
}

// Equals returns true if another type has an identical structure and identical names
func (t Ident) Equals(other Type) bool {
	if t2, ok := other.(Ident); ok {
		return t.Name == t2.Name
	}

	return false
}

// IsError returns false because this is a properly resolved type
func (t Ident) IsError() bool  { return false }
func (t Ident) String() string { return t.Name }
func (t Ident) isType()        {}

func concatTypes(types []Type) string {
	out := ""
	for i, typ := range types {
		if i > 0 {
			out += " "
		}
		out += typ.String()
	}
	return out
}
<|endoftext|>


<commit_before>package main

import ()

type dnsRec struct {
	TTL int
	value string
	String() string
}

type aRec struct {
	dnsRec
}

type cnameRec struct {
	dnsRec
}

type mxRec struct {
	dnsRec
	priority int
}

type txtRec struct {
	dnsRec
}

type nsRec struct {
	cnameRec
}

type ptrRec struct {
	aRec
}

type soaRec struct {

}

type fqdn struct {
	parentPart string
	localPart string
	records []dnsRec
	subdomains []fqdn
}

type zone struct {
	soa soaRec
	defaultTTL int
	tld fqdn
}<commit_msg>somehow put my starting stuff into the wrong project<commit_after><|endoftext|>