<commit_before>package spotify

import (
	"crypto/tls"
	"errors"
	"net/http"
	"os"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
)

const (
	// AuthURL is the URL to Spotify Accounts Service's OAuth2 endpoint.
	AuthURL = "https://accounts.spotify.com/authorize"
	// TokenURL is the URL to the Spotify Accounts Service's OAuth2
	// token endpoint.
	TokenURL = "https://accounts.spotify.com/api/token"
)

// Scopes let you specify exactly which types of data your application wants to access.
// The set of scopes you pass in your authentication request determines what access the
// permissions the user is asked to grant.
const (
	// ScopePlaylistReadPrivate seeks permission to read
	// a user's private playlists.
	ScopePlaylistReadPrivate = "playlist-read-private"
	// ScopePlaylistModifyPublic seeks write access
	// to a user's public playlists.
	ScopePlaylistModifyPublic = "playlist-modify-public"
	// ScopePlaylistModifyPrivate seeks write access to
	// a user's private playlists.
	ScopePlaylistModifyPrivate = "playlist-modify-private"
	// ScopePlaylistReadCollaborative seeks permission to
	// access a user's collaborative playlists.
	ScopePlaylistReadCollaborative = "playlist-read-collaborative"
	// ScopeUserFollowModify seeks write/delete access to
	// the list of artists and other users that a user follows.
	ScopeUserFollowModify = "user-follow-modify"
	// ScopeUserFollowRead seeks read access to the list of
	// artists and other users that a user follows.
	ScopeUserFollowRead = "user-follow-read"
	// ScopeUserLibraryModify seeks write/delete acess to a
	// user's "Your Music" library.
	ScopeUserLibraryModify = "user-library-modify"
	// ScopeUserLibraryRead seeks read access to a user's "Your Music" library.
	ScopeUserLibraryRead = "user-library-read"
	// ScopeUserReadPrivate seeks read access to a user's
	// subsription details (type of user account).
	ScopeUserReadPrivate = "user-read-private"
	// ScopeUserReadEmail seeks read access to a user's email address.
	ScopeUserReadEmail = "user-read-email"
	// ScopeUserReadBirthdate seeks read access to a user's birthdate.
	ScopeUserReadBirthdate = "user-read-birthdate"
)

// Authenticator provides convenience functions for implementing the OAuth2 flow.
// You should always use `NewAuthenticator` to make them.
//
// Example:
//
//     a := spotify.NewAuthenticator(redirectURL, spotify.ScopeUserLibaryRead, spotify.ScopeUserFollowRead)
//     // direct user to Spotify to log in
//     http.Redirect(w, r, a.AuthURL("state-string"), http.StatusFound)
//
//     // then, in redirect handler:
//     token, err := a.Token(state, r)
//     client := a.NewClient(token)
//
type Authenticator struct {
	config  *oauth2.Config
	context context.Context
}

// NewAuthenticator creates an authenticator which is used to implement the
// OAuth2 authorization flow.  The redirectURL must exactly match one of the
// URLs specified in your Spotify developer account.
//
// By default, NewAuthenticator pulls your client ID and secret key from the
// SPOTIFY_ID and SPOTIFY_SECRET environment variables.  If you'd like to provide
// them from some other source, you can call `SetAuthInfo(id, key)` on the
// returned authenticator.
func NewAuthenticator(redirectURL string, scopes ...string) Authenticator {
	cfg := &oauth2.Config{
		ClientID:     os.Getenv("SPOTIFY_ID"),
		ClientSecret: os.Getenv("SPOTIFY_SECRET"),
		RedirectURL:  redirectURL,
		Scopes:       scopes,
		Endpoint: oauth2.Endpoint{
			AuthURL:  AuthURL,
			TokenURL: TokenURL,
		},
	}

	// disable HTTP/2 for DefaultClient, see: https://github.com/zmb3/spotify/issues/20
	tr := &http.Transport{
		TLSNextProto: map[string]func(authority string, c *tls.Conn) http.RoundTripper{},
	}
	ctx := context.WithValue(context.Background(), oauth2.HTTPClient, &http.Client{Transport: tr})
	return Authenticator{
		config:  cfg,
		context: ctx,
	}
}

// SetAuthInfo overwrites the client ID and secret key used by the authenticator.
// You can use this if you don't want to store this information in environment variables.
func (a *Authenticator) SetAuthInfo(clientID, secretKey string) {
	a.config.ClientID = clientID
	a.config.ClientSecret = secretKey
}

// AuthURL returns a URL to the the Spotify Accounts Service's OAuth2 endpoint.
//
// State is a token to protect the user from CSRF attacks.  You should pass the
// same state to `Token`, where it will be validated.  For more info, refer to
// http://tools.ietf.org/html/rfc6749#section-10.12.
func (a Authenticator) AuthURL(state string) string {
	return a.config.AuthCodeURL(state)
}

// Token pulls an authorization code from an HTTP request and attempts to exchange
// it for an access token.  The standard use case is to call Token from the handler
// that handles requests to your application's redirect URL.
func (a Authenticator) Token(state string, r *http.Request) (*oauth2.Token, error) {
	values := r.URL.Query()
	if e := values.Get("error"); e != "" {
		return nil, errors.New("spotify: auth failed - " + e)
	}
	code := values.Get("code")
	if code == "" {
		return nil, errors.New("spotify: didn't get access code")
	}
	actualState := values.Get("state")
	if actualState != state {
		return nil, errors.New("spotify: redirect state parameter doesn't match")
	}
	return a.config.Exchange(a.context, code)
}

// Exchange is like Token, except it allows you to manually specify the access
// code instead of pulling it out of an HTTP request.
func (a Authenticator) Exchange(code string) (*oauth2.Token, error) {
	return a.config.Exchange(a.context, code)
}

