<commit_before>package calendar

import (
	"errors"
	"fmt"
	"time"
)

// Checks if the given time is at the given month and day
func atMD(date time.Time, month, day int) bool {
	return (date.Month() == time.Month(month)) && (date.Day() == day)
}

// Checks if the two given times are at the same months and days
func atDate(t, when time.Time) bool {
	return (t.Month() == when.Month()) && (t.Day() == when.Day())
}

// Return the count of a given weekday from day t, +- a few days
func numberOfWeekdaysInPeriod(date time.Time, days int, whichWeekday time.Weekday) int {
	specialWeekdayCounter := 0
	when := date
	if days < 0 {
		for i := days; i <= 0; i++ {
			when = date.AddDate(0, 0, i)
			if when.Weekday() == whichWeekday {
				specialWeekdayCounter++
			}
		}
	} else {
		for i := 0; i <= days; i++ {
			when = date.AddDate(0, 0, i)
			if when.Weekday() == whichWeekday {
				specialWeekdayCounter++
			}
		}
	}
	return specialWeekdayCounter
}

// Return the number of sundays from day t, +- a few days
func sundaysInPeriod(date time.Time, days int) int {
	return numberOfWeekdaysInPeriod(date, days, time.Sunday)
}

// Find a preceding sunday, same year
func searchBackwardsForSunday(date time.Time) (time.Time, error) {
	return searchBackwardsForDaySameYear(date, time.Sunday)
}

// Find the last weekday given a month/year
func lastDayOfMonth(date time.Time, weekday time.Weekday) time.Time {

	var found time.Time

	// Start with the first day in the given month
	current := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.UTC)

	// Stay within the same month
	for current.Month() == date.Month() {
		// Check if it's the given weekday
		if current.Weekday() == weekday {
			// Found one
			found = current
		}

		// Go the next day
		current = current.AddDate(0, 0, 1)
	}

	// Return the last found day
	return found
}

// Find a later weekday, same month
func searchForwardsForDaySameMonth(date time.Time, weekday time.Weekday) (time.Time, error) {
	// Start with the day after the given date
	current := date.AddDate(0, 0, 1)

	// Stay within the same month
	for current.Month() == date.Month() {
		// Check if it's the given weekday
		if current.Weekday() == weekday {
			// Found one
			return current, nil
		}

		// Go the next day
		current = current.AddDate(0, 0, 1)
	}

	return date, errors.New("Could not find a later " + weekday.String() + " the same month!")
}

// Find a preceding weekday, same year
func searchBackwardsForDaySameYear(date time.Time, weekday time.Weekday) (time.Time, error) {
	// Start with the day before the given date
	current := date.AddDate(0, 0, -1)

	// Stay within the same year
	for current.Year() == date.Year() {
		// Check if it's the given weekday
		if current.Weekday() == weekday {
			// Found one
			return current, nil
		}

		// Go the previous day
		current = current.AddDate(0, 0, -1)
	}

	return date, errors.New("Could not find an earlier " + weekday.String() + " the same year!")
}

// Check if the given date is at the Nth weekday (for istance Sunday) of a given month
func atNthWeekdayOfMonth(date time.Time, n int, weekday time.Weekday, month time.Month) bool {
	if date.Month() != month {
		return false
	}
	nthDay, err := nthWeekdayOfMonth(date, n, weekday)
	if err != nil {
		return false
	}
	if atDate(date, nthDay) {
		return true
	}
	return false
}

// Check if the given date is at the last type of weekday (like monday)
func atLastWeekday(date time.Time, weekday time.Weekday, month time.Month) bool {
	return (date.Month() == month) && atDate(date, lastDayOfMonth(date, weekday))
}

// Find the Nth type of weekday of a given year and month
func nthWeekdayOfMonth(date time.Time, n int, whichWeekday time.Weekday) (time.Time, error) {

	specialWeekdayCounter := 0

	// Start at the first day in the given month
	current := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.UTC)

	// As long as we are in the same month
	for current.Month() == date.Month() {

		// Which weekday is it?
		if current.Weekday() == whichWeekday {
			specialWeekdayCounter++
		}

		// Is it the Nth occurrence?
		if specialWeekdayCounter == n {
			return current, nil
		}

		// If it's the given weekday, advance almost one week forward
		if current.Weekday() == whichWeekday {
			current = current.AddDate(0, 0, 7)
			continue
		}

		// Advance to the next day
		current = current.AddDate(0, 0, 1)
	}

	return date, fmt.Errorf("Could not find the %dth %s in %s", n, whichWeekday, date.Month())
}

// Find the Nth sunday of a given year and month
func nthSundayOfMonth(date time.Time, n int) (time.Time, error) {
	return nthWeekdayOfMonth(date, n, time.Sunday)
}
<commit_msg>Follow the advice of golint<commit_after>package calendar

import (
	"errors"
	"fmt"
	"time"
)

// Checks if the given time is at the given month and day
func atMD(date time.Time, month, day int) bool {
	return (date.Month() == time.Month(month)) && (date.Day() == day)
}

// Checks if the two given times are at the same months and days
func atDate(t, when time.Time) bool {
	return (t.Month() == when.Month()) && (t.Day() == when.Day())
}

// Return the count of a given weekday from day t, +- a few days
func numberOfWeekdaysInPeriod(date time.Time, days int, whichWeekday time.Weekday) int {
	specialWeekdayCounter := 0
	when := date
	if days < 0 {
		for i := days; i <= 0; i++ {
			when = date.AddDate(0, 0, i)
			if when.Weekday() == whichWeekday {
				specialWeekdayCounter++
			}
		}
	} else {
		for i := 0; i <= days; i++ {
			when = date.AddDate(0, 0, i)
			if when.Weekday() == whichWeekday {
				specialWeekdayCounter++
			}
		}
	}
	return specialWeekdayCounter
}

// Return the number of sundays from day t, +- a few days
func sundaysInPeriod(date time.Time, days int) int {
	return numberOfWeekdaysInPeriod(date, days, time.Sunday)
}

// Find a preceding sunday, same year
func searchBackwardsForSunday(date time.Time) (time.Time, error) {
	return searchBackwardsForDaySameYear(date, time.Sunday)
}

// Find the last weekday given a month/year
func lastDayOfMonth(date time.Time, weekday time.Weekday) time.Time {

	var found time.Time

	// Start with the first day in the given month
	current := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.UTC)

	// Stay within the same month
	for current.Month() == date.Month() {
		// Check if it's the given weekday
		if current.Weekday() == weekday {
			// Found one
			found = current
		}

		// Go the next day
		current = current.AddDate(0, 0, 1)
	}

	// Return the last found day
	return found
}

// Find a later weekday, same month
func searchForwardsForDaySameMonth(date time.Time, weekday time.Weekday) (time.Time, error) {
	// Start with the day after the given date
	current := date.AddDate(0, 0, 1)

	// Stay within the same month
	for current.Month() == date.Month() {
		// Check if it's the given weekday
		if current.Weekday() == weekday {
			// Found one
			return current, nil
		}

		// Go the next day
		current = current.AddDate(0, 0, 1)
	}

	return date, errors.New("Could not find a later " + weekday.String() + " the same month!")
}

// Find a preceding weekday, same year
func searchBackwardsForDaySameYear(date time.Time, weekday time.Weekday) (time.Time, error) {
	// Start with the day before the given date
	current := date.AddDate(0, 0, -1)

	// Stay within the same year
	for current.Year() == date.Year() {
		// Check if it's the given weekday
		if current.Weekday() == weekday {
			// Found one
			return current, nil
		}

		// Go the previous day
		current = current.AddDate(0, 0, -1)
	}

	return date, errors.New("Could not find an earlier " + weekday.String() + " the same year!")
}

// Check if the given date is at the Nth weekday (for istance Sunday) of a given month
func atNthWeekdayOfMonth(date time.Time, n int, weekday time.Weekday, month time.Month) bool {
	if date.Month() != month {
		return false
	}
	nthDay, err := nthWeekdayOfMonth(date, n, weekday)
	if err != nil {
		return false
	}
	if atDate(date, nthDay) {
		return true
	}
	return false
}

// Check if the given date is at the last type of weekday (like monday)
func atLastWeekday(date time.Time, weekday time.Weekday, month time.Month) bool {
	return (date.Month() == month) && atDate(date, lastDayOfMonth(date, weekday))
}

// Find the Nth type of weekday of a given year and month
func nthWeekdayOfMonth(date time.Time, n int, whichWeekday time.Weekday) (time.Time, error) {

	specialWeekdayCounter := 0

	// Start at the first day in the given month
	current := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.UTC)

	// As long as we are in the same month
	for current.Month() == date.Month() {

		// Which weekday is it?
		if current.Weekday() == whichWeekday {
			specialWeekdayCounter++
		}

		// Is it the Nth occurrence?
		if specialWeekdayCounter == n {
			return current, nil
		}

		// If it's the given weekday, advance almost one week forward
		if current.Weekday() == whichWeekday {
			current = current.AddDate(0, 0, 7)
			continue
		}

		// Advance to the next day
		current = current.AddDate(0, 0, 1)
	}

	return date, fmt.Errorf("could not find the %dth %s in %s", n, whichWeekday, date.Month())
}

// Find the Nth sunday of a given year and month
func nthSundayOfMonth(date time.Time, n int) (time.Time, error) {
	return nthWeekdayOfMonth(date, n, time.Sunday)
}
<|endoftext|>


<commit_before>package conex_test

import (
	"testing"

	"github.com/omeid/conex/postgres"
)

func TestPGsql1(t *testing.T) { t.Parallel(); testSQLPing(t) }
func TestPGsql2(t *testing.T) { t.Parallel(); testSQLPing(t) }
func TestPGsql3(t *testing.T) { t.Parallel(); testSQLPing(t) }
func TestPGsql4(t *testing.T) { t.Parallel(); testSQLPing(t) }

func testSQLPing(t *testing.T) {

	config := &postgres.Config{
		User:     "postgres",
		Password: "",
	}

	db, c := postgres.Box(t, config)
	_ = c
	// defer c.Drop()

	err := db.Ping()

	if err != nil {
		t.Fatal(err)
	}

}
<commit_msg>test:pgsql: drop the container when doen<commit_after>package conex_test

import (
	"testing"

	"github.com/omeid/conex/postgres"
)

func TestPGsql1(t *testing.T) { t.Parallel(); testSQLPing(t) }
func TestPGsql2(t *testing.T) { t.Parallel(); testSQLPing(t) }
func TestPGsql3(t *testing.T) { t.Parallel(); testSQLPing(t) }
func TestPGsql4(t *testing.T) { t.Parallel(); testSQLPing(t) }

func testSQLPing(t *testing.T) {

	config := &postgres.Config{
		User:     "postgres",
		Password: "",
	}

	db, c := postgres.Box(t, config)
	_ = c
	defer c.Drop()

	err := db.Ping()

	if err != nil {
		t.Fatal(err)
	}

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"net/http"

	"github.com/pressly/chi"
	"github.com/pressly/chi/render"
	"github.com/serbe/edc"
)

func listSiren(w http.ResponseWriter, r *http.Request) {
	type context struct {
		Title  string          `json:"title"`
		Sirens []edc.SirenList `json:"sirens"`
	}
	sirens, err := db.GetSirenListAll()
	if err != nil {
		errmsg("listSirens GetSirenListAll", err)
		return
	}
	ctx := context{Title: "List", Sirens: sirens}
	render.DefaultResponder(w, r, ctx)
}