// NewClient creates a Client that will use the specified access token for its API requests.
func (a Authenticator) NewClient(token *oauth2.Token) Client {
	client := a.config.Client(a.context, token)
	return Client{
		http: client,
	}
}
<commit_msg>update Token on NewClient (#26)<commit_after>package spotify

import (
	"crypto/tls"
	"errors"
	"net/http"
	"os"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
)

const (
	// AuthURL is the URL to Spotify Accounts Service's OAuth2 endpoint.
	AuthURL = "https://accounts.spotify.com/authorize"
	// TokenURL is the URL to the Spotify Accounts Service's OAuth2
	// token endpoint.
	TokenURL = "https://accounts.spotify.com/api/token"
)

// Scopes let you specify exactly which types of data your application wants to access.
// The set of scopes you pass in your authentication request determines what access the
// permissions the user is asked to grant.
const (
	// ScopePlaylistReadPrivate seeks permission to read
	// a user's private playlists.
	ScopePlaylistReadPrivate = "playlist-read-private"
	// ScopePlaylistModifyPublic seeks write access
	// to a user's public playlists.
	ScopePlaylistModifyPublic = "playlist-modify-public"
	// ScopePlaylistModifyPrivate seeks write access to
	// a user's private playlists.
	ScopePlaylistModifyPrivate = "playlist-modify-private"
	// ScopePlaylistReadCollaborative seeks permission to
	// access a user's collaborative playlists.
	ScopePlaylistReadCollaborative = "playlist-read-collaborative"
	// ScopeUserFollowModify seeks write/delete access to
	// the list of artists and other users that a user follows.
	ScopeUserFollowModify = "user-follow-modify"
	// ScopeUserFollowRead seeks read access to the list of
	// artists and other users that a user follows.
	ScopeUserFollowRead = "user-follow-read"
	// ScopeUserLibraryModify seeks write/delete acess to a
	// user's "Your Music" library.
	ScopeUserLibraryModify = "user-library-modify"
	// ScopeUserLibraryRead seeks read access to a user's "Your Music" library.
	ScopeUserLibraryRead = "user-library-read"
	// ScopeUserReadPrivate seeks read access to a user's
	// subsription details (type of user account).
	ScopeUserReadPrivate = "user-read-private"
	// ScopeUserReadEmail seeks read access to a user's email address.
	ScopeUserReadEmail = "user-read-email"
	// ScopeUserReadBirthdate seeks read access to a user's birthdate.
	ScopeUserReadBirthdate = "user-read-birthdate"
)

// Authenticator provides convenience functions for implementing the OAuth2 flow.
// You should always use `NewAuthenticator` to make them.
//
// Example:
//
//     a := spotify.NewAuthenticator(redirectURL, spotify.ScopeUserLibaryRead, spotify.ScopeUserFollowRead)
//     // direct user to Spotify to log in
//     http.Redirect(w, r, a.AuthURL("state-string"), http.StatusFound)
//
//     // then, in redirect handler:
//     token, err := a.Token(state, r)
//     client := a.NewClient(token)
//
type Authenticator struct {
	config  *oauth2.Config
	context context.Context
}

// NewAuthenticator creates an authenticator which is used to implement the
// OAuth2 authorization flow.  The redirectURL must exactly match one of the
// URLs specified in your Spotify developer account.
//
// By default, NewAuthenticator pulls your client ID and secret key from the
// SPOTIFY_ID and SPOTIFY_SECRET environment variables.  If you'd like to provide
// them from some other source, you can call `SetAuthInfo(id, key)` on the
// returned authenticator.
func NewAuthenticator(redirectURL string, scopes ...string) Authenticator {
	cfg := &oauth2.Config{
		ClientID:     os.Getenv("SPOTIFY_ID"),
		ClientSecret: os.Getenv("SPOTIFY_SECRET"),
		RedirectURL:  redirectURL,
		Scopes:       scopes,
		Endpoint: oauth2.Endpoint{
			AuthURL:  AuthURL,
			TokenURL: TokenURL,
		},
	}

	// disable HTTP/2 for DefaultClient, see: https://github.com/zmb3/spotify/issues/20
	tr := &http.Transport{
		TLSNextProto: map[string]func(authority string, c *tls.Conn) http.RoundTripper{},
	}
	ctx := context.WithValue(context.Background(), oauth2.HTTPClient, &http.Client{Transport: tr})
	return Authenticator{
		config:  cfg,
		context: ctx,
	}
}

// SetAuthInfo overwrites the client ID and secret key used by the authenticator.
// You can use this if you don't want to store this information in environment variables.
func (a *Authenticator) SetAuthInfo(clientID, secretKey string) {
	a.config.ClientID = clientID
	a.config.ClientSecret = secretKey
}

// AuthURL returns a URL to the the Spotify Accounts Service's OAuth2 endpoint.
//
// State is a token to protect the user from CSRF attacks.  You should pass the
// same state to `Token`, where it will be validated.  For more info, refer to
// http://tools.ietf.org/html/rfc6749#section-10.12.
func (a Authenticator) AuthURL(state string) string {
	return a.config.AuthCodeURL(state)
}

// Token pulls an authorization code from an HTTP request and attempts to exchange
// it for an access token.  The standard use case is to call Token from the handler
// that handles requests to your application's redirect URL.
func (a Authenticator) Token(state string, r *http.Request) (*oauth2.Token, error) {
	values := r.URL.Query()
	if e := values.Get("error"); e != "" {
		return nil, errors.New("spotify: auth failed - " + e)
	}
	code := values.Get("code")
	if code == "" {
		return nil, errors.New("spotify: didn't get access code")
	}
	actualState := values.Get("state")
	if actualState != state {
		return nil, errors.New("spotify: redirect state parameter doesn't match")
	}
	return a.config.Exchange(a.context, code)
}

// Exchange is like Token, except it allows you to manually specify the access
// code instead of pulling it out of an HTTP request.
func (a Authenticator) Exchange(code string) (*oauth2.Token, error) {
	return a.config.Exchange(a.context, code)
}

// NewClient creates a Client that will use the specified access token for its API requests.
func (a Authenticator) NewClient(token *oauth2.Token) Client {
	client := a.config.Client(a.context, token)
	return Client{
		http: client,
	}
}

// Token gets the client's current token.
func (c *Client) Token() (*oauth2.Token, error) {
	transport, ok := c.http.Transport.(*oauth2.Transport)
	if !ok {
		return nil, errors.New("spotify: oauth2 transport type not correct")
	}
	t, err := transport.Source.Token()
	if err != nil {
		return nil, err
	}

	return t, nil
}
<|endoftext|>


<commit_before>package worker

import (
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/concourse/atc"
	"github.com/pivotal-golang/clock"
)

var ErrContainerNotFound = errors.New("container not found")
var ErrUnsupportedResourceType = errors.New("unsupported resource type")

const containerKeepalive = 30 * time.Second

const ephemeralPropertyName = "concourse:ephemeral"

//go:generate counterfeiter . Worker

type Worker interface {
	Client

	ActiveContainers() int
	Satisfies(ContainerSpec) bool

	Description() string
}

type gardenWorker struct {
	gardenClient garden.Client
	clock        clock.Clock

	activeContainers int
	resourceTypes    []atc.WorkerResourceType
	platform         string
	tags             []string
}

func NewGardenWorker(
	gardenClient garden.Client,
	clock clock.Clock,
	activeContainers int,
	resourceTypes []atc.WorkerResourceType,
	platform string,
	tags []string,
) Worker {
	return &gardenWorker{
		gardenClient: gardenClient,
		clock:        clock,

		activeContainers: activeContainers,
		resourceTypes:    resourceTypes,
		platform:         platform,
		tags:             tags,
	}
}

func (worker *gardenWorker) CreateContainer(id Identifier, spec ContainerSpec) (Container, error) {
	gardenSpec := garden.ContainerSpec{
		Properties: id.gardenProperties(),
	}

dance:
	switch s := spec.(type) {
	case ResourceTypeContainerSpec:
		gardenSpec.Privileged = true

		if s.Ephemeral {
			gardenSpec.Properties[ephemeralPropertyName] = "true"
		}

		for _, t := range worker.resourceTypes {
			if t.Type == s.Type {
				gardenSpec.RootFSPath = t.Image
				break dance
			}
		}

		return nil, ErrUnsupportedResourceType

	case TaskContainerSpec:
		gardenSpec.RootFSPath = s.Image
		gardenSpec.Privileged = s.Privileged

	default:
		return nil, fmt.Errorf("unknown container spec type: %T (%#v)", s, s)
	}

	gardenContainer, err := worker.gardenClient.Create(gardenSpec)
	if err != nil {
		return nil, err
	}

	return newGardenWorkerContainer(gardenContainer, worker.gardenClient, worker.clock), nil
}

func (worker *gardenWorker) LookupContainer(id Identifier) (Container, error) {
	containers, err := worker.gardenClient.Containers(id.gardenProperties())
	if err != nil {
		return nil, err
	}

	if len(containers) == 0 {
	}

	switch len(containers) {
	case 0:
		return nil, ErrContainerNotFound
	case 1:
		return newGardenWorkerContainer(containers[0], worker.gardenClient, worker.clock), nil
	default:
		handles := []string{}

		for _, c := range containers {
			handles = append(handles, c.Handle())
		}

		return nil, MultipleContainersError{
			Handles: handles,
		}
	}
}

func (worker *gardenWorker) ActiveContainers() int {
	return worker.activeContainers
}

func (worker *gardenWorker) Satisfies(spec ContainerSpec) bool {
	switch s := spec.(type) {
	case ResourceTypeContainerSpec:
		for _, t := range worker.resourceTypes {
			if t.Type == s.Type {
				return true
			}
		}

	case TaskContainerSpec:
		if s.Platform != worker.platform {
			return false
		}

		if len(worker.tags) > 0 && len(s.Tags) == 0 {
			return false
		}

	insert_coin:
		for _, stag := range s.Tags {
			for _, wtag := range worker.tags {
				if stag == wtag {
					continue insert_coin
				}
			}

			return false
		}

		return true
	}

	return false
}

func (worker *gardenWorker) Description() string {
	messages := []string{
		fmt.Sprintf("platform '%s'", worker.platform),
	}

	for _, tag := range worker.tags {
		messages = append(messages, fmt.Sprintf("tag '%s'", tag))
	}

	return strings.Join(messages, ", ")
}

type gardenWorkerContainer struct {
	garden.Container

	gardenClient garden.Client

	clock clock.Clock

	stopHeartbeating chan struct{}
	heartbeating     *sync.WaitGroup

	releaseOnce sync.Once
}

func newGardenWorkerContainer(container garden.Container, gardenClient garden.Client, clock clock.Clock) Container {
	workerContainer := &gardenWorkerContainer{
		Container: container,

		gardenClient: gardenClient,

		clock: clock,

		heartbeating:     new(sync.WaitGroup),
		stopHeartbeating: make(chan struct{}),
	}

	workerContainer.heartbeating.Add(1)
	go workerContainer.heartbeat(clock.NewTicker(containerKeepalive))

	return workerContainer
}

func (container *gardenWorkerContainer) Destroy() error {
	container.Release()
	return container.gardenClient.Destroy(container.Handle())
}

func (container *gardenWorkerContainer) Release() {
	container.releaseOnce.Do(func() {
		close(container.stopHeartbeating)
		container.heartbeating.Wait()
	})
}

func (container *gardenWorkerContainer) heartbeat(pacemaker clock.Ticker) {
	defer container.heartbeating.Done()

	for {
		select {
		case <-pacemaker.C():
			container.SetProperty("keepalive", fmt.Sprintf("%d", container.clock.Now().Unix()))
		case <-container.stopHeartbeating:
			return
		}
	}
}
<commit_msg>fix ticker leakage when releasing containers<commit_after>package worker

import (
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"

	"github.com/cloudfoundry-incubator/garden"
	"github.com/concourse/atc"
	"github.com/pivotal-golang/clock"
)

var ErrContainerNotFound = errors.New("container not found")
var ErrUnsupportedResourceType = errors.New("unsupported resource type")

const containerKeepalive = 30 * time.Second

const ephemeralPropertyName = "concourse:ephemeral"

//go:generate counterfeiter . Worker

type Worker interface {
	Client

	ActiveContainers() int
	Satisfies(ContainerSpec) bool

	Description() string
}

type gardenWorker struct {
	gardenClient garden.Client
	clock        clock.Clock

	activeContainers int
	resourceTypes    []atc.WorkerResourceType
	platform         string
	tags             []string
}

func NewGardenWorker(
	gardenClient garden.Client,
	clock clock.Clock,
	activeContainers int,
	resourceTypes []atc.WorkerResourceType,
	platform string,
	tags []string,
) Worker {
	return &gardenWorker{
		gardenClient: gardenClient,
		clock:        clock,

		activeContainers: activeContainers,
		resourceTypes:    resourceTypes,
		platform:         platform,
		tags:             tags,
	}
}

func (worker *gardenWorker) CreateContainer(id Identifier, spec ContainerSpec) (Container, error) {
	gardenSpec := garden.ContainerSpec{
		Properties: id.gardenProperties(),
	}

dance:
	switch s := spec.(type) {
	case ResourceTypeContainerSpec:
		gardenSpec.Privileged = true

		if s.Ephemeral {
			gardenSpec.Properties[ephemeralPropertyName] = "true"
		}

		for _, t := range worker.resourceTypes {
			if t.Type == s.Type {
				gardenSpec.RootFSPath = t.Image
				break dance
			}
		}

		return nil, ErrUnsupportedResourceType

	case TaskContainerSpec:
		gardenSpec.RootFSPath = s.Image
		gardenSpec.Privileged = s.Privileged

	default:
		return nil, fmt.Errorf("unknown container spec type: %T (%#v)", s, s)
	}

	gardenContainer, err := worker.gardenClient.Create(gardenSpec)
	if err != nil {
		return nil, err
	}

	return newGardenWorkerContainer(gardenContainer, worker.gardenClient, worker.clock), nil
}

func (worker *gardenWorker) LookupContainer(id Identifier) (Container, error) {
	containers, err := worker.gardenClient.Containers(id.gardenProperties())
	if err != nil {
		return nil, err
	}

	if len(containers) == 0 {
	}

	switch len(containers) {
	case 0:
		return nil, ErrContainerNotFound
	case 1:
		return newGardenWorkerContainer(containers[0], worker.gardenClient, worker.clock), nil
	default:
		handles := []string{}

		for _, c := range containers {
			handles = append(handles, c.Handle())
		}

		return nil, MultipleContainersError{
			Handles: handles,
		}
	}
}

func (worker *gardenWorker) ActiveContainers() int {
	return worker.activeContainers
}

func (worker *gardenWorker) Satisfies(spec ContainerSpec) bool {
	switch s := spec.(type) {
	case ResourceTypeContainerSpec:
		for _, t := range worker.resourceTypes {
			if t.Type == s.Type {
				return true
			}
		}

	case TaskContainerSpec:
		if s.Platform != worker.platform {
			return false
		}

		if len(worker.tags) > 0 && len(s.Tags) == 0 {
			return false
		}

	insert_coin:
		for _, stag := range s.Tags {
			for _, wtag := range worker.tags {
				if stag == wtag {
					continue insert_coin
				}
			}

			return false
		}

		return true
	}

	return false
}

func (worker *gardenWorker) Description() string {
	messages := []string{
		fmt.Sprintf("platform '%s'", worker.platform),
	}

	for _, tag := range worker.tags {
		messages = append(messages, fmt.Sprintf("tag '%s'", tag))
	}

	return strings.Join(messages, ", ")
}

type gardenWorkerContainer struct {
	garden.Container

	gardenClient garden.Client

	clock clock.Clock

	stopHeartbeating chan struct{}
	heartbeating     *sync.WaitGroup

	releaseOnce sync.Once
}

func newGardenWorkerContainer(container garden.Container, gardenClient garden.Client, clock clock.Clock) Container {
	workerContainer := &gardenWorkerContainer{
		Container: container,

		gardenClient: gardenClient,

		clock: clock,

		heartbeating:     new(sync.WaitGroup),
		stopHeartbeating: make(chan struct{}),
	}

	workerContainer.heartbeating.Add(1)
	go workerContainer.heartbeat(clock.NewTicker(containerKeepalive))

	return workerContainer
}

func (container *gardenWorkerContainer) Destroy() error {
	container.Release()
	return container.gardenClient.Destroy(container.Handle())
}

func (container *gardenWorkerContainer) Release() {
	container.releaseOnce.Do(func() {
		close(container.stopHeartbeating)
		container.heartbeating.Wait()
	})
}

func (container *gardenWorkerContainer) heartbeat(pacemaker clock.Ticker) {
	defer container.heartbeating.Done()
	defer pacemaker.Stop()

	for {
		select {
		case <-pacemaker.C():
			container.SetProperty("keepalive", fmt.Sprintf("%d", container.clock.Now().Unix()))
		case <-container.stopHeartbeating:
			return
		}
	}
}
<|endoftext|>


<commit_before>package gokeepasslib

import (
	"testing"
	"time"

	. "github.com/tobischo/gokeepasslib/v2/wrappers"
)

func TestTimeWrapperMarshalText(t *testing.T) {
	cases := []struct {
		title    string
		valueFn  func() time.Time
		expValue string
		expErr   error
	}{
		{
			title: "negative year",
			valueFn: func() time.Time {
				return time.Date(-1, time.June, 10, 6, 34, 12, 123123, time.UTC)
			},
			expErr: ErrYearOutsideOfRange,
		},
		{
			title: "year above 10000",
			valueFn: func() time.Time {
				return time.Date(10001, time.June, 10, 6, 34, 12, 123123, time.UTC)
			},
			expErr: ErrYearOutsideOfRange,
		},
		{
			title: "realistic year (2018)",
			valueFn: func() time.Time {
				ref, _ := time.Parse(time.RFC3339, "2018-06-10T06:20:23+02:00")
				return ref
			},
			expValue: "2018-06-10T04:20:23Z",
		},
	}

	for _, c := range cases {
		t.Run(c.title, func(t *testing.T) {
			value := c.valueFn()

			timeWrap := TimeWrapper{
				Formatted: true,
				Time:      value,
			}
			data, err := timeWrap.MarshalText()
			if err != c.expErr {
				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
			}

			if string(data) != c.expValue {
				t.Errorf(
					"Did not marshal into expected string '%s', received: '%s'",
					c.expValue,
					string(data),
				)
			}
		})
	}
}

func TestTimeWrapperUnmarshalText(t *testing.T) {
	cases := []struct {
		title    string
		value    string
		expValue time.Time
		expErr   error
	}{
		{
			title:    "Non UTC RFC3339 compatible value",
			value:    "2018-06-10T06:20:23+02:00",
			expValue: time.Date(2018, time.June, 10, 4, 20, 23, 0, time.UTC),
		},
		{
			title:    "UTC RFC3339 compatible value",
			value:    "2018-06-10T04:20:23Z",
			expValue: time.Date(2018, time.June, 10, 4, 20, 23, 0, time.UTC),
		},
	}

	for _, c := range cases {
		t.Run(c.title, func(t *testing.T) {

			timeWrap := &TimeWrapper{
				Formatted: true,
			}
			err := timeWrap.UnmarshalText([]byte(c.value))
			if err != c.expErr {
				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
			}

			if !timeWrap.Time.Equal(c.expValue) {
				t.Errorf("Did not receive expected value '%+v', received: '%+v'", c.expValue, *timeWrap)
			}
		})
	}
}
<commit_msg>Add tests for BoolWrapper Unmarshal case-insensitivity.<commit_after>package gokeepasslib

import (
	"encoding/xml"
	"testing"
	"time"

	. "github.com/tobischo/gokeepasslib/v2/wrappers"
)

func TestTimeWrapperMarshalText(t *testing.T) {
	cases := []struct {
		title    string
		valueFn  func() time.Time
		expValue string
		expErr   error
	}{
		{
			title: "negative year",
			valueFn: func() time.Time {
				return time.Date(-1, time.June, 10, 6, 34, 12, 123123, time.UTC)
			},
			expErr: ErrYearOutsideOfRange,
		},
		{
			title: "year above 10000",
			valueFn: func() time.Time {
				return time.Date(10001, time.June, 10, 6, 34, 12, 123123, time.UTC)
			},
			expErr: ErrYearOutsideOfRange,
		},
		{
			title: "realistic year (2018)",
			valueFn: func() time.Time {
				ref, _ := time.Parse(time.RFC3339, "2018-06-10T06:20:23+02:00")
				return ref
			},
			expValue: "2018-06-10T04:20:23Z",
		},
	}

	for _, c := range cases {
		t.Run(c.title, func(t *testing.T) {
			value := c.valueFn()

			timeWrap := TimeWrapper{
				Formatted: true,
				Time:      value,
			}
			data, err := timeWrap.MarshalText()
			if err != c.expErr {
				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
			}

			if string(data) != c.expValue {
				t.Errorf(
					"Did not marshal into expected string '%s', received: '%s'",
					c.expValue,
					string(data),
				)
			}
		})
	}
}

func TestTimeWrapperUnmarshalText(t *testing.T) {
	cases := []struct {
		title    string
		value    string
		expValue time.Time
		expErr   error
	}{
		{
			title:    "Non UTC RFC3339 compatible value",
			value:    "2018-06-10T06:20:23+02:00",
			expValue: time.Date(2018, time.June, 10, 4, 20, 23, 0, time.UTC),
		},
		{
			title:    "UTC RFC3339 compatible value",
			value:    "2018-06-10T04:20:23Z",
			expValue: time.Date(2018, time.June, 10, 4, 20, 23, 0, time.UTC),
		},
	}

	for _, c := range cases {
		t.Run(c.title, func(t *testing.T) {

			timeWrap := &TimeWrapper{
				Formatted: true,
			}
			err := timeWrap.UnmarshalText([]byte(c.value))
			if err != c.expErr {
				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
			}

			if !timeWrap.Time.Equal(c.expValue) {
				t.Errorf("Did not receive expected value '%+v', received: '%+v'", c.expValue, *timeWrap)
			}
		})
	}
}

func TestBoolWrapperUnmarshal(t *testing.T) {
	cases := []struct {
		title    string
		value    string
		expValue bool
		expErr   error
	}{
		{
			title:    "lowercase true",
			value:    `<Wrap><Val>true</Val></Wrap>`,
			expValue: true,
			expErr:   nil,
		},
		{
			title:    "mixedcase true",
			value:    `<Wrap><Val>TrUe</Val></Wrap>`,
			expValue: true,
			expErr:   nil,
		},
		{
			title:    "lowercase false",
			value:    `<Wrap><Val>false</Val></Wrap>`,
			expValue: false,
			expErr:   nil,
		},
		{
			title:    "mixedcase false",
			value:    `<Wrap><Val>FaLsE</Val></Wrap>`,
			expValue: false,
			expErr:   nil,
		},
		{
			title:    "neither true nor false defaults to false",
			value:    `<Wrap><Val>neither</Val></Wrap>`,
			expValue: false,
			expErr:   nil,
		},
	}

	for _, c := range cases {
		t.Run(c.title, func(t *testing.T) {
			var x struct {
				Val BoolWrapper `xml:"Val"`
			}
			err := xml.Unmarshal([]byte(c.value), &x)

			if err != c.expErr {
				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
			}
			if bool(x.Val) != c.expValue {
				t.Errorf("Did not receive expected value '%+v', received: '%+v'", c.expValue, x.Val)
			}

		})
	}
}

func TestBoolWrapperUnmarshalAttr(t *testing.T) {
	cases := []struct {
		title    string
		value    string
		expValue bool
		expErr   error
	}{
		{
			title:    "lowercase true",
			value:    `<Wrap><Val v="true"></Val></Wrap>`,
			expValue: true,
			expErr:   nil,
		},
		{
			title:    "mixedcase true",
			value:    `<Wrap><Val v="TrUe"></Val></Wrap>`,
			expValue: true,
			expErr:   nil,
		},
		{
			title:    "lowercase false",
			value:    `<Wrap><Val v="false"></Val></Wrap>`,
			expValue: false,
			expErr:   nil,
		},
		{
			title:    "mixedcase false",
			value:    `<Wrap><Val v="FaLsE"></Val></Wrap>`,
			expValue: false,
			expErr:   nil,
		},
		{
			title:    "neither true nor false defaults to false",
			value:    `<Wrap><Val v="neither"></Val></Wrap>`,
			expValue: false,
			expErr:   nil,
		},
	}

	for _, c := range cases {
		t.Run(c.title, func(t *testing.T) {
			var x struct {
				Val struct {
					Content string      `xml:",chardata"`
					V       BoolWrapper `xml:"v,attr,omitempty"`
				}
			}
			err := xml.Unmarshal([]byte(c.value), &x)

			if err != c.expErr {
				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
			}
			if bool(x.Val.V) != c.expValue {
				t.Errorf("Did not receive expected value '%+v', received: '%+v'", c.expValue, x.Val.V)
			}

		})
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package wallet

import (
	"bytes"
	"crypto/sha256"

	"github.com/FactomProject/btcutil/base58"
)

const (
	SeedLength = 64
	Version    = "0.2.1.2"
	ApiVersion = "2.0"
)

// seed address prefix
var seedPrefix = []byte{0x13, 0xdd}

// SeedString returnes the string representation of a raw Wallet Seed or Next
// Wallet Seed.
func SeedString(seed []byte) string {
	if len(seed) != SeedLength {
		return ""
	}

	buf := new(bytes.Buffer)

	// 2 byte Seed Address Prefix
	buf.Write(seedPrefix)

	// 64 byte Seed
	buf.Write(seed)

	// 4 byte Checksum
	check := shad(buf.Bytes())[:4]
	buf.Write(check)

	return base58.Encode(buf.Bytes())
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// newCounter is used to generate the ID field for the JSON2Request
func newCounter() func() int {
	count := 0
	return func() int {
		count += 1
		return count
	}
}

var APICounter = newCounter()
<commit_msg>version increase<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package wallet

import (
	"bytes"
	"crypto/sha256"

	"github.com/FactomProject/btcutil/base58"
)

const (
	SeedLength = 64
	Version    = "0.2.1.3"
	ApiVersion = "2.0"
)

// seed address prefix
var seedPrefix = []byte{0x13, 0xdd}

// SeedString returnes the string representation of a raw Wallet Seed or Next
// Wallet Seed.
func SeedString(seed []byte) string {
	if len(seed) != SeedLength {
		return ""
	}

	buf := new(bytes.Buffer)

	// 2 byte Seed Address Prefix
	buf.Write(seedPrefix)

	// 64 byte Seed
	buf.Write(seed)

	// 4 byte Checksum
	check := shad(buf.Bytes())[:4]
	buf.Write(check)

	return base58.Encode(buf.Bytes())
}

// shad Double Sha256 Hash; sha256(sha256(data))
func shad(data []byte) []byte {
	h1 := sha256.Sum256(data)
	h2 := sha256.Sum256(h1[:])
	return h2[:]
}

// newCounter is used to generate the ID field for the JSON2Request
func newCounter() func() int {
	count := 0
	return func() int {
		count += 1
		return count
	}
}

var APICounter = newCounter()
<|endoftext|>


<commit_before>package cbor

import (
	"encoding/binary"
	"fmt"
	"math"
)

func (d *Decoder) decodeFloat(majorByte byte) (f float64, err error) {
	var bs []byte
	switch majorByte {
	case cborSigilFloat16:
		bs, err = d.r.Readnzc(2)
		f = float64(math.Float32frombits(halfFloatToFloatBits(binary.BigEndian.Uint16(bs))))
	case cborSigilFloat32:
		bs, err = d.r.Readnzc(4)
		f = float64(math.Float32frombits(binary.BigEndian.Uint32(bs)))
	case cborSigilFloat64:
		bs, err = d.r.Readnzc(8)
		f = math.Float64frombits(binary.BigEndian.Uint64(bs))
	}
	return
}

// Decode an unsigned int.
// Must continue to hand down the majorByte because some of its bits are either
// packed with the value outright, or tell us how many more bytes the value fills.
func (d *Decoder) decodeUint(majorByte byte) (ui uint64, err error) {
	v := majorByte & 0x1f
	if v <= 0x17 {
		ui = uint64(v)
	} else {
		if v == 0x18 {
			var b byte
			b, err = d.r.Readn1()
			ui = uint64(b)
		} else if v == 0x19 {
			var bs []byte
			bs, err = d.r.Readnzc(2)
			ui = uint64(binary.BigEndian.Uint16(bs))
		} else if v == 0x1a {
			var bs []byte
			bs, err = d.r.Readnzc(4)
			ui = uint64(binary.BigEndian.Uint32(bs))
		} else if v == 0x1b {
			var bs []byte
			bs, err = d.r.Readnzc(8)
			ui = uint64(binary.BigEndian.Uint64(bs))
		} else {
			err = fmt.Errorf("decodeUint: Invalid descriptor: %v", majorByte)
			return
		}
	}
	return
}

// Decode a *negative* integer.
// Note that CBOR has a very funny-shaped hole here: there is unsigned positive int,
// and there is explicitly negative signed int... and there is no signed, positive int.
// *We have no 'decodeInt' function because that **doesn't exist** in CBOR.*
// So!  Hopefully our consumer doesn't mind having to cast uints to ints fairly frequently.
func (d *Decoder) decodeNegInt(majorByte byte) (i int64, err error) {
	// The packed bits in the majorByte and the following bytes if any are layed out
	// the exact same as a uint; only the major type bits are different.
	ui, err := d.decodeUint(majorByte)
	if err != nil {
		return 0, err
	}
	// TODO needs overflow check
	return -1 - int64(ui), nil
}

// Decode expecting a positive integer.
// None of our token-yielding functions call this directly;
// it's used inside the library when we expect to read e.g. a length header.
// Does not check that your majorByte indicates an integer type at all;
// in context, it often doesn't, e.g. when decoding the length of a string.
func (d *Decoder) decodeLen(majorByte byte) (i int, err error) {
	ui, err := d.decodeUint(majorByte)
	if err != nil {
		return 0, err
	}
	// TODO needs overflow check
	return int(ui), nil
}

// Decoding indefinite-length byte strings in cbor is actually decoding a sequence of
// definite-length byte strings until you encounter a break.
// Caller: use `bs[:0]` if you have something to reuse, or nil
func (d *Decoder) decodeBytesIndefinite(bs []byte) (bsOut []byte, err error) {
	return d.decodeBytesOrStringIndefinite(bs, cborMajorBytes)
}

func (d *Decoder) decodeStringIndefinite() (s string, err error) {
	bs, err := d.decodeBytesOrStringIndefinite(nil, cborMajorString)
	if err != nil {
		return "", err
	}
	return string(bs), nil
}

func (d *Decoder) decodeBytesOrStringIndefinite(bs []byte, majorWanted byte) (bsOut []byte, err error) {
	if bs == nil {
		bs = make([]byte, 0, 16)
	}
	var n int
	for {
		// Read first byte; check for break, or hunk, or invalid.
		// (It's not necessary to have the first majorByte as a param to this function, because
		// indefinite length sequences have a separate sigil which doesn't pack any len info.)
		majorByte, err := d.r.Readn1()
		if err != nil {
			return bs, err
		}
		if majorByte == cborSigilBreak {
			return bs, nil
		} else if major := majorByte | 0x1f - 0x1f; major != majorWanted {
			return bs, fmt.Errorf("cbor: expect bytes or string major type in indefinite string/bytes; got: %v, byte: %v", major, majorByte)
		}
		// Read length header for this hunk, and ensure we have at least that much cap.
		n, err = d.decodeLen(majorByte)
		if err != nil {
			return bs, err
		}
		oldLen := len(bs)
		newLen := oldLen + n
		if newLen > cap(bs) {
			bs2 := make([]byte, newLen, 2*cap(bs)+n)
			copy(bs2, bs)
			bs = bs2
		} else {
			bs = bs[:newLen]
		}
		// Read that hunk.
		d.r.Readb(bs[oldLen:newLen])
	}
}

// Decode a single length-prefixed hunk of bytes.
//
// There are a number of ways this may try to conserve allocations:
//
// - If you say zerocopy=true, and the underlying reader system already has an
//  appropriate byte slice available, then a slice from that will be returned.
//
// - If you provide a byte slice, we will attempt to use it.
//  The byte slice is truncated and used for its capacity only -- not appended.
//  The final returned slice may be a different one if the provided slice did not
//  have sufficient capacity.
//
// - If you say zerocopy=true, and the underlying read system doesn't have an
//  efficient way to yield a slice of its internal buffer, and you provided no
//  destination slice, then we will use a recycleable piece of memory in the Decoder
//  state and return a slice viewing into it.  For small values this will
//  likely save an alloc.
//
// The above rules are resolved in this order; e.g. your byte slice is disregarded
// if zerocopy=true and the underlying reader can do something even more efficient,
// though there is also no harm to providing the slice argument.
// Generally, set zerocopy if you know you're not going to publicly yield the results,
// and the implementation will do its best to be as efficient as possible.
//
// Zerocopy is appropriate when planning to turn the bytes into a string, for example,
// since in that path we know the slice will be treated immutably, not publicly
// exposed, and also any other copy to another intermediate is definitely useless.
func (d *Decoder) decodeBytes(majorByte byte) (bs []byte, err error) {
	n, err := d.decodeLen(majorByte)
	if err != nil {
		return nil, err
	}
	return d.r.Readn(n)
}

// Decode a single length-prefixed string.
func (d *Decoder) decodeString(majorByte byte) (s string, err error) {
	n, err := d.decodeLen(majorByte)
	if err != nil {
		return "", err
	}
	bs, err := d.r.Readnzc(n)
	return string(bs), err
}

// culled from OGRE (Object-Oriented Graphics Rendering Engine)
// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
func halfFloatToFloatBits(yy uint16) (d uint32) {
	y := uint32(yy)
	s := (y >> 15) & 0x01
	e := (y >> 10) & 0x1f
	m := y & 0x03ff

	if e == 0 {
		if m == 0 { // plu or minus 0
			return s << 31
		} else { // Denormalized number -- renormalize it
			for (m & 0x00000400) == 0 {
				m <<= 1
				e -= 1
			}
			e += 1
			const zz uint32 = 0x0400
			m &= ^zz
		}
	} else if e == 31 {
		if m == 0 { // Inf
			return (s << 31) | 0x7f800000
		} else { // NaN
			return (s << 31) | 0x7f800000 | (m << 13)
		}
	}
	e = e + (127 - 15)
	m = m << 13
	return (s << 31) | (e << 23) | m
}
<commit_msg>cbor: Add allocation size limits.<commit_after>package cbor

import (
	"encoding/binary"
	"fmt"
	"math"
)

func (d *Decoder) decodeFloat(majorByte byte) (f float64, err error) {
	var bs []byte
	switch majorByte {
	case cborSigilFloat16:
		bs, err = d.r.Readnzc(2)
		f = float64(math.Float32frombits(halfFloatToFloatBits(binary.BigEndian.Uint16(bs))))
	case cborSigilFloat32:
		bs, err = d.r.Readnzc(4)
		f = float64(math.Float32frombits(binary.BigEndian.Uint32(bs)))
	case cborSigilFloat64:
		bs, err = d.r.Readnzc(8)
		f = math.Float64frombits(binary.BigEndian.Uint64(bs))
	}
	return
}

// Decode an unsigned int.
// Must continue to hand down the majorByte because some of its bits are either
// packed with the value outright, or tell us how many more bytes the value fills.
func (d *Decoder) decodeUint(majorByte byte) (ui uint64, err error) {
	v := majorByte & 0x1f
	if v <= 0x17 {
		ui = uint64(v)
	} else {
		if v == 0x18 {
			var b byte
			b, err = d.r.Readn1()
			ui = uint64(b)
		} else if v == 0x19 {
			var bs []byte
			bs, err = d.r.Readnzc(2)
			ui = uint64(binary.BigEndian.Uint16(bs))
		} else if v == 0x1a {
			var bs []byte
			bs, err = d.r.Readnzc(4)
			ui = uint64(binary.BigEndian.Uint32(bs))
		} else if v == 0x1b {
			var bs []byte
			bs, err = d.r.Readnzc(8)
			ui = uint64(binary.BigEndian.Uint64(bs))
		} else {
			err = fmt.Errorf("decodeUint: Invalid descriptor: %v", majorByte)
			return
		}
	}
	return
}

// Decode a *negative* integer.
// Note that CBOR has a very funny-shaped hole here: there is unsigned positive int,
// and there is explicitly negative signed int... and there is no signed, positive int.
// *We have no 'decodeInt' function because that **doesn't exist** in CBOR.*
// So!  Hopefully our consumer doesn't mind having to cast uints to ints fairly frequently.
func (d *Decoder) decodeNegInt(majorByte byte) (i int64, err error) {
	// The packed bits in the majorByte and the following bytes if any are layed out
	// the exact same as a uint; only the major type bits are different.
	ui, err := d.decodeUint(majorByte)
	if err != nil {
		return 0, err
	}
	// TODO needs overflow check
	return -1 - int64(ui), nil
}

// Decode expecting a positive integer.
// None of our token-yielding functions call this directly;
// it's used inside the library when we expect to read e.g. a length header.
// Does not check that your majorByte indicates an integer type at all;
// in context, it often doesn't, e.g. when decoding the length of a string.
func (d *Decoder) decodeLen(majorByte byte) (i int, err error) {
	ui, err := d.decodeUint(majorByte)
	if err != nil {
		return 0, err
	}
	// TODO needs overflow check
	return int(ui), nil
}

// Decoding indefinite-length byte strings in cbor is actually decoding a sequence of
// definite-length byte strings until you encounter a break.
// Caller: use `bs[:0]` if you have something to reuse, or nil
func (d *Decoder) decodeBytesIndefinite(bs []byte) (bsOut []byte, err error) {
	return d.decodeBytesOrStringIndefinite(bs, cborMajorBytes)
}

func (d *Decoder) decodeStringIndefinite() (s string, err error) {
	bs, err := d.decodeBytesOrStringIndefinite(nil, cborMajorString)
	if err != nil {
		return "", err
	}
	return string(bs), nil
}

func (d *Decoder) decodeBytesOrStringIndefinite(bs []byte, majorWanted byte) (bsOut []byte, err error) {
	if bs == nil {
		bs = make([]byte, 0, 16)
	}
	var n int
	for {
		// Read first byte; check for break, or hunk, or invalid.
		// (It's not necessary to have the first majorByte as a param to this function, because
		// indefinite length sequences have a separate sigil which doesn't pack any len info.)
		majorByte, err := d.r.Readn1()
		if err != nil {
			return bs, err
		}
		if majorByte == cborSigilBreak {
			return bs, nil
		} else if major := majorByte | 0x1f - 0x1f; major != majorWanted {
			return bs, fmt.Errorf("cbor: expect bytes or string major type in indefinite string/bytes; got: %v, byte: %v", major, majorByte)
		}
		// Read length header for this hunk, and ensure we have at least that much cap.
		n, err = d.decodeLen(majorByte)
		if err != nil {
			return bs, err
		}
		oldLen := len(bs)
		newLen := oldLen + n
		if n > 33554432 {
			return nil, fmt.Errorf("cbor: decoding rejected oversized indefinite string/bytes field: %d is too large", n)
		}
		if newLen > cap(bs) {
			bs2 := make([]byte, newLen, 2*cap(bs)+n)
			copy(bs2, bs)
			bs = bs2
		} else {
			bs = bs[:newLen]
		}
		// Read that hunk.
		d.r.Readb(bs[oldLen:newLen])
	}
}

// Decode a single length-prefixed hunk of bytes.
//
// There are a number of ways this may try to conserve allocations:
//
// - If you say zerocopy=true, and the underlying reader system already has an
//  appropriate byte slice available, then a slice from that will be returned.
//
// - If you provide a byte slice, we will attempt to use it.
//  The byte slice is truncated and used for its capacity only -- not appended.
//  The final returned slice may be a different one if the provided slice did not
//  have sufficient capacity.
//
// - If you say zerocopy=true, and the underlying read system doesn't have an
//  efficient way to yield a slice of its internal buffer, and you provided no
//  destination slice, then we will use a recycleable piece of memory in the Decoder
//  state and return a slice viewing into it.  For small values this will
//  likely save an alloc.
//
// The above rules are resolved in this order; e.g. your byte slice is disregarded
// if zerocopy=true and the underlying reader can do something even more efficient,
// though there is also no harm to providing the slice argument.
// Generally, set zerocopy if you know you're not going to publicly yield the results,
// and the implementation will do its best to be as efficient as possible.
//
// Zerocopy is appropriate when planning to turn the bytes into a string, for example,
// since in that path we know the slice will be treated immutably, not publicly
// exposed, and also any other copy to another intermediate is definitely useless.
func (d *Decoder) decodeBytes(majorByte byte) (bs []byte, err error) {
	n, err := d.decodeLen(majorByte)
	if err != nil {
		return nil, err
	}
	if n > 33554432 {
		return nil, fmt.Errorf("cbor: decoding rejected oversized byte field: %d is too large", n)
	}
	return d.r.Readn(n)
}

// Decode a single length-prefixed string.
func (d *Decoder) decodeString(majorByte byte) (s string, err error) {
	n, err := d.decodeLen(majorByte)
	if err != nil {
		return "", err
	}
	if n > 33554432 {
		return "", fmt.Errorf("cbor: decoding rejected oversized string field: %d is too large", n)
	}
	bs, err := d.r.Readnzc(n)
	return string(bs), err
}

// culled from OGRE (Object-Oriented Graphics Rendering Engine)
// function: halfToFloatI (http://stderr.org/doc/ogre-doc/api/OgreBitwise_8h-source.html)
func halfFloatToFloatBits(yy uint16) (d uint32) {
	y := uint32(yy)
	s := (y >> 15) & 0x01
	e := (y >> 10) & 0x1f
	m := y & 0x03ff

	if e == 0 {
		if m == 0 { // plu or minus 0
			return s << 31
		} else { // Denormalized number -- renormalize it
			for (m & 0x00000400) == 0 {
				m <<= 1
				e -= 1
			}
			e += 1
			const zz uint32 = 0x0400
			m &= ^zz
		}
	} else if e == 31 {
		if m == 0 { // Inf
			return (s << 31) | 0x7f800000
		} else { // NaN
			return (s << 31) | 0x7f800000 | (m << 13)
		}
	}
	e = e + (127 - 15)
	m = m << 13
	return (s << 31) | (e << 23) | m
}
<|endoftext|>


<commit_before>package redis

import (
	"context"
	"fmt"
	"time"

	libredis "github.com/go-redis/redis"
	"github.com/pkg/errors"

	"github.com/ulule/limiter"
	"github.com/ulule/limiter/drivers/store/common"
)

// Client is an interface thats allows to use a redis cluster or a redis single client seamlessly.
type Client interface {
	Ping() *libredis.StatusCmd
	Get(key string) *libredis.StringCmd
	Set(key string, value interface{}, expiration time.Duration) *libredis.StatusCmd
	Watch(handler func(*libredis.Tx) error, keys ...string) error
	Del(keys ...string) *libredis.IntCmd
	SetNX(key string, value interface{}, expiration time.Duration) *libredis.BoolCmd
	Eval(script string, keys []string, args ...interface{}) *libredis.Cmd
}

// Store is the redis store.
type Store struct {
	// Prefix used for the key.
	Prefix string
	// MaxRetry is the maximum number of retry under race conditions.
	MaxRetry int
	// client used to communicate with redis server.
	client Client
}

// NewStore returns an instance of redis store with defaults.
func NewStore(client Client) (limiter.Store, error) {
	return NewStoreWithOptions(client, limiter.StoreOptions{
		Prefix:          limiter.DefaultPrefix,
		CleanUpInterval: limiter.DefaultCleanUpInterval,
	})
}

// NewStoreWithOptions returns an instance of redis store with options.
func NewStoreWithOptions(client Client, options limiter.StoreOptions) (limiter.Store, error) {
	store := &Store{
		client:   client,
		Prefix:   options.Prefix,
		MaxRetry: options.MaxRetry,
	}

	if store.MaxRetry <= 0 {
		store.MaxRetry = 1
	}

	_, err := store.ping()
	if err != nil {
		return nil, err
	}

	return store, nil
}

// Get returns the limit for given identifier.
func (store *Store) Get(ctx context.Context, key string, rate limiter.Rate) (limiter.Context, error) {
	key = fmt.Sprintf("%s:%s", store.Prefix, key)
	now := time.Now()

	lctx := limiter.Context{}
	onWatch := func(rtx *libredis.Tx) error {

		created, err := store.doSetValue(rtx, key, rate.Period)
		if err != nil {
			return err
		}

		if created {
			expiration := now.Add(rate.Period)
			lctx = common.GetContextFromState(now, rate, expiration, 1)
			return nil
		}

		count, ttl, err := store.doUpdateValue(rtx, key, rate.Period)
		if err != nil {
			return err
		}

		expiration := now.Add(rate.Period)
		if ttl > 0 {
			expiration = now.Add(ttl)
		}

		lctx = common.GetContextFromState(now, rate, expiration, count)
		return nil
	}

	err := store.client.Watch(onWatch, key)
	if err != nil {
		err = errors.Wrapf(err, "limiter: cannot get value for %s", key)
		return limiter.Context{}, err
	}

	return lctx, nil
}

// Peek returns the limit for given identifier, without modification on current values.
func (store *Store) Peek(ctx context.Context, key string, rate limiter.Rate) (limiter.Context, error) {
	key = fmt.Sprintf("%s:%s", store.Prefix, key)
	now := time.Now()

	lctx := limiter.Context{}
	onWatch := func(rtx *libredis.Tx) error {
		count, ttl, err := store.doPeekValue(rtx, key)
		if err != nil {
			return err
		}

		expiration := now.Add(rate.Period)
		if ttl > 0 {
			expiration = now.Add(ttl)
		}

		lctx = common.GetContextFromState(now, rate, expiration, count)
		return nil
	}

	err := store.client.Watch(onWatch, key)
	if err != nil {
		err = errors.Wrapf(err, "limiter: cannot peek value for %s", key)
		return limiter.Context{}, err
	}

	return lctx, nil
}

// doPeekValue will execute peekValue with a retry mecanism (optimistic locking) until store.MaxRetry is reached.
func (store *Store) doPeekValue(rtx *libredis.Tx, key string) (int64, time.Duration, error) {
	for i := 0; i < store.MaxRetry; i++ {
		count, ttl, err := peekValue(rtx, key)
		if err == nil {
			return count, ttl, nil
		}
	}
	return 0, 0, errors.New("retry limit exceeded")
}

// peekValue will retrieve the counter and its expiration for given key.
func peekValue(rtx *libredis.Tx, key string) (int64, time.Duration, error) {
	pipe := rtx.Pipeline()
	value := pipe.Get(key)
	expire := pipe.PTTL(key)

	_, err := pipe.Exec()
	if err != nil && err != libredis.Nil {
		return 0, 0, err
	}

	count, err := value.Int64()
	if err != nil && err != libredis.Nil {
		return 0, 0, err
	}

	ttl, err := expire.Result()
	if err != nil {
		return 0, 0, err
	}

	return count, ttl, nil
}

// doSetValue will execute setValue with a retry mecanism (optimistic locking) until store.MaxRetry is reached.
func (store *Store) doSetValue(rtx *libredis.Tx, key string, expiration time.Duration) (bool, error) {
	for i := 0; i < store.MaxRetry; i++ {
		created, err := setValue(rtx, key, expiration)
		if err == nil {
			return created, nil
		}
	}
	return false, errors.New("retry limit exceeded")
}

// setValue will try to initialize a new counter if given key doesn't exists.
func setValue(rtx *libredis.Tx, key string, expiration time.Duration) (bool, error) {
	value := rtx.SetNX(key, 1, expiration)

	created, err := value.Result()
	if err != nil {
		return false, err
	}

	return created, nil
}

// doUpdateValue will execute setValue with a retry mecanism (optimistic locking) until store.MaxRetry is reached.
func (store *Store) doUpdateValue(rtx *libredis.Tx, key string,
	expiration time.Duration) (int64, time.Duration, error) {
	for i := 0; i < store.MaxRetry; i++ {
		count, ttl, err := updateValue(rtx, key, expiration)
		if err == nil {
			return count, ttl, nil
		}

		// If ttl is negative and there is an error, do not retry an update.
		if ttl < 0 {
			return 0, 0, err
		}
	}
	return 0, 0, errors.New("retry limit exceeded")
}

// updateValue will try to increment the counter identified by given key.
func updateValue(rtx *libredis.Tx, key string, expiration time.Duration) (int64, time.Duration, error) {
	pipe := rtx.Pipeline()
	value := pipe.Incr(key)
	expire := pipe.PTTL(key)

	_, err := pipe.Exec()
	if err != nil {
		return 0, 0, err
	}

	count, err := value.Result()
	if err != nil {
		return 0, 0, err
	}

	ttl, err := expire.Result()
	if err != nil {
		return 0, 0, err
	}

	// If ttl is negative, we have to define key expiration.
	if ttl < 0 {
		expire := rtx.Expire(key, expiration)

		ok, err := expire.Result()
		if err != nil {
			return count, ttl, err
		}

		if !ok {
			return count, ttl, errors.New("cannot configure timeout on key")
		}
	}

	return count, ttl, nil

}

// ping checks if redis is alive.
func (store *Store) ping() (bool, error) {
	cmd := store.client.Ping()

	pong, err := cmd.Result()
	if err != nil {
		return false, errors.Wrap(err, "limiter: cannot ping redis server")
	}

	return (pong == "PONG"), nil
}
<commit_msg>chore: merge branch 'master'<commit_after>package redis

import (
	"context"
	"fmt"
	"time"

	libredis "github.com/go-redis/redis"
	"github.com/pkg/errors"

	"github.com/ulule/limiter"
	"github.com/ulule/limiter/drivers/store/common"
)

// Client is an interface thats allows to use a redis cluster or a redis single client seamlessly.
type Client interface {
	Ping() *libredis.StatusCmd
	Get(key string) *libredis.StringCmd
	Set(key string, value interface{}, expiration time.Duration) *libredis.StatusCmd
	Watch(handler func(*libredis.Tx) error, keys ...string) error
	Del(keys ...string) *libredis.IntCmd
	SetNX(key string, value interface{}, expiration time.Duration) *libredis.BoolCmd
	Eval(script string, keys []string, args ...interface{}) *libredis.Cmd
}

// Store is the redis store.
type Store struct {
	// Prefix used for the key.
	Prefix string
	// MaxRetry is the maximum number of retry under race conditions.
	MaxRetry int
	// client used to communicate with redis server.
	client Client
}

// NewStore returns an instance of redis store with defaults.
func NewStore(client Client) (limiter.Store, error) {
	return NewStoreWithOptions(client, limiter.StoreOptions{
		Prefix:          limiter.DefaultPrefix,
		CleanUpInterval: limiter.DefaultCleanUpInterval,
		MaxRetry:        limiter.DefaultMaxRetry,
	})
}

// NewStoreWithOptions returns an instance of redis store with options.
func NewStoreWithOptions(client Client, options limiter.StoreOptions) (limiter.Store, error) {
	store := &Store{
		client:   client,
		Prefix:   options.Prefix,
		MaxRetry: options.MaxRetry,
	}

	if store.MaxRetry <= 0 {
		store.MaxRetry = 1
	}

	_, err := store.ping()
	if err != nil {
		return nil, err
	}

	return store, nil
}

// Get returns the limit for given identifier.
func (store *Store) Get(ctx context.Context, key string, rate limiter.Rate) (limiter.Context, error) {
	key = fmt.Sprintf("%s:%s", store.Prefix, key)
	now := time.Now()

	lctx := limiter.Context{}
	onWatch := func(rtx *libredis.Tx) error {

		created, err := store.doSetValue(rtx, key, rate.Period)
		if err != nil {
			return err
		}

		if created {
			expiration := now.Add(rate.Period)
			lctx = common.GetContextFromState(now, rate, expiration, 1)
			return nil
		}

		count, ttl, err := store.doUpdateValue(rtx, key, rate.Period)
		if err != nil {
			return err
		}

		expiration := now.Add(rate.Period)
		if ttl > 0 {
			expiration = now.Add(ttl)
		}

		lctx = common.GetContextFromState(now, rate, expiration, count)
		return nil
	}

	err := store.client.Watch(onWatch, key)
	if err != nil {
		err = errors.Wrapf(err, "limiter: cannot get value for %s", key)
		return limiter.Context{}, err
	}

	return lctx, nil
}

// Peek returns the limit for given identifier, without modification on current values.
func (store *Store) Peek(ctx context.Context, key string, rate limiter.Rate) (limiter.Context, error) {
	key = fmt.Sprintf("%s:%s", store.Prefix, key)
	now := time.Now()

	lctx := limiter.Context{}
	onWatch := func(rtx *libredis.Tx) error {
		count, ttl, err := store.doPeekValue(rtx, key)
		if err != nil {
			return err
		}

		expiration := now.Add(rate.Period)
		if ttl > 0 {
			expiration = now.Add(ttl)
		}

		lctx = common.GetContextFromState(now, rate, expiration, count)
		return nil
	}

	err := store.client.Watch(onWatch, key)
	if err != nil {
		err = errors.Wrapf(err, "limiter: cannot peek value for %s", key)
		return limiter.Context{}, err
	}

	return lctx, nil
}

// doPeekValue will execute peekValue with a retry mecanism (optimistic locking) until store.MaxRetry is reached.
func (store *Store) doPeekValue(rtx *libredis.Tx, key string) (int64, time.Duration, error) {
	for i := 0; i < store.MaxRetry; i++ {
		count, ttl, err := peekValue(rtx, key)
		if err == nil {
			return count, ttl, nil
		}
	}
	return 0, 0, errors.New("retry limit exceeded")
}

// peekValue will retrieve the counter and its expiration for given key.
func peekValue(rtx *libredis.Tx, key string) (int64, time.Duration, error) {
	pipe := rtx.Pipeline()
	value := pipe.Get(key)
	expire := pipe.PTTL(key)

	_, err := pipe.Exec()
	if err != nil && err != libredis.Nil {
		return 0, 0, err
	}

	count, err := value.Int64()
	if err != nil && err != libredis.Nil {
		return 0, 0, err
	}

	ttl, err := expire.Result()
	if err != nil {
		return 0, 0, err
	}

	return count, ttl, nil
}

// doSetValue will execute setValue with a retry mecanism (optimistic locking) until store.MaxRetry is reached.
func (store *Store) doSetValue(rtx *libredis.Tx, key string, expiration time.Duration) (bool, error) {
	for i := 0; i < store.MaxRetry; i++ {
		created, err := setValue(rtx, key, expiration)
		if err == nil {
			return created, nil
		}
	}
	return false, errors.New("retry limit exceeded")
}

// setValue will try to initialize a new counter if given key doesn't exists.
func setValue(rtx *libredis.Tx, key string, expiration time.Duration) (bool, error) {
	value := rtx.SetNX(key, 1, expiration)

	created, err := value.Result()
	if err != nil {
		return false, err
	}

	return created, nil
}

// doUpdateValue will execute setValue with a retry mecanism (optimistic locking) until store.MaxRetry is reached.
func (store *Store) doUpdateValue(rtx *libredis.Tx, key string,
	expiration time.Duration) (int64, time.Duration, error) {
	for i := 0; i < store.MaxRetry; i++ {
		count, ttl, err := updateValue(rtx, key, expiration)
		if err == nil {
			return count, ttl, nil
		}

		// If ttl is negative and there is an error, do not retry an update.
		if ttl < 0 {
			return 0, 0, err
		}
	}
	return 0, 0, errors.New("retry limit exceeded")
}

// updateValue will try to increment the counter identified by given key.
func updateValue(rtx *libredis.Tx, key string, expiration time.Duration) (int64, time.Duration, error) {
	pipe := rtx.Pipeline()
	value := pipe.Incr(key)
	expire := pipe.PTTL(key)

	_, err := pipe.Exec()
	if err != nil {
		return 0, 0, err
	}

	count, err := value.Result()
	if err != nil {
		return 0, 0, err
	}

	ttl, err := expire.Result()
	if err != nil {
		return 0, 0, err
	}

	// If ttl is negative, we have to define key expiration.
	if ttl < 0 {
		expire := rtx.Expire(key, expiration)

		ok, err := expire.Result()
		if err != nil {
			return count, ttl, err
		}

		if !ok {
			return count, ttl, errors.New("cannot configure timeout on key")
		}
	}

	return count, ttl, nil

}

// ping checks if redis is alive.
func (store *Store) ping() (bool, error) {
	cmd := store.client.Ping()

	pong, err := cmd.Result()
	if err != nil {
		return false, errors.Wrap(err, "limiter: cannot ping redis server")
	}

	return (pong == "PONG"), nil
}
<|endoftext|>


<commit_before>package xlsx

import (
	"fmt"
	"math"
	"strconv"
	"strings"
	"time"
)

// CellType is an int type for storing metadata about the data type in the cell.
type CellType int

// Known types for cell values.
const (
	CellTypeString CellType = iota
	CellTypeFormula
	CellTypeNumeric
	CellTypeBool
	CellTypeInline
	CellTypeError
	CellTypeDate
	CellTypeGeneral
)

// Cell is a high level structure intended to provide user access to
// the contents of Cell within an xlsx.Row.
type Cell struct {
	Row      *Row
	Value    string
	formula  string
	style    *Style
	NumFmt   string
	date1904 bool
	Hidden   bool
	HMerge   int
	VMerge   int
	cellType CellType
}

// CellInterface defines the public API of the Cell.
type CellInterface interface {
	String() string
	FormattedValue() string
}

// NewCell creates a cell and adds it to a row.
func NewCell(r *Row) *Cell {
	return &Cell{Row: r}
}

// Merge with other cells, horizontally and/or vertically.
func (c *Cell) Merge(hcells, vcells int) {
	c.HMerge = hcells
	c.VMerge = vcells
}

// Type returns the CellType of a cell. See CellType constants for more details.
func (c *Cell) Type() CellType {
	return c.cellType
}

// SetString sets the value of a cell to a string.
func (c *Cell) SetString(s string) {
	c.Value = s
	c.formula = ""
	c.cellType = CellTypeString
}

// String returns the value of a Cell as a string.
func (c *Cell) String() (string, error) {
	return c.FormattedValue()
}

// SetFloat sets the value of a cell to a float.
func (c *Cell) SetFloat(n float64) {
	c.SetValue(n)
}

//GetTime returns the value of a Cell as a time.Time
func (c *Cell) GetTime(date1904 bool) (t time.Time, err error) {
	f, err := c.Float()
	if err != nil {
		return t, err
	}
	return TimeFromExcelTime(f, date1904), nil
}

/*
	The following are samples of format samples.

	* "0.00e+00"
	* "0", "#,##0"
	* "0.00", "#,##0.00", "@"
	* "#,##0 ;(#,##0)", "#,##0 ;[red](#,##0)"
	* "#,##0.00;(#,##0.00)", "#,##0.00;[red](#,##0.00)"
	* "0%", "0.00%"
	* "0.00e+00", "##0.0e+0"
*/

// SetFloatWithFormat sets the value of a cell to a float and applies
// formatting to the cell.
func (c *Cell) SetFloatWithFormat(n float64, format string) {
	// beauty the output when the float is small enough
	if n != 0 && n < 0.00001 {
		c.Value = strconv.FormatFloat(n, 'e', -1, 64)
	} else {
		c.Value = strconv.FormatFloat(n, 'f', -1, 64)
	}
	c.NumFmt = format
	c.formula = ""
	c.cellType = CellTypeNumeric
}

var timeLocationUTC, _ = time.LoadLocation("UTC")

func TimeToUTCTime(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), timeLocationUTC)
}

func TimeToExcelTime(t time.Time) float64 {
	return float64(t.Unix())/86400.0 + 25569.0
}

// SetDate sets the value of a cell to a float.
func (c *Cell) SetDate(t time.Time) {
	c.SetDateTimeWithFormat(float64(int64(TimeToExcelTime(TimeToUTCTime(t)))), builtInNumFmt[14])
}

func (c *Cell) SetDateTime(t time.Time) {
	c.SetDateTimeWithFormat(TimeToExcelTime(TimeToUTCTime(t)), builtInNumFmt[22])
}

func (c *Cell) SetDateTimeWithFormat(n float64, format string) {
	c.Value = strconv.FormatFloat(n, 'f', -1, 64)
	c.NumFmt = format
	c.formula = ""
	c.cellType = CellTypeDate
}

// Float returns the value of cell as a number.
func (c *Cell) Float() (float64, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return math.NaN(), err
	}
	return f, nil
}

// SetInt64 sets a cell's value to a 64-bit integer.
func (c *Cell) SetInt64(n int64) {
	c.SetValue(n)
}

// Int64 returns the value of cell as 64-bit integer.
func (c *Cell) Int64() (int64, error) {
	f, err := strconv.ParseInt(c.Value, 10, 64)
	if err != nil {
		return -1, err
	}
	return f, nil
}

// SetInt sets a cell's value to an integer.
func (c *Cell) SetInt(n int) {
	c.SetValue(n)
}

// SetInt sets a cell's value to an integer.
func (c *Cell) SetValue(n interface{}) {
	switch t := n.(type) {
	case time.Time:
		c.SetDateTime(n.(time.Time))
		return
	case int, int8, int16, int32, int64, float32, float64:
		c.setGeneral(fmt.Sprintf("%v", n))
	case string:
		c.SetString(t)
	case []byte:
		c.SetString(string(t))
	case nil:
		c.SetString("")
	default:
		c.SetString(fmt.Sprintf("%v", n))
	}
}

// SetInt sets a cell's value to an integer.
func (c *Cell) setGeneral(s string) {
	c.Value = s
	c.NumFmt = builtInNumFmt[builtInNumFmtIndex_GENERAL]
	c.formula = ""
	c.cellType = CellTypeGeneral
}

// Int returns the value of cell as integer.
// Has max 53 bits of precision
// See: float64(int64(math.MaxInt))
func (c *Cell) Int() (int, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return -1, err
	}
	return int(f), nil
}