func getSiren(w http.ResponseWriter, r *http.Request) {
	type context struct {
		Title string    `json:"title"`
		Siren edc.Siren `json:"siren"`
	}
	id := toInt(chi.URLParam(r, "id"))
	siren, err := db.GetSiren(id)
	if err != nil {
		errmsg("getSiren GetSiren", err)
		return
	}
	ctx := context{Title: "Create siren type", Siren: siren}
	render.DefaultResponder(w, r, ctx)
}

func createSiren(w http.ResponseWriter, r *http.Request) {
	var siren edc.Siren
	decoder := json.NewDecoder(r.Body)
	errchkmsg("createSiren Decode", decoder.Decode(&siren))
	defer func() {
		errchkmsg("createSiren defer Body.Close", r.Body.Close())
	}()
	_, err := db.CreateSiren(siren)
	errchkmsg("createSiren CreateSiren", err)
	return
}

func updateSiren(w http.ResponseWriter, r *http.Request) {
	var siren edc.Siren
	decoder := json.NewDecoder(r.Body)
	errchkmsg("updateSiren Decode", decoder.Decode(&siren))
	defer func() {
		errchkmsg("updateSiren defer Body.Close", r.Body.Close())
	}()
	errchkmsg("updateSiren UpdateSiren", db.UpdateSiren(siren))
	return
}

func deleteSiren(w http.ResponseWriter, r *http.Request) {
	id := toInt(chi.URLParam(r, "id"))
	errchkmsg("deleteSiren DeleteSiren", db.DeleteSiren(id))
	return
}
<commit_msg>continue add siren<commit_after>package main

import (
	"encoding/json"
	"net/http"

	"github.com/pressly/chi"
	"github.com/pressly/chi/render"
	"github.com/serbe/edc"
)

func listSiren(w http.ResponseWriter, r *http.Request) {
	type context struct {
		Title  string          `json:"title"`
		Sirens []edc.SirenList `json:"sirens"`
	}
	sirens, err := db.GetSirenList()
	if err != nil {
		errmsg("listSirens GetSirenList", err)
		return
	}
	ctx := context{Title: "List", Sirens: sirens}
	render.DefaultResponder(w, r, ctx)
}

func getSiren(w http.ResponseWriter, r *http.Request) {
	type context struct {
		Title      string           `json:"title"`
		Siren      edc.Siren        `json:"siren"`
		Contacts   []edc.SelectItem `json:"contacts"`
		Companies  []edc.SelectItem `json:"companies"`
		SirenTypes []edc.SelectItem `json:"siren_types"`
	}
	id := toInt(chi.URLParam(r, "id"))
	siren, err := db.GetSiren(id)
	if err != nil {
		errmsg("getSiren GetSiren", err)
		return
	}
	contacts, err := db.GetContactSelectAll()
	if err != nil {
		errmsg("getSiren GetContactSelectAll", err)
		return
	}
	companies, err := db.GetCompanySelectAll()
	if err != nil {
		errmsg("getSiren GetCompanySelectAll", err)
		return
	}
	sirenTypes, err := db.GetSirenTypeSelectAll()
	if err != nil {
		errmsg("getSiren GetSirenTypeSelectAll", err)
		return
	}
	ctx := context{
		Title:      "Create siren type",
		Siren:      siren,
		Contacts:   contacts,
		Companies:  companies,
		SirenTypes: sirenTypes,
	}
	render.DefaultResponder(w, r, ctx)
}

func createSiren(w http.ResponseWriter, r *http.Request) {
	var siren edc.Siren
	decoder := json.NewDecoder(r.Body)
	errchkmsg("createSiren Decode", decoder.Decode(&siren))
	defer func() {
		errchkmsg("createSiren defer Body.Close", r.Body.Close())
	}()
	_, err := db.CreateSiren(siren)
	errchkmsg("createSiren CreateSiren", err)
	return
}

func updateSiren(w http.ResponseWriter, r *http.Request) {
	var siren edc.Siren
	decoder := json.NewDecoder(r.Body)
	errchkmsg("updateSiren Decode", decoder.Decode(&siren))
	defer func() {
		errchkmsg("updateSiren defer Body.Close", r.Body.Close())
	}()
	errchkmsg("updateSiren UpdateSiren", db.UpdateSiren(siren))
	return
}

func deleteSiren(w http.ResponseWriter, r *http.Request) {
	id := toInt(chi.URLParam(r, "id"))
	errchkmsg("deleteSiren DeleteSiren", db.DeleteSiren(id))
	return
}
<|endoftext|>


<commit_before><commit_msg>minor bug fix<commit_after><|endoftext|>


<commit_before>package sohop

import (
	"crypto/rand"
	"crypto/tls"
	"encoding/hex"
	"fmt"
	"log"
	"math"
	"math/big"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	"github.com/gorilla/securecookie"
	"gitlab.com/davars/sohop/acme"
	"gitlab.com/davars/sohop/auth"
	"gitlab.com/davars/sohop/store"
)

// A Config can be used to set up a sohop proxy
type Config struct {
	// Domain is the domain to which the subdomains belong. Also used as the
	// domain for the session cookie.
	Domain string

	// Upstreams is an array of configurations for upstream servers.  Keys are
	// the subdomain to proxy to the configured server.  Values describe
	// various aspects of the upstream server.
	Upstreams map[string]UpstreamConfig

	// Auth configures the auth middleware.
	Auth auth.Config

	// Cookie configures the session cookie store.
	Cookie CookieConfig

	// TLS can be used to specify a static TLS configuration for the server.
	// It is overridden by the values from the AcmeWrapper if Acme is used.
	TLS TLSConfig

	// Acme configures automatic provisioning and renewal of TLS certificates
	// using the ACME protocol.
	Acme *acme.Config

	// Deprecated.  See https://godoc.org/gitlab.com/davars/sohop/auth#Config.
	Github *auth.GithubAuth

	// Deprecated.  See https://godoc.org/gitlab.com/davars/sohop/auth#Config.
	Google *auth.GoogleAuth
}

// CookieConfig configures the session cookie store.
type CookieConfig struct {
	// Name is the name of the session cookie.  If not set, a random name will
	// be generated on start-up.
	Name string

	// Secret is the private key used to authenticate session cookies. Should be
	// a hex-encoded string 128 characters in length (64 byte key).  If not set,
	// a random key will be generated on start-up.  Run `openssl rand -hex 64`
	// to generate a key.
	Secret string
}

// TLSConfig configures the server certificate.
type TLSConfig struct {
	// CertFile is a path to the PEM-encoded server certificate.
	CertFile string

	// CertKey is a path to the unencrypted PEM-encoded private key for the
	// server certificate.
	CertKey string
}

type Server struct {
	Config    *Config
	HTTPAddr  string
	HTTPSAddr string

	proxy http.Handler
	store store.Namer
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func (s Server) Run() {
	var err error

	s.store, err = s.Config.namer()
	check(err)
	s.Config.checkTLS()

	go func() {
		if s.Config.Acme == nil {
			err = http.ListenAndServeTLS(s.HTTPSAddr, s.Config.TLS.CertFile, s.Config.TLS.CertKey, s.handler())
			check(err)
		} else {
			domains := make([]string, 0, len(s.Config.Upstreams)+2)
			for _, subdomain := range []string{"oauth", "health"} {
				domains = append(domains, fmt.Sprintf("%s.%s", subdomain, s.Config.Domain))
			}
			for subdomain := range s.Config.Upstreams {
				domains = append(domains, fmt.Sprintf("%s.%s", subdomain, s.Config.Domain))
			}

			s.Config.Acme.Address = s.HTTPSAddr
			s.Config.Acme.Domains = domains

			w, err := s.Config.Acme.Wrapper()
			check(err)

			s.Config.TLS.CertFile = w.Config.TLSCertFile
			s.Config.TLS.CertKey = w.Config.TLSKeyFile

			tlsConfig := w.TLSConfig()

			listener, err := tls.Listen("tcp", s.HTTPSAddr, tlsConfig)
			check(err)

			// To enable http2, we need http.Server to have reference to tlsconfig
			// https://github.com/golang/go/issues/14374
			server := &http.Server{
				Addr:      s.HTTPSAddr,
				Handler:   s.handler(),
				TLSConfig: tlsConfig,
			}
			err = server.Serve(listener)
			check(err)
		}
	}()
	go func() {
		err := http.ListenAndServe(s.HTTPAddr,
			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				r.URL.Scheme = "https"
				r.URL.Host = r.Host + s.HTTPSAddr
				http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently)
				return
			}))
		check(err)
	}()
	select {}
}

type UpstreamConfig struct {
	// The URL of the upstream server.
	URL string

	// Auth is whether requests to this upstream require authentication.
	Auth bool

	// HealthCheck is a URL to use as a health check, if different from
	// Upstreams.URL (for example if UpstreamConfig.URL returns a 302 response).
	// It should return a 200 response if the upstream is healthy.
	HealthCheck string

	// WebSocket is a ws:// or wss:// URL receive proxied WebSocket connections.
	WebSocket string

	// Headers can be used to replace the headers of an incomping request
	// before it is sent upstream.  The values are templates, evaluated with the
	// current session available as `.Session`.
	Headers http.Header
}

func (c *Config) namer() (store.Namer, error) {
	if c.Cookie.Name == "" {
		n, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
		if err != nil {
			log.Fatal(err)
		}
		c.Cookie.Name = fmt.Sprintf("_s%d", n)
	}
	if c.Cookie.Secret == "" {
		c.Cookie.Secret = hex.EncodeToString(securecookie.GenerateRandomKey(64))
	}
	return store.New(c.Cookie.Name, c.Cookie.Secret, c.Domain)
}

func (c *Config) checkTLS() {
	if _, err := os.Stat(c.TLS.CertFile); err != nil {
		log.Fatalf("cannot find TLS.CertFile: %v", err)
	}
	if _, err := os.Stat(c.TLS.CertKey); err != nil {
		log.Fatalf("cannot find TLS.CertKey: %v", err)
	}
}

func (c *Config) auther() auth.Auther {
	if c.Github != nil || c.Google != nil {
		log.Fatal("Authorization configuration has changed.  Refer to the README regarding the \"Auth\" key.")
	}
	a, err := auth.NewAuther(c.Auth)
	if err != nil {
		log.Fatalf("NewAuther: %v", err)
	}
	return a
}

func (s Server) handler() http.Handler {
	router := mux.NewRouter()
	router.NotFoundHandler = http.HandlerFunc(notFound)

	conf := s.Config
	oauthRouter := router.Host(fmt.Sprintf("oauth.%s", conf.Domain)).Subrouter()
	auther := conf.auther()
	oauthRouter.Path("/authorized").Handler(auth.Handler(s.store, auther))
	authenticating := auth.Middleware(s.store, auther)

	// TODO: switch to JWT so that this isn't necessary
	oauthRouter.Path("/session").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		session, _ := s.store.Get(r, s.store.Name())
		fmt.Fprintf(w, "%v", session.Values)
	})

	healthRouter := router.Host(fmt.Sprintf("health.%s", conf.Domain)).Subrouter()
	healthRouter.Path("/check").Handler(s.HealthHandler())

	proxyRouter := router.Host(fmt.Sprintf("{subdomain:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?}.%s", conf.Domain)).Subrouter()
	proxy := s.ProxyHandler()
	proxyRouter.MatcherFunc(requiresAuth(conf)).Handler(authenticating(proxy))
	proxyRouter.PathPrefix("/").Handler(proxy)

	return logging(router)
}
<commit_msg>checkTLS only applies to the non-ACME case<commit_after>package sohop