// SetBool sets a cell's value to a boolean.
func (c *Cell) SetBool(b bool) {
	if b {
		c.Value = "1"
	} else {
		c.Value = "0"
	}
	c.cellType = CellTypeBool
}

// Bool returns a boolean from a cell's value.
// TODO: Determine if the current return value is
// appropriate for types other than CellTypeBool.
func (c *Cell) Bool() bool {
	// If bool, just return the value.
	if c.cellType == CellTypeBool {
		return c.Value == "1"
	}
	// If numeric, base it on a non-zero.
	if c.cellType == CellTypeNumeric || c.cellType == CellTypeGeneral {
		return c.Value != "0"
	}
	// Return whether there's an empty string.
	return c.Value != ""
}

// SetFormula sets the format string for a cell.
func (c *Cell) SetFormula(formula string) {
	c.formula = formula
	c.cellType = CellTypeFormula
}

// Formula returns the formula string for the cell.
func (c *Cell) Formula() string {
	return c.formula
}

// GetStyle returns the Style associated with a Cell
func (c *Cell) GetStyle() *Style {
	if c.style == nil {
		c.style = NewStyle()
	}
	return c.style
}

// SetStyle sets the style of a cell.
func (c *Cell) SetStyle(style *Style) {
	c.style = style
}

// GetNumberFormat returns the number format string for a cell.
func (c *Cell) GetNumberFormat() string {
	return c.NumFmt
}