import (
	"crypto/rand"
	"crypto/tls"
	"encoding/hex"
	"fmt"
	"log"
	"math"
	"math/big"
	"net/http"
	"os"

	"github.com/gorilla/mux"
	"github.com/gorilla/securecookie"
	"gitlab.com/davars/sohop/acme"
	"gitlab.com/davars/sohop/auth"
	"gitlab.com/davars/sohop/store"
)

// A Config can be used to set up a sohop proxy
type Config struct {
	// Domain is the domain to which the subdomains belong. Also used as the
	// domain for the session cookie.
	Domain string

	// Upstreams is an array of configurations for upstream servers.  Keys are
	// the subdomain to proxy to the configured server.  Values describe
	// various aspects of the upstream server.
	Upstreams map[string]UpstreamConfig

	// Auth configures the auth middleware.
	Auth auth.Config

	// Cookie configures the session cookie store.
	Cookie CookieConfig

	// TLS can be used to specify a static TLS configuration for the server.
	// It is overridden by the values from the AcmeWrapper if Acme is used.
	TLS TLSConfig

	// Acme configures automatic provisioning and renewal of TLS certificates
	// using the ACME protocol.
	Acme *acme.Config

	// Deprecated.  See https://godoc.org/gitlab.com/davars/sohop/auth#Config.
	Github *auth.GithubAuth

	// Deprecated.  See https://godoc.org/gitlab.com/davars/sohop/auth#Config.
	Google *auth.GoogleAuth
}

// CookieConfig configures the session cookie store.
type CookieConfig struct {
	// Name is the name of the session cookie.  If not set, a random name will
	// be generated on start-up.
	Name string

	// Secret is the private key used to authenticate session cookies. Should be
	// a hex-encoded string 128 characters in length (64 byte key).  If not set,
	// a random key will be generated on start-up.  Run `openssl rand -hex 64`
	// to generate a key.
	Secret string
}

// TLSConfig configures the server certificate.
type TLSConfig struct {
	// CertFile is a path to the PEM-encoded server certificate.
	CertFile string

	// CertKey is a path to the unencrypted PEM-encoded private key for the
	// server certificate.
	CertKey string
}

type Server struct {
	Config    *Config
	HTTPAddr  string
	HTTPSAddr string

	proxy http.Handler
	store store.Namer
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func (s Server) Run() {
	var err error

	s.store, err = s.Config.namer()
	check(err)

	go func() {
		if s.Config.Acme == nil {
			s.Config.checkTLS()
			err = http.ListenAndServeTLS(s.HTTPSAddr, s.Config.TLS.CertFile, s.Config.TLS.CertKey, s.handler())
			check(err)
		} else {
			domains := make([]string, 0, len(s.Config.Upstreams)+2)
			for _, subdomain := range []string{"oauth", "health"} {
				domains = append(domains, fmt.Sprintf("%s.%s", subdomain, s.Config.Domain))
			}
			for subdomain := range s.Config.Upstreams {
				domains = append(domains, fmt.Sprintf("%s.%s", subdomain, s.Config.Domain))
			}

			s.Config.Acme.Address = s.HTTPSAddr
			s.Config.Acme.Domains = domains

			w, err := s.Config.Acme.Wrapper()
			check(err)

			s.Config.TLS.CertFile = w.Config.TLSCertFile
			s.Config.TLS.CertKey = w.Config.TLSKeyFile

			tlsConfig := w.TLSConfig()

			listener, err := tls.Listen("tcp", s.HTTPSAddr, tlsConfig)
			check(err)

			// To enable http2, we need http.Server to have reference to tlsconfig
			// https://github.com/golang/go/issues/14374
			server := &http.Server{
				Addr:      s.HTTPSAddr,
				Handler:   s.handler(),
				TLSConfig: tlsConfig,
			}
			err = server.Serve(listener)
			check(err)
		}
	}()
	go func() {
		err := http.ListenAndServe(s.HTTPAddr,
			http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				r.URL.Scheme = "https"
				r.URL.Host = r.Host + s.HTTPSAddr
				http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently)
				return
			}))
		check(err)
	}()
	select {}
}

type UpstreamConfig struct {
	// The URL of the upstream server.
	URL string

	// Auth is whether requests to this upstream require authentication.
	Auth bool

	// HealthCheck is a URL to use as a health check, if different from
	// Upstreams.URL (for example if UpstreamConfig.URL returns a 302 response).
	// It should return a 200 response if the upstream is healthy.
	HealthCheck string

	// WebSocket is a ws:// or wss:// URL receive proxied WebSocket connections.
	WebSocket string

	// Headers can be used to replace the headers of an incomping request
	// before it is sent upstream.  The values are templates, evaluated with the
	// current session available as `.Session`.
	Headers http.Header
}

func (c *Config) namer() (store.Namer, error) {
	if c.Cookie.Name == "" {
		n, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
		if err != nil {
			log.Fatal(err)
		}
		c.Cookie.Name = fmt.Sprintf("_s%d", n)
	}
	if c.Cookie.Secret == "" {
		c.Cookie.Secret = hex.EncodeToString(securecookie.GenerateRandomKey(64))
	}
	return store.New(c.Cookie.Name, c.Cookie.Secret, c.Domain)
}

func (c *Config) checkTLS() {
	if _, err := os.Stat(c.TLS.CertFile); err != nil {
		log.Fatalf("cannot find TLS.CertFile: %v", err)
	}
	if _, err := os.Stat(c.TLS.CertKey); err != nil {
		log.Fatalf("cannot find TLS.CertKey: %v", err)
	}
}

func (c *Config) auther() auth.Auther {
	if c.Github != nil || c.Google != nil {
		log.Fatal("Authorization configuration has changed.  Refer to the README regarding the \"Auth\" key.")
	}
	a, err := auth.NewAuther(c.Auth)
	if err != nil {
		log.Fatalf("NewAuther: %v", err)
	}
	return a
}

func (s Server) handler() http.Handler {
	router := mux.NewRouter()
	router.NotFoundHandler = http.HandlerFunc(notFound)

	conf := s.Config
	oauthRouter := router.Host(fmt.Sprintf("oauth.%s", conf.Domain)).Subrouter()
	auther := conf.auther()
	oauthRouter.Path("/authorized").Handler(auth.Handler(s.store, auther))
	authenticating := auth.Middleware(s.store, auther)

	// TODO: switch to JWT so that this isn't necessary
	oauthRouter.Path("/session").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		session, _ := s.store.Get(r, s.store.Name())
		fmt.Fprintf(w, "%v", session.Values)
	})

	healthRouter := router.Host(fmt.Sprintf("health.%s", conf.Domain)).Subrouter()
	healthRouter.Path("/check").Handler(s.HealthHandler())

	proxyRouter := router.Host(fmt.Sprintf("{subdomain:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?}.%s", conf.Domain)).Subrouter()
	proxy := s.ProxyHandler()
	proxyRouter.MatcherFunc(requiresAuth(conf)).Handler(authenticating(proxy))
	proxyRouter.PathPrefix("/").Handler(proxy)

	return logging(router)
}
<|endoftext|>


<commit_before>// How to create kubernetes stack pattern and template?

<commit_msg>Update design.go<commit_after>// How to create kubernetes stack pattern and template?

// The relationship between apiserver and apiserver installer?

// What is the role of apiserver installer?
<|endoftext|>


<commit_before>package lzma

import (
	"errors"
	"fmt"
	"io"
)

// The CFlags type is used in the CodecParams structure to store flags.
type CFlags int

// Flags for the CodecParams structure.
const (
	// EOS marker must be written or will be present.
	CEOSMarker CFlags = 1 << iota
	// The data will or is not be compressed.
	CUncompressed
	// No uncompressed size is provided.
	CNoUncompressedSize
	// No compressed size is provided.
	CNoCompressedSize
	// If the CodecParams value is used with Reset describes which
	// part of the encoder or decoder must be reset.
	CResetState
	CResetProperties
	CResetDict
)

// Flag indicates in a decoder that the end of stream has been reached.
const ceos = CResetDict << (iota + 1)

// The CodecParams provides the parameters for the encoder and decoder.
// Note that the size fields are limits for encoding and fixed values
// for decoding.
//
// Currently only the decoder prints the stream of operations of debug
// is set to a non-zero value.
type CodecParams struct {
	// dictionary capacity
	DictCap int
	// buffer capacity
	BufCap int
	// compressed size; see CNoCompressedSize
	CompressedSize int64
	// uncompressed size; see CNoUncompressedSize
	UncompressedSize int64
	// literal context
	LC int
	// literal position bits
	LP int
	// position bits
	PB int
	// Debug defines the debug level
	Debug byte
	// boolean flags are stored here
	Flags CFlags
}

// Decoder decodes a raw LZMA stream without any header.
type Decoder struct {
	// dictionary
	dict decoderDict
	// decoder state
	state state
	// range decoder
	rd *rangeDecoder
	// start stores the head value of the dictionary for the LZMA
	// stream
	start int64
	// uncompressedSize stors the value of the CodecParams  value
	uncompressedSize int64
	// flags as provided by the CodecParams value
	flags CFlags
	// debug value as provided by the CodecParams value
	debug byte
	// counter of operations used for debug output
	opCounter int64
	// reader for uncompressed data
	lr *io.LimitedReader
}

// InitDecoder initializes a LZMA decoder value.
func InitDecoder(d *Decoder, r io.Reader, p *CodecParams) error {
	*d = Decoder{}
	if err := initDecoderDict(&d.dict, p.DictCap, p.BufCap); err != nil {
		return err
	}
	p.Flags |= CResetDict
	err := d.Reset(r, p)
	return err
}

// NewDecoder allocates and initializes a new LZMA decoder.
func NewDecoder(r io.Reader, p *CodecParams) (d *Decoder, err error) {
	d = new(Decoder)
	if err = InitDecoder(d, r, p); err != nil {
		return nil, err
	}
	return d, nil
}

// Reset resets the decoder. Note that the buffer will contain its
// current value.
func (d *Decoder) Reset(r io.Reader, p *CodecParams) error {
	d.flags = p.Flags
	d.uncompressedSize = p.UncompressedSize
	d.debug = p.Debug

	if p.Flags&CResetDict != 0 {
		d.dict.Reset()
	}
	d.start = d.dict.head

	if d.flags&CUncompressed != 0 {
		if d.flags&CNoUncompressedSize != 0 {
			panic("uncompressed segment needs size")
		}
		d.lr = &io.LimitedReader{R: r, N: d.uncompressedSize}
		return nil
	}

	if p.Flags&(CResetProperties|CResetDict) != 0 {
		props, err := NewProperties(p.LC, p.LP, p.PB)
		if err != nil {
			return err
		}
		initState(&d.state, props)
	} else if p.Flags&CResetState != 0 {
		d.state.Reset()
	}

	var err error
	if p.Flags&CNoCompressedSize != 0 {
		d.rd, err = newRangeDecoder(r)
	} else {
		d.rd, err = newRangeDecoderLimit(r, p.CompressedSize)
	}
	return err
}

// decodeLiteral decodes a single literal from the LZMA stream.
func (d *Decoder) decodeLiteral() (op operation, err error) {
	litState := d.state.litState(d.dict.ByteAt(1), d.dict.head)
	match := d.dict.ByteAt(int(d.state.rep[0]) + 1)
	s, err := d.state.litCodec.Decode(d.rd, d.state.state, match, litState)
	if err != nil {
		return nil, err
	}
	return lit{s}, nil
}