func (c *Cell) formatToFloat(format string) (string, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return c.Value, err
	}
	return fmt.Sprintf(format, f), nil
}

func (c *Cell) formatToInt(format string) (string, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return c.Value, err
	}
	return fmt.Sprintf(format, int(f)), nil
}

// FormattedValue returns a value, and possibly an error condition
// from a Cell.  If it is possible to apply a format to the cell
// value, it will do so, if not then an error will be returned, along
// with the raw value of the Cell.
func (c *Cell) FormattedValue() (string, error) {
	var numberFormat = c.GetNumberFormat()
	if isTimeFormat(numberFormat) {
		return parseTime(c)
	}
	switch numberFormat {
	case builtInNumFmt[builtInNumFmtIndex_GENERAL], builtInNumFmt[builtInNumFmtIndex_STRING]:
		return c.Value, nil
	case builtInNumFmt[builtInNumFmtIndex_INT], "#,##0":
		return c.formatToInt("%d")
	case builtInNumFmt[builtInNumFmtIndex_FLOAT], "#,##0.00":
		return c.formatToFloat("%.2f")
	case "#,##0 ;(#,##0)", "#,##0 ;[red](#,##0)":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		if f < 0 {
			i := int(math.Abs(f))
			return fmt.Sprintf("(%d)", i), nil
		}
		i := int(f)
		return fmt.Sprintf("%d", i), nil
	case "#,##0.00;(#,##0.00)", "#,##0.00;[red](#,##0.00)":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		if f < 0 {
			return fmt.Sprintf("(%.2f)", f), nil
		}
		return fmt.Sprintf("%.2f", f), nil
	case "0%":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		f = f * 100
		return fmt.Sprintf("%d%%", int(f)), nil
	case "0.00%":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		f = f * 100
		return fmt.Sprintf("%.2f%%", f), nil
	case "0.00e+00", "##0.0e+0":
		return c.formatToFloat("%e")
	}
	return c.Value, nil

}