// verifyEOS checks whether the decoder is indeed at the end of the LZMA
// stream.
func (d *Decoder) verifyEOS() error {
	if d.flags&CNoCompressedSize == 0 && d.rd.r.limit != d.rd.r.n {
		return errCompressedSize
	}
	if d.flags&CNoUncompressedSize == 0 && d.uncompressedSize != d.Uncompressed() {
		return errUncompressedSize
	}
	return nil
}

// handleEOSMarker handles an identified ESO marker.
func (d *Decoder) handleEOSMarker() error {
	d.flags |= ceos
	if !d.rd.possiblyAtEnd() {
		return errMoreData
	}
	return d.verifyEOS()
}

// handleEOS handles an identified EOS condition, but not the
// identification of an EOS marker.
func (d *Decoder) handleEOS() error {
	d.flags |= ceos
	if d.flags&CEOSMarker != 0 {
		_, err := d.readOp()
		if err != nil {
			if err == errEOS {
				return nil
			}
			return err
		}
		return errMissingEOSMarker
	}
	if !d.rd.possiblyAtEnd() ||
		(d.flags&CNoCompressedSize == 0 && d.rd.r.n < d.rd.r.limit) {

		op, err := d.readOp()
		if err != nil {
			if err == errEOS {
				return nil
			}
			return err
		}
		if err = d.apply(op); err != nil {
			return err
		}
		if err = d.verifyEOS(); err != nil {
			return err
		}
		panic("read one more op without an error")
	}
	return d.verifyEOS()
}

// errEOS indicates that an EOS marker has been found.
var errEOS = errors.New("EOS marker found")

// readOp decodes the next operation from the compressed stream. It
// returns the operation. If an explicit end of stream marker is
// identified the eos error is returned.
func (d *Decoder) readOp() (op operation, err error) {
	// Value of the end of stream (EOS) marker
	const eosDist = 1<<32 - 1

	state, state2, posState := d.state.states(d.dict.head)

	b, err := d.state.isMatch[state2].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// literal
		op, err := d.decodeLiteral()
		if err != nil {
			return nil, err
		}
		d.state.updateStateLiteral()
		return op, nil
	}
	b, err = d.state.isRep[state].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// simple match
		d.state.rep[3], d.state.rep[2], d.state.rep[1] =
			d.state.rep[2], d.state.rep[1], d.state.rep[0]

		d.state.updateStateMatch()
		// The length decoder returns the length offset.
		n, err := d.state.lenCodec.Decode(d.rd, posState)
		if err != nil {
			return nil, err
		}
		// The dist decoder returns the distance offset. The actual
		// distance is 1 higher.
		d.state.rep[0], err = d.state.distCodec.Decode(d.rd, n)
		if err != nil {
			return nil, err
		}
		if d.state.rep[0] == eosDist {
			if err = d.handleEOSMarker(); err == nil {
				err = errEOS
			}
			return nil, err
		}
		op = match{n: int(n) + minMatchLen,
			distance: int(d.state.rep[0]) + minDistance}
		return op, nil
	}
	b, err = d.state.isRepG0[state].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	dist := d.state.rep[0]
	if b == 0 {
		// rep match 0
		b, err = d.state.isRepG0Long[state2].Decode(d.rd)
		if err != nil {
			return nil, err
		}
		if b == 0 {
			d.state.updateStateShortRep()
			op = match{n: 1, distance: int(dist) + minDistance}
			return op, nil
		}
	} else {
		b, err = d.state.isRepG1[state].Decode(d.rd)
		if err != nil {
			return nil, err
		}
		if b == 0 {
			dist = d.state.rep[1]
		} else {
			b, err = d.state.isRepG2[state].Decode(d.rd)
			if err != nil {
				return nil, err
			}
			if b == 0 {
				dist = d.state.rep[2]
			} else {
				dist = d.state.rep[3]
				d.state.rep[3] = d.state.rep[2]
			}
			d.state.rep[2] = d.state.rep[1]
		}
		d.state.rep[1] = d.state.rep[0]
		d.state.rep[0] = dist
	}
	n, err := d.state.repLenCodec.Decode(d.rd, posState)
	if err != nil {
		return nil, err
	}
	d.state.updateStateRep()
	op = match{n: int(n) + minMatchLen, distance: int(dist) + minDistance}
	return op, nil
}

// Printf produces output if d.debug is not zero. It uses fmt.Printf
// for the implementation.
func (d *Decoder) Printf(format string, args ...interface{}) (n int, err error) {
	if d.debug != 0 {
		return fmt.Printf(format, args...)
	}
	return 0, nil
}

// apply takes the operation and transforms the decoder dictionary accordingly.
func (d *Decoder) apply(op operation) error {
	d.opCounter++
	d.Printf("%d %s\n", d.opCounter, op)
	switch x := op.(type) {
	case match:
		return d.dict.WriteMatch(x.distance, x.n)
	case lit:
		return d.dict.WriteByte(x.b)
	}
	panic("op is neither a match nor a literal")
}

// fillDict fills the dictionary unless no space for new data is
// available in the dictionary.
func (d *Decoder) fillDict() error {
	if d.flags&ceos != 0 {
		return nil
	}
	for d.dict.Available() >= maxMatchLen {
		op, err := d.readOp()
		switch err {
		case nil:
			break
		case errEOS:
			return nil
		case io.EOF:
			d.flags |= ceos
			return io.ErrUnexpectedEOF
		default:
			return err
		}
		if err = d.apply(op); err != nil {
			return err
		}
		if d.flags&CNoUncompressedSize == 0 && d.Uncompressed() >=
			d.uncompressedSize {

			return d.handleEOS()
		}
		if d.flags&CNoCompressedSize == 0 && d.rd.r.n >= d.rd.r.limit {
			return d.handleEOS()
		}
	}
	return nil
}

// fillDictUncompressed fills the dictionary if the input stream isn't
// compressed.
func (d *Decoder) fillDictUncompressed() error {
	if d.flags&CUncompressed == 0 {
		panic("Uncompressed flag not set")
	}
	if d.flags&ceos != 0 {
		return nil
	}
	for d.dict.Available() >= 0 {
		_, err := io.CopyN(&d.dict, d.lr, int64(d.dict.Available()))
		if err != nil {
			if err == io.EOF {
				d.flags |= ceos
				if d.lr.N != 0 {
					return errUncompressedSize
				}
				return nil
			}
		}
	}
	return nil
}

// Errors that may be returned while decoding data.
var (
	errMissingEOSMarker = errors.New("EOS marker is missing")
	errMoreData         = errors.New("more data after EOS")
	errCompressedSize   = errors.New("compressed size wrong")
	errUncompressedSize = errors.New("uncompressed size wrong")
)

// Read reads data from the buffer. If no more data is available EOF is
// returned.
func (d *Decoder) Read(p []byte) (n int, err error) {
	fillDict := d.fillDict
	if d.flags&CUncompressed != 0 {
		fillDict = d.fillDictUncompressed
	}

	var k int
	for n < len(p) {
		if err = fillDict(); err != nil {
			return
		}
		// Read of decoder dict never returns an error.
		k, err = d.dict.Read(p[n:])
		if err != nil {
			panic(fmt.Errorf("dictionary read error %s", err))
		}
		if k == 0 && d.flags&ceos != 0 {
			return n, io.EOF
		}
		n += k
	}
	return
}

// Compressed returns the number of compressed bytes read.
func (d *Decoder) Compressed() int64 {
	return d.rd.Compressed()
}

// Uncompressed returns the number of uncompressed bytes decoded.
func (d *Decoder) Uncompressed() int64 {
	return d.dict.head - d.start
}
<commit_msg>lzma: minor changes to public interface documentation<commit_after>package lzma

import (
	"errors"
	"fmt"
	"io"
)

// The CFlags type is used in the CodecParams structure to store flags.
type CFlags int

// Flags for the CodecParams structure.
const (
	// EOS marker must be written or will be present.
	CEOSMarker CFlags = 1 << iota
	// The data will be or is not compressed.
	CUncompressed
	// No uncompressed size is provided.
	CNoUncompressedSize
	// No compressed size is provided.
	CNoCompressedSize
	// If the CodecParams value is used with Reset describes which
	// part of the encoder or decoder must be reset.
	CResetState
	CResetProperties
	CResetDict
)

// Flag indicates in a decoder that the end of stream has been reached.
const ceos = CResetDict << (iota + 1)

// The CodecParams provides the parameters for the encoder and decoder.
// Note that the size fields are limits for encoding and fixed values
// for decoding.
//
// The debug flag is currently only supported by the LZMA decoder. The
// stream of operations is printed if the debug field is set to any
// value not equal to zero.
type CodecParams struct {
	// dictionary capacity
	DictCap int
	// buffer capacity
	BufCap int
	// compressed size; see CNoCompressedSize
	CompressedSize int64
	// uncompressed size; see CNoUncompressedSize
	UncompressedSize int64
	// literal context
	LC int
	// literal position bits
	LP int
	// position bits
	PB int
	// Debug defines the debug level
	Debug byte
	// boolean flags are stored here
	Flags CFlags
}

// Decoder decodes a raw LZMA stream without any header.
type Decoder struct {
	// dictionary
	dict decoderDict
	// decoder state
	state state
	// range decoder
	rd *rangeDecoder
	// start stores the head value of the dictionary for the LZMA
	// stream
	start int64
	// uncompressedSize stors the value of the CodecParams  value
	uncompressedSize int64
	// flags as provided by the CodecParams value
	flags CFlags
	// debug value as provided by the CodecParams value
	debug byte
	// counter of operations used for debug output
	opCounter int64
	// reader for uncompressed data
	lr *io.LimitedReader
}

// InitDecoder initializes a LZMA decoder value.
func InitDecoder(d *Decoder, r io.Reader, p *CodecParams) error {
	*d = Decoder{}
	if err := initDecoderDict(&d.dict, p.DictCap, p.BufCap); err != nil {
		return err
	}
	p.Flags |= CResetDict
	err := d.Reset(r, p)
	return err
}

// NewDecoder allocates and initializes a new LZMA decoder.
func NewDecoder(r io.Reader, p *CodecParams) (d *Decoder, err error) {
	d = new(Decoder)
	if err = InitDecoder(d, r, p); err != nil {
		return nil, err
	}
	return d, nil
}

// Reset resets the decoder. Note that the buffer will contain its
// current value.
func (d *Decoder) Reset(r io.Reader, p *CodecParams) error {
	d.flags = p.Flags
	d.uncompressedSize = p.UncompressedSize
	d.debug = p.Debug

	if p.Flags&CResetDict != 0 {
		d.dict.Reset()
	}
	d.start = d.dict.head

	if d.flags&CUncompressed != 0 {
		if d.flags&CNoUncompressedSize != 0 {
			panic("uncompressed segment needs size")
		}
		d.lr = &io.LimitedReader{R: r, N: d.uncompressedSize}
		return nil
	}

	if p.Flags&(CResetProperties|CResetDict) != 0 {
		props, err := NewProperties(p.LC, p.LP, p.PB)
		if err != nil {
			return err
		}
		initState(&d.state, props)
	} else if p.Flags&CResetState != 0 {
		d.state.Reset()
	}

	var err error
	if p.Flags&CNoCompressedSize != 0 {
		d.rd, err = newRangeDecoder(r)
	} else {
		d.rd, err = newRangeDecoderLimit(r, p.CompressedSize)
	}
	return err
}