// parseTime returns a string parsed using time.Time
func parseTime(c *Cell) (string, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return c.Value, err
	}
	val := TimeFromExcelTime(f, c.date1904)
	format := c.GetNumberFormat()

	// Replace Excel placeholders with Go time placeholders.
	// For example, replace yyyy with 2006. These are in a specific order,
	// due to the fact that m is used in month, minute, and am/pm. It would
	// be easier to fix that with regular expressions, but if it's possible
	// to keep this simple it would be easier to maintain.
	// Full-length month and days (e.g. March, Tuesday) have letters in them that would be replaced
	// by other characters below (such as the 'h' in March, or the 'd' in Tuesday) below.
	// First we convert them to arbitrary characters unused in Excel Date formats, and then at the end,
	// turn them to what they should actually be.
	// Based off: http://www.ozgrid.com/Excel/CustomFormats.htm
	replacements := []struct{ xltime, gotime string }{
		{"yyyy", "2006"},
		{"yy", "06"},
		{"mmmm", "%%%%"},
		{"dddd", "&&&&"},
		{"dd", "02"},
		{"d", "2"},
		{"mmm", "Jan"},
		{"mmss", "0405"},
		{"ss", "05"},
		{"hh", "15"},
		{"h", "3"},
		{"mm:", "04:"},
		{":mm", ":04"},
		{"mm", "01"},
		{"am/pm", "pm"},
		{"m/", "1/"},
		{"%%%%", "January"},
		{"&&&&", "Monday"},
	}
	for _, repl := range replacements {
		format = strings.Replace(format, repl.xltime, repl.gotime, 1)
	}
	// If the hour is optional, strip it out, along with the
	// possible dangling colon that would remain.
	if val.Hour() < 1 {
		format = strings.Replace(format, "]:", "]", 1)
		format = strings.Replace(format, "[3]", "", 1)
		format = strings.Replace(format, "[15]", "", 1)
	} else {
		format = strings.Replace(format, "[3]", "3", 1)
		format = strings.Replace(format, "[15]", "15", 1)
	}
	return val.Format(format), nil
}