// decodeLiteral decodes a single literal from the LZMA stream.
func (d *Decoder) decodeLiteral() (op operation, err error) {
	litState := d.state.litState(d.dict.ByteAt(1), d.dict.head)
	match := d.dict.ByteAt(int(d.state.rep[0]) + 1)
	s, err := d.state.litCodec.Decode(d.rd, d.state.state, match, litState)
	if err != nil {
		return nil, err
	}
	return lit{s}, nil
}

// verifyEOS checks whether the decoder is indeed at the end of the LZMA
// stream.
func (d *Decoder) verifyEOS() error {
	if d.flags&CNoCompressedSize == 0 && d.rd.r.limit != d.rd.r.n {
		return errCompressedSize
	}
	if d.flags&CNoUncompressedSize == 0 && d.uncompressedSize != d.Uncompressed() {
		return errUncompressedSize
	}
	return nil
}

// handleEOSMarker handles an identified ESO marker.
func (d *Decoder) handleEOSMarker() error {
	d.flags |= ceos
	if !d.rd.possiblyAtEnd() {
		return errMoreData
	}
	return d.verifyEOS()
}

// handleEOS handles an identified EOS condition, but not the
// identification of an EOS marker.
func (d *Decoder) handleEOS() error {
	d.flags |= ceos
	if d.flags&CEOSMarker != 0 {
		_, err := d.readOp()
		if err != nil {
			if err == errEOS {
				return nil
			}
			return err
		}
		return errMissingEOSMarker
	}
	if !d.rd.possiblyAtEnd() ||
		(d.flags&CNoCompressedSize == 0 && d.rd.r.n < d.rd.r.limit) {

		op, err := d.readOp()
		if err != nil {
			if err == errEOS {
				return nil
			}
			return err
		}
		if err = d.apply(op); err != nil {
			return err
		}
		if err = d.verifyEOS(); err != nil {
			return err
		}
		panic("read one more op without an error")
	}
	return d.verifyEOS()
}

// errEOS indicates that an EOS marker has been found.
var errEOS = errors.New("EOS marker found")

// readOp decodes the next operation from the compressed stream. It
// returns the operation. If an explicit end of stream marker is
// identified the eos error is returned.
func (d *Decoder) readOp() (op operation, err error) {
	// Value of the end of stream (EOS) marker
	const eosDist = 1<<32 - 1

	state, state2, posState := d.state.states(d.dict.head)

	b, err := d.state.isMatch[state2].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// literal
		op, err := d.decodeLiteral()
		if err != nil {
			return nil, err
		}
		d.state.updateStateLiteral()
		return op, nil
	}
	b, err = d.state.isRep[state].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	if b == 0 {
		// simple match
		d.state.rep[3], d.state.rep[2], d.state.rep[1] =
			d.state.rep[2], d.state.rep[1], d.state.rep[0]

		d.state.updateStateMatch()
		// The length decoder returns the length offset.
		n, err := d.state.lenCodec.Decode(d.rd, posState)
		if err != nil {
			return nil, err
		}
		// The dist decoder returns the distance offset. The actual
		// distance is 1 higher.
		d.state.rep[0], err = d.state.distCodec.Decode(d.rd, n)
		if err != nil {
			return nil, err
		}
		if d.state.rep[0] == eosDist {
			if err = d.handleEOSMarker(); err == nil {
				err = errEOS
			}
			return nil, err
		}
		op = match{n: int(n) + minMatchLen,
			distance: int(d.state.rep[0]) + minDistance}
		return op, nil
	}
	b, err = d.state.isRepG0[state].Decode(d.rd)
	if err != nil {
		return nil, err
	}
	dist := d.state.rep[0]
	if b == 0 {
		// rep match 0
		b, err = d.state.isRepG0Long[state2].Decode(d.rd)
		if err != nil {
			return nil, err
		}
		if b == 0 {
			d.state.updateStateShortRep()
			op = match{n: 1, distance: int(dist) + minDistance}
			return op, nil
		}
	} else {
		b, err = d.state.isRepG1[state].Decode(d.rd)
		if err != nil {
			return nil, err
		}
		if b == 0 {
			dist = d.state.rep[1]
		} else {
			b, err = d.state.isRepG2[state].Decode(d.rd)
			if err != nil {
				return nil, err
			}
			if b == 0 {
				dist = d.state.rep[2]
			} else {
				dist = d.state.rep[3]
				d.state.rep[3] = d.state.rep[2]
			}
			d.state.rep[2] = d.state.rep[1]
		}
		d.state.rep[1] = d.state.rep[0]
		d.state.rep[0] = dist
	}
	n, err := d.state.repLenCodec.Decode(d.rd, posState)
	if err != nil {
		return nil, err
	}
	d.state.updateStateRep()
	op = match{n: int(n) + minMatchLen, distance: int(dist) + minDistance}
	return op, nil
}

// Printf produces output if d.debug is not zero. It uses fmt.Printf
// for the implementation.
func (d *Decoder) Printf(format string, args ...interface{}) (n int, err error) {
	if d.debug != 0 {
		return fmt.Printf(format, args...)
	}
	return 0, nil
}

// apply takes the operation and transforms the decoder dictionary accordingly.
func (d *Decoder) apply(op operation) error {
	d.opCounter++
	d.Printf("%d %s\n", d.opCounter, op)
	switch x := op.(type) {
	case match:
		return d.dict.WriteMatch(x.distance, x.n)
	case lit:
		return d.dict.WriteByte(x.b)
	}
	panic("op is neither a match nor a literal")
}

// fillDict fills the dictionary unless no space for new data is
// available in the dictionary.
func (d *Decoder) fillDict() error {
	if d.flags&ceos != 0 {
		return nil
	}
	for d.dict.Available() >= maxMatchLen {
		op, err := d.readOp()
		switch err {
		case nil:
			break
		case errEOS:
			return nil
		case io.EOF:
			d.flags |= ceos
			return io.ErrUnexpectedEOF
		default:
			return err
		}
		if err = d.apply(op); err != nil {
			return err
		}
		if d.flags&CNoUncompressedSize == 0 && d.Uncompressed() >=
			d.uncompressedSize {

			return d.handleEOS()
		}
		if d.flags&CNoCompressedSize == 0 && d.rd.r.n >= d.rd.r.limit {
			return d.handleEOS()
		}
	}
	return nil
}

// fillDictUncompressed fills the dictionary if the input stream isn't
// compressed.
func (d *Decoder) fillDictUncompressed() error {
	if d.flags&CUncompressed == 0 {
		panic("Uncompressed flag not set")
	}
	if d.flags&ceos != 0 {
		return nil
	}
	for d.dict.Available() >= 0 {
		_, err := io.CopyN(&d.dict, d.lr, int64(d.dict.Available()))
		if err != nil {
			if err == io.EOF {
				d.flags |= ceos
				if d.lr.N != 0 {
					return errUncompressedSize
				}
				return nil
			}
		}
	}
	return nil
}

// Errors that may be returned while decoding data.
var (
	errMissingEOSMarker = errors.New("EOS marker is missing")
	errMoreData         = errors.New("more data after EOS")
	errCompressedSize   = errors.New("compressed size wrong")
	errUncompressedSize = errors.New("uncompressed size wrong")
)

// Read reads data from the buffer. If no more data is available EOF is
// returned.
func (d *Decoder) Read(p []byte) (n int, err error) {
	fillDict := d.fillDict
	if d.flags&CUncompressed != 0 {
		fillDict = d.fillDictUncompressed
	}

	var k int
	for n < len(p) {
		if err = fillDict(); err != nil {
			return
		}
		// Read of decoder dict never returns an error.
		k, err = d.dict.Read(p[n:])
		if err != nil {
			panic(fmt.Errorf("dictionary read error %s", err))
		}
		if k == 0 && d.flags&ceos != 0 {
			return n, io.EOF
		}
		n += k
	}
	return
}

// Compressed returns the number of compressed bytes read.
func (d *Decoder) Compressed() int64 {
	return d.rd.Compressed()
}

// Uncompressed returns the number of uncompressed bytes decoded.
func (d *Decoder) Uncompressed() int64 {
	return d.dict.head - d.start
}
<|endoftext|>


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

package lzma

import (
	"errors"
	"io"
)

// Reader2Params defines the LZMA2 reader parameters. The defaults are
// defined by Reader2Defaults.
type Reader2Params struct {
	DictCap int
}

// Reader2Defaults define the defaults for the reader parameters.
var Reader2Defaults = Reader2Params{
	DictCap: 8 * 1024 * 1024,
}

// Verify verifies the LZMA2 reader parameters for correctness.
func (p *Reader2Params) Verify() error {
	return verifyDictCap(p.DictCap)
}

// Reader2 supports the reading of LZMA2 chunk sequences. Note that the
// first chunk should have a dictionary reset and the first compressed
// chunk a properties reset. The chunk sequence may not be terminated by
// an end-of-stream chunk.
type Reader2 struct {
	r   io.Reader
	err error

	dict        *decoderDict
	ur          *uncompressedReader
	decoder     *decoder
	chunkReader io.Reader

	cstate chunkState
	ctype  chunkType
}

// NewReader2 creates a reader for an LZMA2 chunk sequence with the given
// dictionary capacity.
func NewReader2(lzma2 io.Reader, dictCap int) (r *Reader2, err error) {
	params := Reader2Defaults
	params.DictCap = dictCap
	return NewReader2Params(lzma2, &params)
}

// NewReader2Params creates a new LZMA2 reader using the given
// parameters.
func NewReader2Params(lzma2 io.Reader, params *Reader2Params) (r *Reader2, err error) {
	if err = params.Verify(); err != nil {
		return nil, err
	}
	r = &Reader2{
		r:      lzma2,
		cstate: start,
	}
	r.dict, err = newDecoderDict(params.DictCap)
	if err != nil {
		return nil, err
	}
	if err = r.startChunk(); err != nil {
		return nil, err
	}
	return r, nil
}

// uncompressed tests whether the chunk type specifies an uncompressed
// chunk.
func uncompressed(ctype chunkType) bool {
	return ctype == cU || ctype == cUD
}

// startChunk parses a new chunk.
func (r *Reader2) startChunk() error {
	r.chunkReader = nil
	header, err := readChunkHeader(r.r)
	if err != nil {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		return err
	}
	if err = r.cstate.next(header.ctype); err != nil {
		return err
	}
	if r.cstate == stop {
		return io.EOF
	}
	if header.ctype == cUD || header.ctype == cLRND {
		r.dict.Reset()
	}
	size := int64(header.uncompressed) + 1
	if uncompressed(header.ctype) {
		if r.ur != nil {
			r.ur.Reopen(r.r, size)
		} else {
			r.ur = newUncompressedReader(r.r, r.dict, size)
		}
		r.chunkReader = r.ur
		return nil
	}
	br := ByteReader(io.LimitReader(r.r, int64(header.compressed)+1))
	if r.decoder == nil {
		state := newState(header.props)
		r.decoder, err = newDecoder(br, state, r.dict, size)
		if err != nil {
			return err
		}
		r.chunkReader = r.decoder
		return nil
	}
	switch header.ctype {
	case cLR:
		r.decoder.State.Reset()
	case cLRN, cLRND:
		r.decoder.State = newState(header.props)
	}
	err = r.decoder.Reopen(br, size)
	if err != nil {
		return err
	}
	r.chunkReader = r.decoder
	return nil
}

// Read reads data from the LZMA2 chunk sequence.
func (r *Reader2) Read(p []byte) (n int, err error) {
	if r.err != nil {
		return 0, r.err
	}
	for n < len(p) {
		var k int
		k, err = r.chunkReader.Read(p[n:])
		n += k
		if err == io.EOF {
			err = r.startChunk()
		}
		if err != nil {
			r.err = err
			return n, err
		}
		if k == 0 {
			r.err = errors.New("lzma: Reader2 doesn't get data")
			return n, r.err
		}
	}
	return n, nil
}

// EOS returns whether the LZMA2 stream has been terminated by an
// end-of-stream chunk.
func (r *Reader2) EOS() bool {
	return r.cstate == stop
}

// uncompressedReader is used to read uncompressed chunks.
type uncompressedReader struct {
	lr   io.LimitedReader
	Dict *decoderDict
	eof  bool
	err  error
}

// newUncompressedReader initializes a new uncompressedReader.
func newUncompressedReader(r io.Reader, dict *decoderDict, size int64) *uncompressedReader {
	ur := &uncompressedReader{
		lr:   io.LimitedReader{R: r, N: size},
		Dict: dict,
	}
	return ur
}

// Reopen reinitializes an uncompressed reader.
func (ur *uncompressedReader) Reopen(r io.Reader, size int64) {
	ur.err = nil
	ur.eof = false
	ur.lr = io.LimitedReader{R: r, N: size}
}

// fill reads uncompressed data into the dictionary.
func (ur *uncompressedReader) fill() error {
	if !ur.eof {
		n, err := io.CopyN(ur.Dict, &ur.lr, int64(ur.Dict.Available()))
		if err != io.EOF {
			return err
		}
		ur.eof = true
		if n > 0 {
			return nil
		}
	}
	if ur.lr.N != 0 {
		return io.ErrUnexpectedEOF
	}
	return io.EOF
}

// Read reads uncompressed data from the limited reader.
func (ur *uncompressedReader) Read(p []byte) (n int, err error) {
	if ur.err != nil {
		return 0, ur.err
	}
	for {
		var k int
		k, err = ur.Dict.Read(p[n:])
		n += k
		if n >= len(p) {
			return n, nil
		}
		if err != nil {
			break
		}
		err = ur.fill()
		if err != nil {
			break
		}
	}
	ur.err = err
	return n, err
}
<commit_msg>lzma: fixed bug in Read method of Reader2<commit_after>// Copyright 2014-2016 Ulrich Kunitz. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lzma

import (
	"errors"
	"io"
)

// Reader2Params defines the LZMA2 reader parameters. The defaults are
// defined by Reader2Defaults.
type Reader2Params struct {
	DictCap int
}

// Reader2Defaults define the defaults for the reader parameters.
var Reader2Defaults = Reader2Params{
	DictCap: 8 * 1024 * 1024,
}

// Verify verifies the LZMA2 reader parameters for correctness.
func (p *Reader2Params) Verify() error {
	return verifyDictCap(p.DictCap)
}

// Reader2 supports the reading of LZMA2 chunk sequences. Note that the
// first chunk should have a dictionary reset and the first compressed
// chunk a properties reset. The chunk sequence may not be terminated by
// an end-of-stream chunk.
type Reader2 struct {
	r   io.Reader
	err error

	dict        *decoderDict
	ur          *uncompressedReader
	decoder     *decoder
	chunkReader io.Reader

	cstate chunkState
	ctype  chunkType
}

// NewReader2 creates a reader for an LZMA2 chunk sequence with the given
// dictionary capacity.
func NewReader2(lzma2 io.Reader, dictCap int) (r *Reader2, err error) {
	params := Reader2Defaults
	params.DictCap = dictCap
	return NewReader2Params(lzma2, &params)
}

// NewReader2Params creates a new LZMA2 reader using the given
// parameters.
func NewReader2Params(lzma2 io.Reader, params *Reader2Params) (r *Reader2, err error) {
	if err = params.Verify(); err != nil {
		return nil, err
	}
	r = &Reader2{
		r:      lzma2,
		cstate: start,
	}
	r.dict, err = newDecoderDict(params.DictCap)
	if err != nil {
		return nil, err
	}
	if err = r.startChunk(); err != nil {
		return nil, err
	}
	return r, nil
}

// uncompressed tests whether the chunk type specifies an uncompressed
// chunk.
func uncompressed(ctype chunkType) bool {
	return ctype == cU || ctype == cUD
}

// startChunk parses a new chunk.
func (r *Reader2) startChunk() error {
	r.chunkReader = nil
	header, err := readChunkHeader(r.r)
	if err != nil {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		return err
	}
	if err = r.cstate.next(header.ctype); err != nil {
		return err
	}
	if r.cstate == stop {
		return io.EOF
	}
	if header.ctype == cUD || header.ctype == cLRND {
		r.dict.Reset()
	}
	size := int64(header.uncompressed) + 1
	if uncompressed(header.ctype) {
		if r.ur != nil {
			r.ur.Reopen(r.r, size)
		} else {
			r.ur = newUncompressedReader(r.r, r.dict, size)
		}
		r.chunkReader = r.ur
		return nil
	}
	br := ByteReader(io.LimitReader(r.r, int64(header.compressed)+1))
	if r.decoder == nil {
		state := newState(header.props)
		r.decoder, err = newDecoder(br, state, r.dict, size)
		if err != nil {
			return err
		}
		r.chunkReader = r.decoder
		return nil
	}
	switch header.ctype {
	case cLR:
		r.decoder.State.Reset()
	case cLRN, cLRND:
		r.decoder.State = newState(header.props)
	}
	err = r.decoder.Reopen(br, size)
	if err != nil {
		return err
	}
	r.chunkReader = r.decoder
	return nil
}

// Read reads data from the LZMA2 chunk sequence.
func (r *Reader2) Read(p []byte) (n int, err error) {
	if r.err != nil {
		return 0, r.err
	}
	for n < len(p) {
		var k int
		k, err = r.chunkReader.Read(p[n:])
		n += k
		if err != nil {
			if err == io.EOF {
				err = r.startChunk()
				if err == nil {
					continue
				}
			}
			r.err = err
			return n, err
		}
		if k == 0 {
			r.err = errors.New("lzma: Reader2 doesn't get data")
			return n, r.err
		}
	}
	return n, nil
}

// EOS returns whether the LZMA2 stream has been terminated by an
// end-of-stream chunk.
func (r *Reader2) EOS() bool {
	return r.cstate == stop
}

// uncompressedReader is used to read uncompressed chunks.
type uncompressedReader struct {
	lr   io.LimitedReader
	Dict *decoderDict
	eof  bool
	err  error
}

// newUncompressedReader initializes a new uncompressedReader.
func newUncompressedReader(r io.Reader, dict *decoderDict, size int64) *uncompressedReader {
	ur := &uncompressedReader{
		lr:   io.LimitedReader{R: r, N: size},
		Dict: dict,
	}
	return ur
}

// Reopen reinitializes an uncompressed reader.
func (ur *uncompressedReader) Reopen(r io.Reader, size int64) {
	ur.err = nil
	ur.eof = false
	ur.lr = io.LimitedReader{R: r, N: size}
}

// fill reads uncompressed data into the dictionary.
func (ur *uncompressedReader) fill() error {
	if !ur.eof {
		n, err := io.CopyN(ur.Dict, &ur.lr, int64(ur.Dict.Available()))
		if err != io.EOF {
			return err
		}
		ur.eof = true
		if n > 0 {
			return nil
		}
	}
	if ur.lr.N != 0 {
		return io.ErrUnexpectedEOF
	}
	return io.EOF
}

// Read reads uncompressed data from the limited reader.
func (ur *uncompressedReader) Read(p []byte) (n int, err error) {
	if ur.err != nil {
		return 0, ur.err
	}
	for {
		var k int
		k, err = ur.Dict.Read(p[n:])
		n += k
		if n >= len(p) {
			return n, nil
		}
		if err != nil {
			break
		}
		err = ur.fill()
		if err != nil {
			break
		}
	}
	ur.err = err
	return n, err
}
<|endoftext|>


<commit_before>// Copyright 2017 the gousb Authors.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package usb

import (
	"errors"
	"sync"
	"time"
)

type fakeTransfer struct {
	// done is the channel that needs to be closed when the transfer has finished.
	done chan struct{}
	// buf is the slice for reading/writing data between the submit() and wait() returning.
	buf []byte
	// status will be returned by wait() on this transfer
	status TransferStatus
	// length is the number of bytes used from the buffer (write) or available
	// in the buffer (read).
	length int
}

type fakeLibusb struct {
	libusbIntf

	mu sync.Mutex
	// ts has a map of all allocated transfers, indexed by the pointer of
	// underlying libusbTransfer.
	ts map[*libusbTransfer]*fakeTransfer
	// submitted receives a fakeTransfers when submit() is called.
	submitted chan *fakeTransfer
	// handlers is a map of device handles pointing at opened devices.
	handlers map[*libusbDevHandle]*libusbDevice
}

func (f *fakeLibusb) alloc(_ *libusbDevHandle, _ uint8, _ TransferType, _ time.Duration, _ int, buf []byte) (*libusbTransfer, error) {
	f.mu.Lock()
	defer f.mu.Unlock()
	t := new(libusbTransfer)
	f.ts[t] = &fakeTransfer{buf: buf}
	return t, nil
}

func (f *fakeLibusb) submit(t *libusbTransfer, done chan struct{}) error {
	f.mu.Lock()
	ft := f.ts[t]
	f.mu.Unlock()
	ft.done = done
	f.submitted <- ft
	return nil
}

func (f *fakeLibusb) cancel(t *libusbTransfer) error { return nil }
func (f *fakeLibusb) free(t *libusbTransfer) {
	f.mu.Lock()
	defer f.mu.Unlock()
	delete(f.ts, t)
}

func (f *fakeLibusb) data(t *libusbTransfer) (int, TransferStatus) {
	f.mu.Lock()
	defer f.mu.Unlock()
	return f.ts[t].length, f.ts[t].status
}

func (f *fakeLibusb) waitForSubmitted() *fakeTransfer {
	return <-f.submitted
}

func newFakeLibusb() *fakeLibusb {
	return &fakeLibusb{
		ts:         make(map[*libusbTransfer]*fakeTransfer),
		submitted:  make(chan *fakeTransfer, 10),
		handlers:   make(map[*libusbDevHandle]*libusbDevice),
		libusbIntf: libusbImpl{},
	}
}

var (
	fakeDev1 = new(libusbDevice)
	fakeDev2 = new(libusbDevice)
)

func (f *fakeLibusb) getDevices(*libusbContext) ([]*libusbDevice, error) {
	return []*libusbDevice{fakeDev1, fakeDev2}, nil
}

func (f *fakeLibusb) getDeviceDesc(d *libusbDevice) (*Descriptor, error) {
	switch d {
	case fakeDev1:
		// Bus 001 Device 001: ID 9999:0001
		// One config, one interface, one setup,
		// two endpoints: 0x01 write, 0x82 read.
		return &Descriptor{
			Bus:      1,
			Address:  1,
			Spec:     USB_2_0,
			Device:   BCD(0x0100), // 1.00
			Vendor:   ID(0x9999),
			Product:  ID(0x0001),
			Protocol: 255,
			Configs: []ConfigInfo{{
				Config:     1,
				Attributes: uint8(TRANSFER_TYPE_BULK),
				MaxPower:   50, // * 2mA
				Interfaces: []InterfaceInfo{{
					Number: 0,
					Setups: []InterfaceSetup{{
						Number:    0,
						Alternate: 0,
						IfClass:   uint8(CLASS_VENDOR_SPEC),
						Endpoints: []EndpointInfo{},
					}},
				}},
			}},
		}, nil
	case fakeDev2:
		return &Descriptor{}, nil
	}
	return nil, errors.New("invalid USB device")
}