// isTimeFormat checks whether an Excel format string represents
// a time.Time.
func isTimeFormat(format string) bool {
	dateParts := []string{
		"yy", "hh", "am", "pm", "ss", "mm", ":",
	}
	for _, part := range dateParts {
		if strings.Contains(format, part) {
			return true
		}
	}
	return false
}
<commit_msg>TimeToExcelTime is tuncating time to second<commit_after>package xlsx

import (
	"fmt"
	"math"
	"strconv"
	"strings"
	"time"
)

// CellType is an int type for storing metadata about the data type in the cell.
type CellType int

// Known types for cell values.
const (
	CellTypeString CellType = iota
	CellTypeFormula
	CellTypeNumeric
	CellTypeBool
	CellTypeInline
	CellTypeError
	CellTypeDate
	CellTypeGeneral
)

// Cell is a high level structure intended to provide user access to
// the contents of Cell within an xlsx.Row.
type Cell struct {
	Row      *Row
	Value    string
	formula  string
	style    *Style
	NumFmt   string
	date1904 bool
	Hidden   bool
	HMerge   int
	VMerge   int
	cellType CellType
}

// CellInterface defines the public API of the Cell.
type CellInterface interface {
	String() string
	FormattedValue() string
}

// NewCell creates a cell and adds it to a row.
func NewCell(r *Row) *Cell {
	return &Cell{Row: r}
}