func (f *fakeLibusb) dereference(d *libusbDevice) {}

func (f *fakeLibusb) open(d *libusbDevice) (*libusbDevHandle, error) {
	h := new(libusbDevHandle)
	f.mu.Lock()
	defer f.mu.Unlock()
	f.handlers[h] = d
	return h, nil
}

func (f *fakeLibusb) close(h *libusbDevHandle) {
	f.mu.Lock()
	defer f.mu.Unlock()
	delete(f.handlers, h)
}
<commit_msg>add two device descriptors<commit_after>// Copyright 2017 the gousb Authors.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package usb

import (
	"fmt"
	"sync"
	"time"
	"unsafe"
)

type fakeTransfer struct {
	// done is the channel that needs to be closed when the transfer has finished.
	done chan struct{}
	// buf is the slice for reading/writing data between the submit() and wait() returning.
	buf []byte
	// status will be returned by wait() on this transfer
	status TransferStatus
	// length is the number of bytes used from the buffer (write) or available
	// in the buffer (read).
	length int
}

type fakeLibusb struct {
	libusbIntf

	mu sync.Mutex
	// ts has a map of all allocated transfers, indexed by the pointer of
	// underlying libusbTransfer.
	ts map[*libusbTransfer]*fakeTransfer
	// submitted receives a fakeTransfers when submit() is called.
	submitted chan *fakeTransfer
	// handlers is a map of device handles pointing at opened devices.
	handlers map[*libusbDevHandle]*libusbDevice
}

func (f *fakeLibusb) alloc(_ *libusbDevHandle, _ uint8, _ TransferType, _ time.Duration, _ int, buf []byte) (*libusbTransfer, error) {
	f.mu.Lock()
	defer f.mu.Unlock()
	t := new(libusbTransfer)
	f.ts[t] = &fakeTransfer{buf: buf}
	return t, nil
}

func (f *fakeLibusb) submit(t *libusbTransfer, done chan struct{}) error {
	f.mu.Lock()
	ft := f.ts[t]
	f.mu.Unlock()
	ft.done = done
	f.submitted <- ft
	return nil
}

func (f *fakeLibusb) cancel(t *libusbTransfer) error { return nil }
func (f *fakeLibusb) free(t *libusbTransfer) {
	f.mu.Lock()
	defer f.mu.Unlock()
	delete(f.ts, t)
}

func (f *fakeLibusb) data(t *libusbTransfer) (int, TransferStatus) {
	f.mu.Lock()
	defer f.mu.Unlock()
	return f.ts[t].length, f.ts[t].status
}

func (f *fakeLibusb) waitForSubmitted() *fakeTransfer {
	return <-f.submitted
}

func newFakeLibusb() *fakeLibusb {
	return &fakeLibusb{
		ts:         make(map[*libusbTransfer]*fakeTransfer),
		submitted:  make(chan *fakeTransfer, 10),
		handlers:   make(map[*libusbDevHandle]*libusbDevice),
		libusbIntf: libusbImpl{},
	}
}

var (
	fakeDevices = map[*libusbDevice]*Descriptor{
		// Bus 001 Device 001: ID 9999:0001
		// One config, one interface, one setup,
		// two endpoints: 0x01 OUT, 0x82 IN.
		// TODO(https://github.com/golang/go/issues/19487): replace with
		// new(libusbDevice)
		(*libusbDevice)(unsafe.Pointer(uintptr(1))): &Descriptor{
			Bus:      1,
			Address:  1,
			Spec:     USB_2_0,
			Device:   BCD(0x0100), // 1.00
			Vendor:   ID(0x9999),
			Product:  ID(0x0001),
			Protocol: 255,
			Configs: []ConfigInfo{{
				Config:   1,
				MaxPower: 50, // * 2mA
				Interfaces: []InterfaceInfo{{
					Number: 0,
					Setups: []InterfaceSetup{{
						Number:    0,
						Alternate: 0,
						IfClass:   uint8(CLASS_VENDOR_SPEC),
						Endpoints: []EndpointInfo{{
							Address:       uint8(0x01 | ENDPOINT_DIR_OUT),
							Attributes:    uint8(TRANSFER_TYPE_BULK),
							MaxPacketSize: 512,
						}, {
							Address:       uint8(0x02 | ENDPOINT_DIR_IN),
							Attributes:    uint8(TRANSFER_TYPE_BULK),
							MaxPacketSize: 512,
						}},
					}},
				}},
			}},
		},
		// Bus 001 Device 002: ID 8888:0002
		// One config, two interfaces. interface #0 with no endpoints,
		// interface #1 with two alt setups with different packet sizes for
		// endpoints. Two isochronous endpoints, 0x05 OUT and 0x86 OUT.
		// TODO(https://github.com/golang/go/issues/19487): replace with
		// new(libusbDevice)
		(*libusbDevice)(unsafe.Pointer(uintptr(2))): &Descriptor{
			Bus:      1,
			Address:  2,
			Spec:     USB_2_0,
			Device:   BCD(0x0103), // 1.03
			Vendor:   ID(0x8888),
			Product:  ID(0x0002),
			Protocol: 255,
			Configs: []ConfigInfo{{
				Config:   1,
				MaxPower: 50, // * 2mA
				Interfaces: []InterfaceInfo{{
					Number: 0,
					Setups: []InterfaceSetup{{
						Number:    0,
						Alternate: 0,
						IfClass:   uint8(CLASS_VENDOR_SPEC),
					}},
				}, {
					Number: 1,
					Setups: []InterfaceSetup{{
						Number:    1,
						Alternate: 0,
						IfClass:   uint8(CLASS_VENDOR_SPEC),
						Endpoints: []EndpointInfo{{
							Address:       uint8(0x05 | ENDPOINT_DIR_OUT),
							Attributes:    uint8(TRANSFER_TYPE_ISOCHRONOUS),
							MaxPacketSize: 2<<11 | 1024,
							MaxIsoPacket:  3 * 1024,
						}, {
							Address:       uint8(0x06 | ENDPOINT_DIR_IN),
							Attributes:    uint8(TRANSFER_TYPE_ISOCHRONOUS),
							MaxPacketSize: 2<<11 | 1024,
							MaxIsoPacket:  3 * 1024,
						}},
					}, {
						Number:    1,
						Alternate: 1,
						IfClass:   uint8(CLASS_VENDOR_SPEC),
						Endpoints: []EndpointInfo{{
							Address:       uint8(0x05 | ENDPOINT_DIR_OUT),
							Attributes:    uint8(TRANSFER_TYPE_ISOCHRONOUS),
							MaxPacketSize: 1<<11 | 1024,
							MaxIsoPacket:  2 * 1024,
						}, {
							Address:       uint8(0x06 | ENDPOINT_DIR_IN),
							Attributes:    uint8(TRANSFER_TYPE_ISOCHRONOUS),
							MaxPacketSize: 1<<11 | 1024,
							MaxIsoPacket:  2 * 1024,
						}},
					}, {
						Number:    1,
						Alternate: 2,
						IfClass:   uint8(CLASS_VENDOR_SPEC),
						Endpoints: []EndpointInfo{{
							Address:       uint8(0x05 | ENDPOINT_DIR_OUT),
							Attributes:    uint8(TRANSFER_TYPE_ISOCHRONOUS),
							MaxPacketSize: 1024,
							MaxIsoPacket:  1024,
						}, {
							Address:       uint8(0x06 | ENDPOINT_DIR_IN),
							Attributes:    uint8(TRANSFER_TYPE_ISOCHRONOUS),
							MaxPacketSize: 1024,
							MaxIsoPacket:  1024,
						}},
					}},
				}},
			}},
		},
	}
)

func (f *fakeLibusb) getDevices(*libusbContext) ([]*libusbDevice, error) {
	ret := make([]*libusbDevice, 0, len(fakeDevices))
	for d := range fakeDevices {
		ret = append(ret, d)
	}
	return ret, nil
}

func (f *fakeLibusb) getDeviceDesc(d *libusbDevice) (*Descriptor, error) {
	if desc, ok := fakeDevices[d]; ok {
		return desc, nil
	}
	return nil, fmt.Errorf("invalid USB device %p", d)
}

func (f *fakeLibusb) dereference(d *libusbDevice) {}

func (f *fakeLibusb) open(d *libusbDevice) (*libusbDevHandle, error) {
	h := new(libusbDevHandle)
	f.mu.Lock()
	defer f.mu.Unlock()
	f.handlers[h] = d
	return h, nil
}

func (f *fakeLibusb) close(h *libusbDevHandle) {
	f.mu.Lock()
	defer f.mu.Unlock()
	delete(f.handlers, h)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"log"
	"strings"
	"time"
)

// Match represents a game being played
type Match struct {
	Players       []Player      `json:"players"`
	Judges        []Judge       `json:"judges"`
	Kind          string        `json:"kind"`
	Index         int           `json:"index"`
	Length        int           `json:"length"`
	Started       time.Time     `json:"started"`
	Ended         time.Time     `json:"ended"`
	Tournament    *Tournament   `json:"-"`
	Commits       []MatchCommit `json:"commits"`
	presentColors map[string]bool
}

// MatchCommit is a state commit for a round of a match
type MatchCommit struct {
	Kills     [][]int `json:"kills"`
	Shots     []bool  `json:"shots"`
	Committed string  `json:"comitted"` // ISO-8601
}

// NewMatch creates a new Match for usage!
func NewMatch(t *Tournament, index int, kind string) *Match {
	m := Match{
		Index:      index,
		Kind:       kind,
		Tournament: t,
		Length:     10,
	}
	m.presentColors = make(map[string]bool)

	// Finals are longer <3
	if kind == "final" {
		m.Length = 20
	}

	return &m
}

func (m *Match) String() string {
	var tempo string
	var name string

	if !m.IsStarted() {
		tempo = "not started"
	} else if m.IsEnded() {
		tempo = "ended"
	} else {
		tempo = "playing"
	}

	if m.Kind == "final" {
		name = "Final"
	} else {
		name = fmt.Sprintf("%s %d", strings.Title(m.Kind), m.Index+1)
	}

	names := make([]string, 0, len(m.Players))
	for _, p := range m.Players {
		names = append(names, p.Name())
	}

	return fmt.Sprintf(
		"<%s: %s - %s>",
		name,
		strings.Join(names, " / "),
		tempo,
	)
}

// Title returns a title string
func (m *Match) Title() string {
	l := 2
	if m.Kind == "final" {
		return "Final"
	} else if m.Kind == "tryout" {
		l = len(m.Tournament.Tryouts)
	}

	out := fmt.Sprintf(
		"%s %d/%d",
		strings.Title(m.Kind),
		m.Index+1,
		l,
	)
	return out
}

// URL builds the URL to the match
func (m *Match) URL() string {
	out := fmt.Sprintf(
		"/%s/%s/%d/",
		m.Tournament.ID,
		m.Kind,
		m.Index,
	)
	return out
}