// Merge with other cells, horizontally and/or vertically.
func (c *Cell) Merge(hcells, vcells int) {
	c.HMerge = hcells
	c.VMerge = vcells
}

// Type returns the CellType of a cell. See CellType constants for more details.
func (c *Cell) Type() CellType {
	return c.cellType
}

// SetString sets the value of a cell to a string.
func (c *Cell) SetString(s string) {
	c.Value = s
	c.formula = ""
	c.cellType = CellTypeString
}

// String returns the value of a Cell as a string.
func (c *Cell) String() (string, error) {
	return c.FormattedValue()
}

// SetFloat sets the value of a cell to a float.
func (c *Cell) SetFloat(n float64) {
	c.SetValue(n)
}

//GetTime returns the value of a Cell as a time.Time
func (c *Cell) GetTime(date1904 bool) (t time.Time, err error) {
	f, err := c.Float()
	if err != nil {
		return t, err
	}
	return TimeFromExcelTime(f, date1904), nil
}

/*
	The following are samples of format samples.

	* "0.00e+00"
	* "0", "#,##0"
	* "0.00", "#,##0.00", "@"
	* "#,##0 ;(#,##0)", "#,##0 ;[red](#,##0)"
	* "#,##0.00;(#,##0.00)", "#,##0.00;[red](#,##0.00)"
	* "0%", "0.00%"
	* "0.00e+00", "##0.0e+0"
*/

// SetFloatWithFormat sets the value of a cell to a float and applies
// formatting to the cell.
func (c *Cell) SetFloatWithFormat(n float64, format string) {
	// beauty the output when the float is small enough
	if n != 0 && n < 0.00001 {
		c.Value = strconv.FormatFloat(n, 'e', -1, 64)
	} else {
		c.Value = strconv.FormatFloat(n, 'f', -1, 64)
	}
	c.NumFmt = format
	c.formula = ""
	c.cellType = CellTypeNumeric
}

var timeLocationUTC, _ = time.LoadLocation("UTC")

func TimeToUTCTime(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), timeLocationUTC)
}

func TimeToExcelTime(t time.Time) float64 {
	return float64(t.UnixNano())/8.64e13 + 25569.0
}

// SetDate sets the value of a cell to a float.
func (c *Cell) SetDate(t time.Time) {
	c.SetDateTimeWithFormat(float64(int64(TimeToExcelTime(TimeToUTCTime(t)))), builtInNumFmt[14])
}

func (c *Cell) SetDateTime(t time.Time) {
	c.SetDateTimeWithFormat(TimeToExcelTime(TimeToUTCTime(t)), builtInNumFmt[22])
}

func (c *Cell) SetDateTimeWithFormat(n float64, format string) {
	c.Value = strconv.FormatFloat(n, 'f', -1, 64)
	c.NumFmt = format
	c.formula = ""
	c.cellType = CellTypeDate
}

// Float returns the value of cell as a number.
func (c *Cell) Float() (float64, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return math.NaN(), err
	}
	return f, nil
}

// SetInt64 sets a cell's value to a 64-bit integer.
func (c *Cell) SetInt64(n int64) {
	c.SetValue(n)
}

// Int64 returns the value of cell as 64-bit integer.
func (c *Cell) Int64() (int64, error) {
	f, err := strconv.ParseInt(c.Value, 10, 64)
	if err != nil {
		return -1, err
	}
	return f, nil
}

// SetInt sets a cell's value to an integer.
func (c *Cell) SetInt(n int) {
	c.SetValue(n)
}

// SetInt sets a cell's value to an integer.
func (c *Cell) SetValue(n interface{}) {
	switch t := n.(type) {
	case time.Time:
		c.SetDateTime(n.(time.Time))
		return
	case int, int8, int16, int32, int64, float32, float64:
		c.setGeneral(fmt.Sprintf("%v", n))
	case string:
		c.SetString(t)
	case []byte:
		c.SetString(string(t))
	case nil:
		c.SetString("")
	default:
		c.SetString(fmt.Sprintf("%v", n))
	}
}

// SetInt sets a cell's value to an integer.
func (c *Cell) setGeneral(s string) {
	c.Value = s
	c.NumFmt = builtInNumFmt[builtInNumFmtIndex_GENERAL]
	c.formula = ""
	c.cellType = CellTypeGeneral
}

// Int returns the value of cell as integer.
// Has max 53 bits of precision
// See: float64(int64(math.MaxInt))
func (c *Cell) Int() (int, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return -1, err
	}
	return int(f), nil
}

// SetBool sets a cell's value to a boolean.
func (c *Cell) SetBool(b bool) {
	if b {
		c.Value = "1"
	} else {
		c.Value = "0"
	}
	c.cellType = CellTypeBool
}

// Bool returns a boolean from a cell's value.
// TODO: Determine if the current return value is
// appropriate for types other than CellTypeBool.
func (c *Cell) Bool() bool {
	// If bool, just return the value.
	if c.cellType == CellTypeBool {
		return c.Value == "1"
	}
	// If numeric, base it on a non-zero.
	if c.cellType == CellTypeNumeric || c.cellType == CellTypeGeneral {
		return c.Value != "0"
	}
	// Return whether there's an empty string.
	return c.Value != ""
}

// SetFormula sets the format string for a cell.
func (c *Cell) SetFormula(formula string) {
	c.formula = formula
	c.cellType = CellTypeFormula
}

// Formula returns the formula string for the cell.
func (c *Cell) Formula() string {
	return c.formula
}

// GetStyle returns the Style associated with a Cell
func (c *Cell) GetStyle() *Style {
	if c.style == nil {
		c.style = NewStyle()
	}
	return c.style
}

// SetStyle sets the style of a cell.
func (c *Cell) SetStyle(style *Style) {
	c.style = style
}

// GetNumberFormat returns the number format string for a cell.
func (c *Cell) GetNumberFormat() string {
	return c.NumFmt
}

func (c *Cell) formatToFloat(format string) (string, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return c.Value, err
	}
	return fmt.Sprintf(format, f), nil
}

func (c *Cell) formatToInt(format string) (string, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return c.Value, err
	}
	return fmt.Sprintf(format, int(f)), nil
}

// FormattedValue returns a value, and possibly an error condition
// from a Cell.  If it is possible to apply a format to the cell
// value, it will do so, if not then an error will be returned, along
// with the raw value of the Cell.
func (c *Cell) FormattedValue() (string, error) {
	var numberFormat = c.GetNumberFormat()
	if isTimeFormat(numberFormat) {
		return parseTime(c)
	}
	switch numberFormat {
	case builtInNumFmt[builtInNumFmtIndex_GENERAL], builtInNumFmt[builtInNumFmtIndex_STRING]:
		return c.Value, nil
	case builtInNumFmt[builtInNumFmtIndex_INT], "#,##0":
		return c.formatToInt("%d")
	case builtInNumFmt[builtInNumFmtIndex_FLOAT], "#,##0.00":
		return c.formatToFloat("%.2f")
	case "#,##0 ;(#,##0)", "#,##0 ;[red](#,##0)":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		if f < 0 {
			i := int(math.Abs(f))
			return fmt.Sprintf("(%d)", i), nil
		}
		i := int(f)
		return fmt.Sprintf("%d", i), nil
	case "#,##0.00;(#,##0.00)", "#,##0.00;[red](#,##0.00)":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		if f < 0 {
			return fmt.Sprintf("(%.2f)", f), nil
		}
		return fmt.Sprintf("%.2f", f), nil
	case "0%":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		f = f * 100
		return fmt.Sprintf("%d%%", int(f)), nil
	case "0.00%":
		f, err := strconv.ParseFloat(c.Value, 64)
		if err != nil {
			return c.Value, err
		}
		f = f * 100
		return fmt.Sprintf("%.2f%%", f), nil
	case "0.00e+00", "##0.0e+0":
		return c.formatToFloat("%e")
	}
	return c.Value, nil

}

// parseTime returns a string parsed using time.Time
func parseTime(c *Cell) (string, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return c.Value, err
	}
	val := TimeFromExcelTime(f, c.date1904)
	format := c.GetNumberFormat()

	// Replace Excel placeholders with Go time placeholders.
	// For example, replace yyyy with 2006. These are in a specific order,
	// due to the fact that m is used in month, minute, and am/pm. It would
	// be easier to fix that with regular expressions, but if it's possible
	// to keep this simple it would be easier to maintain.
	// Full-length month and days (e.g. March, Tuesday) have letters in them that would be replaced
	// by other characters below (such as the 'h' in March, or the 'd' in Tuesday) below.
	// First we convert them to arbitrary characters unused in Excel Date formats, and then at the end,
	// turn them to what they should actually be.
	// Based off: http://www.ozgrid.com/Excel/CustomFormats.htm
	replacements := []struct{ xltime, gotime string }{
		{"yyyy", "2006"},
		{"yy", "06"},
		{"mmmm", "%%%%"},
		{"dddd", "&&&&"},
		{"dd", "02"},
		{"d", "2"},
		{"mmm", "Jan"},
		{"mmss", "0405"},
		{"ss", "05"},
		{"hh", "15"},
		{"h", "3"},
		{"mm:", "04:"},
		{":mm", ":04"},
		{"mm", "01"},
		{"am/pm", "pm"},
		{"m/", "1/"},
		{"%%%%", "January"},
		{"&&&&", "Monday"},
	}
	for _, repl := range replacements {
		format = strings.Replace(format, repl.xltime, repl.gotime, 1)
	}
	// If the hour is optional, strip it out, along with the
	// possible dangling colon that would remain.
	if val.Hour() < 1 {
		format = strings.Replace(format, "]:", "]", 1)
		format = strings.Replace(format, "[3]", "", 1)
		format = strings.Replace(format, "[15]", "", 1)
	} else {
		format = strings.Replace(format, "[3]", "3", 1)
		format = strings.Replace(format, "[15]", "15", 1)
	}
	return val.Format(format), nil
}

// isTimeFormat checks whether an Excel format string represents
// a time.Time.
func isTimeFormat(format string) bool {
	dateParts := []string{
		"yy", "hh", "am", "pm", "ss", "mm", ":",
	}
	for _, part := range dateParts {
		if strings.Contains(format, part) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package cete

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"math"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/1lann/badger"
	"github.com/1lann/msgpack"
)

// Common errors that can be returned
var (
	ErrAlreadyExists  = errors.New("cete: already exists")
	ErrNotFound       = errors.New("cete: not found")
	ErrBadIdentifier  = errors.New("cete: bad identifier")
	ErrEndOfRange     = errors.New("cete: end of range")
	ErrCounterChanged = errors.New("cete: counter changed")
	ErrIndexError     = errors.New("cete: index error")
)

// Name represents a table or index identifier.
type Name string

// Hex returns the hexadecimal representation of the name.
func (n Name) Hex() string {
	return hex.EncodeToString([]byte(n))
}

// Index represents an index of a table.
type Index struct {
	index *badger.KV
	table *Table
}

// Table represents a table in the database.
type Table struct {
	indexes map[Name]*Index
	data    *badger.KV
	db      *DB

	compressionLock *sync.RWMutex
	keyToCompressed map[string]string
	compressedToKey map[string]string
	nextKey         string
}

// DB represents the database.
type DB struct {
	path        string
	tables      map[Name]*Table
	config      dbConfig
	configMutex *sync.Mutex
	openOptions badger.Options
	closed      int32
}

func exists(path string) (bool, error) {
	stat, err := os.Stat(path)
	if err == nil {
		if !stat.IsDir() {
			return false, nil
		}
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return true, err
}

func integerToBytes(integer interface{}) []byte {
	var num uint64
	switch i := integer.(type) {
	case int:
		num = uint64(i) + (1 << 63)
	case int16:
		num = uint64(i) + (1 << 63)
	case int32:
		num = uint64(i) + (1 << 63)
	case int64:
		num = uint64(i) + (1 << 63)
	case uint16:
		num = uint64(i) + (1 << 63)
	case uint32:
		num = uint64(i) + (1 << 63)
	case uint64:
		num = i + (1 << 63)
	default:
		log.Fatal("integerToBytes called on a non integer: ", i)
	}

	result := make([]byte, 8)
	binary.BigEndian.PutUint64(result, num)
	return result
}

func valueToBytes(value interface{}) (b []byte) {
	switch v := value.(type) {
	case int, int16, int32, int64, uint16, uint32, uint64:
		return integerToBytes(v)
	case float32:
		return integerToBytes(math.Float32bits(v))
	case float64:
		return integerToBytes(math.Float64bits(v))
	case string:
		return append([]byte(strings.ToLower(v)), 0)
	case []byte:
		return append(v, 0)
	case []interface{}:
		var result []byte
		for _, vv := range v {
			result = append(result, valueToBytes(vv)...)
		}
		return result
	case time.Time:
		return append(valueToBytes(v.Unix()), valueToBytes(v.Nanosecond())...)
	case Bounds:
		return integerToBytes(int64(v))
	}

	panic(fmt.Sprintf("cete: unsupported value: %v", value))
}

func getItemValue(item *badger.KVItem) []byte {
	result := make(chan []byte, 1)
	err := item.Value(func(value []byte) error {
		result <- value
		return nil
	})
	if err != nil {
		return nil
	}
	return <-result
}

// Document represents the value of a document.
type Document struct {
	data  []byte
	table *Table
}

// QueryInt returns the int value of a QueryOne assumed to contain an int.
func (v Document) QueryInt(query string) int {
	r, ok := v.QueryOne(query).(uint64)
	if !ok {
		return 0
	}

	return int(r)
}

// QueryInt64 returns the int64 value of a QueryOne assumed to contain an int64.
func (v Document) QueryInt64(query string) int64 {
	r, ok := v.QueryOne(query).(uint64)
	if !ok {
		return 0
	}

	return int64(r)
}

// QueryFloat64 returns the float64 value of a QueryOne assumed to contain a float64.
func (v Document) QueryFloat64(query string) float64 {
	r, ok := v.QueryOne(query).(float64)
	if !ok {
		return 0
	}

	return r
}

// QueryString returns the string value of a QueryOne assumed to contain a string.
func (v Document) QueryString(query string) string {
	r, ok := v.QueryOne(query).(string)
	if !ok {
		return ""
	}

	return r
}

// QueryBytes returns the []byte value of a QueryOne assumed to contain a []byte.
func (v Document) QueryBytes(query string) []byte {
	r, ok := v.QueryOne(query).([]byte)
	if !ok {
		return nil
	}

	return r
}

// QueryTime returns the time.Time value of a QueryOne assumed to contain a time.Time.
func (v Document) QueryTime(query string) time.Time {
	t, ok := v.QueryOne(query).([]interface{})
	if !ok {
		return time.Time{}
	}
	return time.Unix(int64(t[0].(uint64)), int64(t[1].(uint64)))
}

// QueryOne returns the first matching value of a msgpack query.
func (v Document) QueryOne(query string) interface{} {
	results := v.QueryAll(query)
	if len(results) == 0 {
		return nil
	}

	return results[0]
}

// QueryAll returns the first matching value of a msgpack query.
func (v Document) QueryAll(query string) []interface{} {
	var results []interface{}
	var err error
	if v.table != nil && v.table.keyToCompressed != nil {
		results, err = msgpack.NewDecoder(bytes.NewReader(v.data)).
			QueryCompressed(v.table.keyToC, query)
	} else {
		results, err = msgpack.NewDecoder(bytes.NewReader(v.data)).Query(query)
	}

	if err != nil || len(results) == 0 {
		return nil
	}
	return results
}

// Decode attempts to decodes the document to an interface using reflection.
func (v Document) Decode(dst interface{}) error {
	if v.table != nil && v.table.keyToCompressed != nil {
		return msgpack.UnmarshalCompressed(v.table.cToKey, v.data, dst)
	}

	return msgpack.Unmarshal(v.data, dst)
}
<commit_msg>fix: strange bugs<commit_after>package cete

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"math"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/1lann/badger"
	"github.com/1lann/msgpack"
)

// Common errors that can be returned
var (
	ErrAlreadyExists  = errors.New("cete: already exists")
	ErrNotFound       = errors.New("cete: not found")
	ErrBadIdentifier  = errors.New("cete: bad identifier")
	ErrEndOfRange     = errors.New("cete: end of range")
	ErrCounterChanged = errors.New("cete: counter changed")
	ErrIndexError     = errors.New("cete: index error")
)

// Name represents a table or index identifier.
type Name string

// Hex returns the hexadecimal representation of the name.
func (n Name) Hex() string {
	return hex.EncodeToString([]byte(n))
}

// Index represents an index of a table.
type Index struct {
	index *badger.KV
	table *Table
}

// Table represents a table in the database.
type Table struct {
	indexes map[Name]*Index
	data    *badger.KV
	db      *DB

	compressionLock *sync.RWMutex
	keyToCompressed map[string]string
	compressedToKey map[string]string
	nextKey         string
}

// DB represents the database.
type DB struct {
	path        string
	tables      map[Name]*Table
	config      dbConfig
	configMutex *sync.Mutex
	openOptions badger.Options
	closed      int32
}

func exists(path string) (bool, error) {
	stat, err := os.Stat(path)
	if err == nil {
		if !stat.IsDir() {
			return false, nil
		}
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return true, err
}

func integerToBytes(integer interface{}) []byte {
	var num uint64
	switch i := integer.(type) {
	case int:
		num = uint64(i) + (1 << 63)
	case int16:
		num = uint64(i) + (1 << 63)
	case int32:
		num = uint64(i) + (1 << 63)
	case int64:
		num = uint64(i) + (1 << 63)
	case uint16:
		num = uint64(i) + (1 << 63)
	case uint32:
		num = uint64(i) + (1 << 63)
	case uint64:
		num = i + (1 << 63)
	default:
		log.Fatal("integerToBytes called on a non integer: ", i)
	}

	result := make([]byte, 8)
	binary.BigEndian.PutUint64(result, num)
	return result
}

func valueToBytes(value interface{}) (b []byte) {
	switch v := value.(type) {
	case int, int16, int32, int64, uint16, uint32, uint64:
		return integerToBytes(v)
	case float32:
		return integerToBytes(math.Float32bits(v))
	case float64:
		return integerToBytes(math.Float64bits(v))
	case string:
		return append([]byte(strings.ToLower(v)), 0)
	case []byte:
		return append(v, 0)
	case []interface{}:
		var result []byte
		for _, vv := range v {
			result = append(result, valueToBytes(vv)...)
		}
		return result
	case time.Time:
		return append(valueToBytes(v.Unix()), valueToBytes(v.Nanosecond())...)
	case Bounds:
		return integerToBytes(int64(v))
	}

	panic(fmt.Sprintf("cete: unsupported value: %v", value))
}

func getItemValue(item *badger.KVItem) []byte {
	if item == nil {
		return nil
	}

	result := make(chan []byte, 1)
	err := item.Value(func(value []byte) error {
		result <- value
		return nil
	})
	if err != nil {
		return nil
	}
	return <-result
}

// Document represents the value of a document.
type Document struct {
	data  []byte
	table *Table
}

// QueryInt returns the int value of a QueryOne assumed to contain an int.
func (v Document) QueryInt(query string) int {
	r, ok := v.QueryOne(query).(int64)
	if !ok {
		return 0
	}

	return int(r)
}

// QueryInt64 returns the int64 value of a QueryOne assumed to contain an int64.
func (v Document) QueryInt64(query string) int64 {
	r, ok := v.QueryOne(query).(int64)
	if !ok {
		return 0
	}

	return int64(r)
}

// QueryFloat64 returns the float64 value of a QueryOne assumed to contain a float64.
func (v Document) QueryFloat64(query string) float64 {
	r, ok := v.QueryOne(query).(float64)
	if !ok {
		return 0
	}

	return r
}

// QueryString returns the string value of a QueryOne assumed to contain a string.
func (v Document) QueryString(query string) string {
	r, ok := v.QueryOne(query).(string)
	if !ok {
		return ""
	}

	return r
}

// QueryBytes returns the []byte value of a QueryOne assumed to contain a []byte.
func (v Document) QueryBytes(query string) []byte {
	r, ok := v.QueryOne(query).([]byte)
	if !ok {
		return nil
	}

	return r
}

// QueryTime returns the time.Time value of a QueryOne assumed to contain a time.Time.
func (v Document) QueryTime(query string) time.Time {
	t, ok := v.QueryOne(query).(*time.Time)
	if !ok {
		return time.Time{}
	}
	return *t
}

// QueryOne returns the first matching value of a msgpack query.
func (v Document) QueryOne(query string) interface{} {
	results := v.QueryAll(query)
	if len(results) == 0 {
		return nil
	}

	return results[0]
}

// QueryAll returns the first matching value of a msgpack query.
func (v Document) QueryAll(query string) []interface{} {
	var results []interface{}
	var err error
	if v.table != nil && v.table.keyToCompressed != nil {
		results, err = msgpack.NewDecoder(bytes.NewReader(v.data)).
			QueryCompressed(v.table.keyToC, query)
	} else {
		results, err = msgpack.NewDecoder(bytes.NewReader(v.data)).Query(query)
	}

	if err != nil || len(results) == 0 {
		return nil
	}
	return results
}

// Decode attempts to decodes the document to an interface using reflection.
func (v Document) Decode(dst interface{}) error {
	if v.table != nil && v.table.keyToCompressed != nil {
		return msgpack.UnmarshalCompressed(v.table.cToKey, v.data, dst)
	}

	return msgpack.Unmarshal(v.data, dst)
}
<|endoftext|>