// AddPlayer adds a player to the match
func (m *Match) AddPlayer(p Player) error {
	if len(m.Players) == 4 {
		return errors.New("cannot add fifth player")
	}

	// Reset all possible scores
	p.Reset()

	c := p.PreferredColor()
	p.OriginalColor = c
	if _, ok := m.presentColors[c]; ok {
		// Color is already present - give the player a new random one.
		c = Colors.Available(m).Random()
		log.Printf("Corrected color of %s from %s to %s", p.Person.Nick, p.OriginalColor, c)
	}

	// Set the player color
	p.Color = c
	m.presentColors[c] = true

	// Also set the match pointer
	p.Match = m

	m.Players = append(m.Players, p)

	return nil
}

// UpdatePlayer updates a player for the given match
func (m *Match) UpdatePlayer(p Player) error {
	for i, o := range m.Players {
		if o.Name() == p.Name() {
			m.Players[i] = p
		}
	}
	return nil
}

// Commit adds a state of the players
func (m *Match) Commit(c MatchCommit) {
	for i, score := range c.Kills {
		shotGiven := false
		ups := score[0]
		downs := score[1]

		// If the score is 3, then this player killed everyone else.
		// Count that as a sweep.
		if ups == 3 {
			m.Players[i].AddSweep()
			// Since AddSweep gives a shot, we shouldn't give another further down.
			shotGiven = true

			// If we have a sweep and a down, we need to redact the
			// extra shot, because no player should get more than
			// one shot per round. Removing one from here makes
			// sure that the `downs` calculation below still adds
			// the one.
			if downs == 1 {
				m.Players[i].RemoveShot()
			}
		} else if ups > 0 {
			m.Players[i].AddKill(ups)
		}

		if downs != 0 {
			m.Players[i].AddSelf()
			shotGiven = true
		}

		if c.Shots[i] && !shotGiven {
			m.Players[i].AddShot()
		}
	}

	m.Commits = append(m.Commits, c)
	_ = m.Tournament.Persist()
}

// Start starts the match
func (m *Match) Start() error {
	if !m.Started.IsZero() {
		return errors.New("match already started")
	}

	// If there are not four players in the match, we need to populate
	// the match with runnerups from the tournament
	if len(m.Players) != 4 {
		m.Tournament.PopulateRunnerups(m)
	}

	for i := range m.Players {
		m.Players[i].Reset()
		m.Players[i].Match = m
	}

	m.Started = time.Now()
	if m.Tournament != nil {
		m.Tournament.Persist()
	}
	return nil
}

// End signals that the match has ended
//
// It is also the place that moves players into either the Runnerup bracket
// or into their place in the semis.
func (m *Match) End() error {
	if !m.Ended.IsZero() {
		return errors.New("match already ended")
	}

	// Give the winner one last shot
	ps := ByScore(m.Players)
	winner := ps[0].Name()
	for i, p := range m.Players {
		if p.Name() == winner {
			m.Players[i].AddShot()
			break
		}
	}

	m.Ended = time.Now()
	// TODO: This is for the tests not to break. Fix by setting up better tests.
	if m.Tournament != nil {
		if m.Kind == "final" {
			m.Tournament.AwardMedals(m)
		} else {
			m.Tournament.MovePlayers(m)
		}

		m.Tournament.Persist()
	}
	return nil
}

// IsStarted returns boolean whether the match has started or not
func (m *Match) IsStarted() bool {
	return !m.Started.IsZero()
}

// IsEnded returns boolean whether the match has ended or not
func (m *Match) IsEnded() bool {
	return !m.Ended.IsZero()
}

// CanStart returns boolean the match can be controlled or not
func (m *Match) CanStart() bool {
	return !m.IsStarted() && !m.IsEnded()
}

// CanEnd returns boolean whether the match can be ended or not
func (m *Match) CanEnd() bool {
	if !m.IsOpen() {
		return false
	}
	for _, p := range m.Players {
		if p.Kills >= m.Length {
			return true
		}
	}
	return false
}

// IsOpen returns boolean the match can be controlled or not
func (m *Match) IsOpen() bool {
	return m.IsStarted() && !m.IsEnded()
}

// NewMatchCommit makes a new MatchCommit object from a CommitRequest
func NewMatchCommit(c CommitRequest) MatchCommit {
	states := c.State
	m := MatchCommit{
		[][]int{
			[]int{states[0].Ups, states[0].Downs},
			[]int{states[1].Ups, states[1].Downs},
			[]int{states[2].Ups, states[2].Downs},
			[]int{states[3].Ups, states[3].Downs},
		},
		[]bool{
			states[0].Shot,
			states[1].Shot,
			states[2].Shot,
			states[3].Shot,
		},
		// ISO-8601 timestamp
		time.Now().UTC().Format(time.RFC3339),
	}

	return m
}
<commit_msg>Remove pointless call to PopulateRunnerups()<commit_after>package main

import (
	"errors"
	"fmt"
	"log"
	"strings"
	"time"
)

// Match represents a game being played
type Match struct {
	Players       []Player      `json:"players"`
	Judges        []Judge       `json:"judges"`
	Kind          string        `json:"kind"`
	Index         int           `json:"index"`
	Length        int           `json:"length"`
	Started       time.Time     `json:"started"`
	Ended         time.Time     `json:"ended"`
	Tournament    *Tournament   `json:"-"`
	Commits       []MatchCommit `json:"commits"`
	presentColors map[string]bool
}

// MatchCommit is a state commit for a round of a match
type MatchCommit struct {
	Kills     [][]int `json:"kills"`
	Shots     []bool  `json:"shots"`
	Committed string  `json:"comitted"` // ISO-8601
}

// NewMatch creates a new Match for usage!
func NewMatch(t *Tournament, index int, kind string) *Match {
	m := Match{
		Index:      index,
		Kind:       kind,
		Tournament: t,
		Length:     10,
	}
	m.presentColors = make(map[string]bool)

	// Finals are longer <3
	if kind == "final" {
		m.Length = 20
	}

	return &m
}

func (m *Match) String() string {
	var tempo string
	var name string

	if !m.IsStarted() {
		tempo = "not started"
	} else if m.IsEnded() {
		tempo = "ended"
	} else {
		tempo = "playing"
	}

	if m.Kind == "final" {
		name = "Final"
	} else {
		name = fmt.Sprintf("%s %d", strings.Title(m.Kind), m.Index+1)
	}

	names := make([]string, 0, len(m.Players))
	for _, p := range m.Players {
		names = append(names, p.Name())
	}

	return fmt.Sprintf(
		"<%s: %s - %s>",
		name,
		strings.Join(names, " / "),
		tempo,
	)
}

// Title returns a title string
func (m *Match) Title() string {
	l := 2
	if m.Kind == "final" {
		return "Final"
	} else if m.Kind == "tryout" {
		l = len(m.Tournament.Tryouts)
	}

	out := fmt.Sprintf(
		"%s %d/%d",
		strings.Title(m.Kind),
		m.Index+1,
		l,
	)
	return out
}

// URL builds the URL to the match
func (m *Match) URL() string {
	out := fmt.Sprintf(
		"/%s/%s/%d/",
		m.Tournament.ID,
		m.Kind,
		m.Index,
	)
	return out
}

// AddPlayer adds a player to the match
func (m *Match) AddPlayer(p Player) error {
	if len(m.Players) == 4 {
		return errors.New("cannot add fifth player")
	}

	// Reset all possible scores
	p.Reset()

	c := p.PreferredColor()
	p.OriginalColor = c
	if _, ok := m.presentColors[c]; ok {
		// Color is already present - give the player a new random one.
		c = Colors.Available(m).Random()
		log.Printf("Corrected color of %s from %s to %s", p.Person.Nick, p.OriginalColor, c)
	}

	// Set the player color
	p.Color = c
	m.presentColors[c] = true

	// Also set the match pointer
	p.Match = m

	m.Players = append(m.Players, p)

	return nil
}

// UpdatePlayer updates a player for the given match
func (m *Match) UpdatePlayer(p Player) error {
	for i, o := range m.Players {
		if o.Name() == p.Name() {
			m.Players[i] = p
		}
	}
	return nil
}

// Commit adds a state of the players
func (m *Match) Commit(c MatchCommit) {
	for i, score := range c.Kills {
		shotGiven := false
		ups := score[0]
		downs := score[1]

		// If the score is 3, then this player killed everyone else.
		// Count that as a sweep.
		if ups == 3 {
			m.Players[i].AddSweep()
			// Since AddSweep gives a shot, we shouldn't give another further down.
			shotGiven = true

			// If we have a sweep and a down, we need to redact the
			// extra shot, because no player should get more than
			// one shot per round. Removing one from here makes
			// sure that the `downs` calculation below still adds
			// the one.
			if downs == 1 {
				m.Players[i].RemoveShot()
			}
		} else if ups > 0 {
			m.Players[i].AddKill(ups)
		}

		if downs != 0 {
			m.Players[i].AddSelf()
			shotGiven = true
		}

		if c.Shots[i] && !shotGiven {
			m.Players[i].AddShot()
		}
	}

	m.Commits = append(m.Commits, c)
	_ = m.Tournament.Persist()
}

// Start starts the match
func (m *Match) Start() error {
	if !m.Started.IsZero() {
		return errors.New("match already started")
	}

	for i := range m.Players {
		m.Players[i].Reset()
		m.Players[i].Match = m
	}

	m.Started = time.Now()
	if m.Tournament != nil {
		m.Tournament.Persist()
	}
	return nil
}

// End signals that the match has ended
//
// It is also the place that moves players into either the Runnerup bracket
// or into their place in the semis.
func (m *Match) End() error {
	if !m.Ended.IsZero() {
		return errors.New("match already ended")
	}

	// Give the winner one last shot
	ps := ByScore(m.Players)
	winner := ps[0].Name()
	for i, p := range m.Players {
		if p.Name() == winner {
			m.Players[i].AddShot()
			break
		}
	}

	m.Ended = time.Now()
	// TODO: This is for the tests not to break. Fix by setting up better tests.
	if m.Tournament != nil {
		if m.Kind == "final" {
			m.Tournament.AwardMedals(m)
		} else {
			m.Tournament.MovePlayers(m)
		}

		m.Tournament.Persist()
	}
	return nil
}

// IsStarted returns boolean whether the match has started or not
func (m *Match) IsStarted() bool {
	return !m.Started.IsZero()
}

// IsEnded returns boolean whether the match has ended or not
func (m *Match) IsEnded() bool {
	return !m.Ended.IsZero()
}

// CanStart returns boolean the match can be controlled or not
func (m *Match) CanStart() bool {
	return !m.IsStarted() && !m.IsEnded()
}

// CanEnd returns boolean whether the match can be ended or not
func (m *Match) CanEnd() bool {
	if !m.IsOpen() {
		return false
	}
	for _, p := range m.Players {
		if p.Kills >= m.Length {
			return true
		}
	}
	return false
}

// IsOpen returns boolean the match can be controlled or not
func (m *Match) IsOpen() bool {
	return m.IsStarted() && !m.IsEnded()
}

// NewMatchCommit makes a new MatchCommit object from a CommitRequest
func NewMatchCommit(c CommitRequest) MatchCommit {
	states := c.State
	m := MatchCommit{
		[][]int{
			[]int{states[0].Ups, states[0].Downs},
			[]int{states[1].Ups, states[1].Downs},
			[]int{states[2].Ups, states[2].Downs},
			[]int{states[3].Ups, states[3].Downs},
		},
		[]bool{
			states[0].Shot,
			states[1].Shot,
			states[2].Shot,
			states[3].Shot,
		},
		// ISO-8601 timestamp
		time.Now().UTC().Format(time.RFC3339),
	}

	return m
}
<|endoftext|>