<commit_before>package deb

import (
	"fmt"
	"github.com/smira/aptly/aptly"
	"github.com/smira/aptly/utils"
	"sort"
)

// Dependency options
const (
	// DepFollowSource pulls source packages when required
	DepFollowSource = 1 << iota
	// DepFollowSuggests pulls from suggests
	DepFollowSuggests
	// DepFollowRecommends pulls from recommends
	DepFollowRecommends
	// DepFollowAllVariants follows all variants if depends on "a | b"
	DepFollowAllVariants
	// DepFollowBuild pulls build dependencies
	DepFollowBuild
)

// PackageList is list of unique (by key) packages
//
// It could be seen as repo snapshot, repo contents, result of filtering,
// merge, etc.
//
// If indexed, PackageList starts supporting searching
type PackageList struct {
	// Straight list of packages as map
	packages map[string]*Package
	// Has index been prepared?
	indexed bool
	// Indexed list of packages, sorted by name internally
	packagesIndex []*Package
	// Map of packages for each virtual package (provides)
	providesIndex map[string][]*Package
}

// Verify interface
var (
	_ sort.Interface = &PackageList{}
	_ PackageCatalog = &PackageList{}
)

// NewPackageList creates empty package list
func NewPackageList() *PackageList {
	return &PackageList{packages: make(map[string]*Package, 1000)}
}

// NewPackageListFromRefList loads packages list from PackageRefList
func NewPackageListFromRefList(reflist *PackageRefList, collection *PackageCollection, progress aptly.Progress) (*PackageList, error) {
	// empty reflist
	if reflist == nil {
		return NewPackageList(), nil
	}

	result := &PackageList{packages: make(map[string]*Package, reflist.Len())}

	if progress != nil {
		progress.InitBar(int64(reflist.Len()), false)
	}

	err := reflist.ForEach(func(key []byte) error {
		p, err2 := collection.ByKey(key)
		if err2 != nil {
			return fmt.Errorf("unable to load package with key %s: %s", key, err2)
		}
		if progress != nil {
			progress.AddBar(1)
		}
		return result.Add(p)
	})

	if progress != nil {
		progress.ShutdownBar()
	}

	if err != nil {
		return nil, err
	}

	return result, nil
}

// Add appends package to package list, additionally checking for uniqueness
func (l *PackageList) Add(p *Package) error {
	key := string(p.ShortKey(""))
	existing, ok := l.packages[key]
	if ok {
		if !existing.Equals(p) {
			return fmt.Errorf("conflict in package %s", p)
		}
		return nil
	}
	l.packages[key] = p

	if l.indexed {
		for _, provides := range p.Provides {
			l.providesIndex[provides] = append(l.providesIndex[provides], p)
		}

		i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.lessPackages(p, l.packagesIndex[j]) })

		// insert p into l.packagesIndex in position i
		l.packagesIndex = append(l.packagesIndex, nil)
		copy(l.packagesIndex[i+1:], l.packagesIndex[i:])
		l.packagesIndex[i] = p
	}
	return nil
}

// ForEach calls handler for each package in list
func (l *PackageList) ForEach(handler func(*Package) error) error {
	var err error
	for _, p := range l.packages {
		err = handler(p)
		if err != nil {
			return err
		}
	}
	return err
}

// ForEachIndexed calls handler for each package in list in indexed order
func (l *PackageList) ForEachIndexed(handler func(*Package) error) error {
	if !l.indexed {
		panic("list not indexed, can't iterate")
	}

	var err error
	for _, p := range l.packagesIndex {
		err = handler(p)
		if err != nil {
			return err
		}
	}
	return err
}

// Len returns number of packages in the list
func (l *PackageList) Len() int {
	return len(l.packages)
}

// Append adds content from one package list to another
func (l *PackageList) Append(pl *PackageList) error {
	if l.indexed {
		panic("Append not supported when indexed")
	}
	for k, p := range pl.packages {
		existing, ok := l.packages[k]
		if ok {
			if !existing.Equals(p) {
				return fmt.Errorf("conflict in package %s", p)
			}
		} else {
			l.packages[k] = p
		}
	}

	return nil
}

// Remove removes package from the list, and updates index when required
func (l *PackageList) Remove(p *Package) {
	delete(l.packages, string(p.ShortKey("")))
	if l.indexed {
		for _, provides := range p.Provides {
			for i, pkg := range l.providesIndex[provides] {
				if pkg.Equals(p) {
					// remove l.ProvidesIndex[provides][i] w/o preserving order
					l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][i], l.providesIndex[provides] =
						nil, l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][:len(l.providesIndex[provides])-1]
					break
				}
			}
		}

		i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= p.Name })
		for i < len(l.packagesIndex) && l.packagesIndex[i].Name == p.Name {
			if l.packagesIndex[i].Equals(p) {
				// remove l.packagesIndex[i] preserving order
				copy(l.packagesIndex[i:], l.packagesIndex[i+1:])
				l.packagesIndex[len(l.packagesIndex)-1] = nil
				l.packagesIndex = l.packagesIndex[:len(l.packagesIndex)-1]
				break
			}
			i++
		}
	}
}

// Architectures returns list of architectures present in packages and flag if source packages are present.
//
// If includeSource is true, meta-architecture "source" would be present in the list
func (l *PackageList) Architectures(includeSource bool) (result []string) {
	result = make([]string, 0, 10)
	for _, pkg := range l.packages {
		if pkg.Architecture != "all" && (pkg.Architecture != "source" || includeSource) && !utils.StrSliceHasItem(result, pkg.Architecture) {
			result = append(result, pkg.Architecture)
		}
	}
	return
}

// depSliceDeduplicate removes dups in slice of Dependencies
func depSliceDeduplicate(s []Dependency) []Dependency {
	l := len(s)
	if l < 2 {
		return s
	}
	if l == 2 {
		if s[0] == s[1] {
			return s[0:1]
		}
		return s
	}

	found := make(map[string]bool, l)
	j := 0
	for i, x := range s {
		h := x.Hash()
		if !found[h] {
			found[h] = true
			s[j] = s[i]
			j++
		}
	}

	return s[:j]
}

// VerifyDependencies looks for missing dependencies in package list.
//
// Analysis would be peformed for each architecture, in specified sources
func (l *PackageList) VerifyDependencies(options int, architectures []string, sources *PackageList, progress aptly.Progress) ([]Dependency, error) {
	l.PrepareIndex()
	missing := make([]Dependency, 0, 128)

	if progress != nil {
		progress.InitBar(int64(l.Len())*int64(len(architectures)), false)
	}

	for _, arch := range architectures {
		cache := make(map[string]bool, 2048)

		for _, p := range l.packagesIndex {
			if progress != nil {
				progress.AddBar(1)
			}

			if !p.MatchesArchitecture(arch) {
				continue
			}

			for _, dep := range p.GetDependencies(options) {
				variants, err := ParseDependencyVariants(dep)
				if err != nil {
					return nil, fmt.Errorf("unable to process package %s: %s", p, err)
				}

				variants = depSliceDeduplicate(variants)

				variantsMissing := make([]Dependency, 0, len(variants))

				for _, dep := range variants {
					if dep.Architecture == "" {
						dep.Architecture = arch
					}

					hash := dep.Hash()
					satisfied, ok := cache[hash]
					if !ok {
						satisfied = sources.Search(dep, false) != nil
						cache[hash] = satisfied
					}

					if !satisfied && !ok {
						variantsMissing = append(variantsMissing, dep)
					}

					if satisfied && options&DepFollowAllVariants == 0 {
						variantsMissing = nil
						break
					}
				}

				missing = append(missing, variantsMissing...)
			}
		}
	}

	if progress != nil {
		progress.ShutdownBar()
	}

	return missing, nil
}

// Swap swaps two packages in index
func (l *PackageList) Swap(i, j int) {
	l.packagesIndex[i], l.packagesIndex[j] = l.packagesIndex[j], l.packagesIndex[i]
}

func (l *PackageList) lessPackages(iPkg, jPkg *Package) bool {
	if iPkg.Name == jPkg.Name {
		cmp := CompareVersions(iPkg.Version, jPkg.Version)
		if cmp == 0 {
			return iPkg.Architecture < jPkg.Architecture
		}
		return cmp == 1
	}

	return iPkg.Name < jPkg.Name
}

// Less compares two packages by name (lexographical) and version (latest to oldest)
func (l *PackageList) Less(i, j int) bool {
	return l.lessPackages(l.packagesIndex[i], l.packagesIndex[j])
}

// PrepareIndex prepares list for indexing
func (l *PackageList) PrepareIndex() {
	if l.indexed {
		return
	}

	l.packagesIndex = make([]*Package, l.Len())
	l.providesIndex = make(map[string][]*Package, 128)

	i := 0
	for _, p := range l.packages {
		l.packagesIndex[i] = p
		i++

		for _, provides := range p.Provides {
			l.providesIndex[provides] = append(l.providesIndex[provides], p)
		}
	}

	sort.Sort(l)

	l.indexed = true
}

// Scan searches package index using full scan
func (l *PackageList) Scan(q PackageQuery) (result *PackageList) {
	result = NewPackageList()
	for _, pkg := range l.packages {
		if q.Matches(pkg) {
			result.Add(pkg)
		}
	}

	return
}

// SearchSupported returns true for PackageList
func (l *PackageList) SearchSupported() bool {
	return true
}

// SearchByKey looks up package by exact key reference
func (l *PackageList) SearchByKey(arch, name, version string) (result *PackageList) {
	result = NewPackageList()

	pkg := l.packages["P"+arch+" "+name+" "+version]
	if pkg != nil {
		result.Add(pkg)
	}

	return
}

// Search searches package index for specified package(s) using optimized queries
func (l *PackageList) Search(dep Dependency, allMatches bool) (searchResults []*Package) {
	if !l.indexed {
		panic("list not indexed, can't search")
	}

	if dep.Relation == VersionDontCare {
		for _, p := range l.providesIndex[dep.Pkg] {
			if dep.Architecture == "" || p.MatchesArchitecture(dep.Architecture) {
				searchResults = append(searchResults, p)

				if !allMatches {
					break
				}
			}
		}
	}

	i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= dep.Pkg })

	for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
		p := l.packagesIndex[i]
		if p.MatchesDependency(dep) {
			searchResults = append(searchResults, p)

			if !allMatches {
				break
			}
		}

		i++
	}

	return
}

// Filter filters package index by specified queries (ORed together), possibly pulling dependencies
func (l *PackageList) Filter(queries []PackageQuery, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string) (*PackageList, error) {
	if !l.indexed {
		panic("list not indexed, can't filter")
	}

	result := NewPackageList()

	for _, query := range queries {
		result.Append(query.Query(l))
	}

	if withDependencies {
		added := result.Len()
		result.PrepareIndex()

		dependencySource := NewPackageList()
		if source != nil {
			dependencySource.Append(source)
		}
		dependencySource.Append(result)
		dependencySource.PrepareIndex()

		// while some new dependencies were discovered
		for added > 0 {
			added = 0

			// find missing dependencies
			missing, err := result.VerifyDependencies(dependencyOptions, architecturesList, dependencySource, nil)
			if err != nil {
				return nil, err
			}

			// try to satisfy dependencies
			for _, dep := range missing {
				// dependency might have already been satisfied
				// with packages already been added
				if result.Search(dep, false) != nil {
					continue
				}

				searchResults := l.Search(dep, false)
				if searchResults != nil {
					for _, p := range searchResults {
						result.Add(p)
						dependencySource.Add(p)
						added++
						if dependencyOptions&DepFollowAllVariants == 0 {
							break
						}
					}
				}
			}
		}
	}

	return result, nil
}
<commit_msg>Strings() for PackageList: turning list into sequence of package Ids. #116<commit_after>package deb

import (
	"fmt"
	"github.com/smira/aptly/aptly"
	"github.com/smira/aptly/utils"
	"sort"
)

// Dependency options
const (
	// DepFollowSource pulls source packages when required
	DepFollowSource = 1 << iota
	// DepFollowSuggests pulls from suggests
	DepFollowSuggests
	// DepFollowRecommends pulls from recommends
	DepFollowRecommends
	// DepFollowAllVariants follows all variants if depends on "a | b"
	DepFollowAllVariants
	// DepFollowBuild pulls build dependencies
	DepFollowBuild
)

// PackageList is list of unique (by key) packages
//
// It could be seen as repo snapshot, repo contents, result of filtering,
// merge, etc.
//
// If indexed, PackageList starts supporting searching
type PackageList struct {
	// Straight list of packages as map
	packages map[string]*Package
	// Has index been prepared?
	indexed bool
	// Indexed list of packages, sorted by name internally
	packagesIndex []*Package
	// Map of packages for each virtual package (provides)
	providesIndex map[string][]*Package
}

// Verify interface
var (
	_ sort.Interface = &PackageList{}
	_ PackageCatalog = &PackageList{}
)

// NewPackageList creates empty package list
func NewPackageList() *PackageList {
	return &PackageList{packages: make(map[string]*Package, 1000)}
}

// NewPackageListFromRefList loads packages list from PackageRefList
func NewPackageListFromRefList(reflist *PackageRefList, collection *PackageCollection, progress aptly.Progress) (*PackageList, error) {
	// empty reflist
	if reflist == nil {
		return NewPackageList(), nil
	}

	result := &PackageList{packages: make(map[string]*Package, reflist.Len())}

	if progress != nil {
		progress.InitBar(int64(reflist.Len()), false)
	}

	err := reflist.ForEach(func(key []byte) error {
		p, err2 := collection.ByKey(key)
		if err2 != nil {
			return fmt.Errorf("unable to load package with key %s: %s", key, err2)
		}
		if progress != nil {
			progress.AddBar(1)
		}
		return result.Add(p)
	})

	if progress != nil {
		progress.ShutdownBar()
	}

	if err != nil {
		return nil, err
	}

	return result, nil
}

// Add appends package to package list, additionally checking for uniqueness
func (l *PackageList) Add(p *Package) error {
	key := string(p.ShortKey(""))
	existing, ok := l.packages[key]
	if ok {
		if !existing.Equals(p) {
			return fmt.Errorf("conflict in package %s", p)
		}
		return nil
	}
	l.packages[key] = p

	if l.indexed {
		for _, provides := range p.Provides {
			l.providesIndex[provides] = append(l.providesIndex[provides], p)
		}

		i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.lessPackages(p, l.packagesIndex[j]) })

		// insert p into l.packagesIndex in position i
		l.packagesIndex = append(l.packagesIndex, nil)
		copy(l.packagesIndex[i+1:], l.packagesIndex[i:])
		l.packagesIndex[i] = p
	}
	return nil
}

// ForEach calls handler for each package in list
func (l *PackageList) ForEach(handler func(*Package) error) error {
	var err error
	for _, p := range l.packages {
		err = handler(p)
		if err != nil {
			return err
		}
	}
	return err
}

// ForEachIndexed calls handler for each package in list in indexed order
func (l *PackageList) ForEachIndexed(handler func(*Package) error) error {
	if !l.indexed {
		panic("list not indexed, can't iterate")
	}

	var err error
	for _, p := range l.packagesIndex {
		err = handler(p)
		if err != nil {
			return err
		}
	}
	return err
}

// Len returns number of packages in the list
func (l *PackageList) Len() int {
	return len(l.packages)
}

// Append adds content from one package list to another
func (l *PackageList) Append(pl *PackageList) error {
	if l.indexed {
		panic("Append not supported when indexed")
	}
	for k, p := range pl.packages {
		existing, ok := l.packages[k]
		if ok {
			if !existing.Equals(p) {
				return fmt.Errorf("conflict in package %s", p)
			}
		} else {
			l.packages[k] = p
		}
	}

	return nil
}

// Remove removes package from the list, and updates index when required
func (l *PackageList) Remove(p *Package) {
	delete(l.packages, string(p.ShortKey("")))
	if l.indexed {
		for _, provides := range p.Provides {
			for i, pkg := range l.providesIndex[provides] {
				if pkg.Equals(p) {
					// remove l.ProvidesIndex[provides][i] w/o preserving order
					l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][i], l.providesIndex[provides] =
						nil, l.providesIndex[provides][len(l.providesIndex[provides])-1], l.providesIndex[provides][:len(l.providesIndex[provides])-1]
					break
				}
			}
		}

		i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= p.Name })
		for i < len(l.packagesIndex) && l.packagesIndex[i].Name == p.Name {
			if l.packagesIndex[i].Equals(p) {
				// remove l.packagesIndex[i] preserving order
				copy(l.packagesIndex[i:], l.packagesIndex[i+1:])
				l.packagesIndex[len(l.packagesIndex)-1] = nil
				l.packagesIndex = l.packagesIndex[:len(l.packagesIndex)-1]
				break
			}
			i++
		}
	}
}

// Architectures returns list of architectures present in packages and flag if source packages are present.
//
// If includeSource is true, meta-architecture "source" would be present in the list
func (l *PackageList) Architectures(includeSource bool) (result []string) {
	result = make([]string, 0, 10)
	for _, pkg := range l.packages {
		if pkg.Architecture != "all" && (pkg.Architecture != "source" || includeSource) && !utils.StrSliceHasItem(result, pkg.Architecture) {
			result = append(result, pkg.Architecture)
		}
	}
	return
}

// Strings builds list of strings with package keys
func (l *PackageList) Strings() []string {
	result := make([]string, l.Len())
	i := 0

	for _, p := range l.packages {
		result[i] = string(p.Key(""))
		i += 1
	}

	return result
}

// depSliceDeduplicate removes dups in slice of Dependencies
func depSliceDeduplicate(s []Dependency) []Dependency {
	l := len(s)
	if l < 2 {
		return s
	}
	if l == 2 {
		if s[0] == s[1] {
			return s[0:1]
		}
		return s
	}

	found := make(map[string]bool, l)
	j := 0
	for i, x := range s {
		h := x.Hash()
		if !found[h] {
			found[h] = true
			s[j] = s[i]
			j++
		}
	}

	return s[:j]
}

// VerifyDependencies looks for missing dependencies in package list.
//
// Analysis would be peformed for each architecture, in specified sources
func (l *PackageList) VerifyDependencies(options int, architectures []string, sources *PackageList, progress aptly.Progress) ([]Dependency, error) {
	l.PrepareIndex()
	missing := make([]Dependency, 0, 128)

	if progress != nil {
		progress.InitBar(int64(l.Len())*int64(len(architectures)), false)
	}

	for _, arch := range architectures {
		cache := make(map[string]bool, 2048)

		for _, p := range l.packagesIndex {
			if progress != nil {
				progress.AddBar(1)
			}

			if !p.MatchesArchitecture(arch) {
				continue
			}

			for _, dep := range p.GetDependencies(options) {
				variants, err := ParseDependencyVariants(dep)
				if err != nil {
					return nil, fmt.Errorf("unable to process package %s: %s", p, err)
				}

				variants = depSliceDeduplicate(variants)

				variantsMissing := make([]Dependency, 0, len(variants))

				for _, dep := range variants {
					if dep.Architecture == "" {
						dep.Architecture = arch
					}

					hash := dep.Hash()
					satisfied, ok := cache[hash]
					if !ok {
						satisfied = sources.Search(dep, false) != nil
						cache[hash] = satisfied
					}

					if !satisfied && !ok {
						variantsMissing = append(variantsMissing, dep)
					}

					if satisfied && options&DepFollowAllVariants == 0 {
						variantsMissing = nil
						break
					}
				}

				missing = append(missing, variantsMissing...)
			}
		}
	}

	if progress != nil {
		progress.ShutdownBar()
	}

	return missing, nil
}

// Swap swaps two packages in index
func (l *PackageList) Swap(i, j int) {
	l.packagesIndex[i], l.packagesIndex[j] = l.packagesIndex[j], l.packagesIndex[i]
}

func (l *PackageList) lessPackages(iPkg, jPkg *Package) bool {
	if iPkg.Name == jPkg.Name {
		cmp := CompareVersions(iPkg.Version, jPkg.Version)
		if cmp == 0 {
			return iPkg.Architecture < jPkg.Architecture
		}
		return cmp == 1
	}

	return iPkg.Name < jPkg.Name
}

// Less compares two packages by name (lexographical) and version (latest to oldest)
func (l *PackageList) Less(i, j int) bool {
	return l.lessPackages(l.packagesIndex[i], l.packagesIndex[j])
}

// PrepareIndex prepares list for indexing
func (l *PackageList) PrepareIndex() {
	if l.indexed {
		return
	}

	l.packagesIndex = make([]*Package, l.Len())
	l.providesIndex = make(map[string][]*Package, 128)

	i := 0
	for _, p := range l.packages {
		l.packagesIndex[i] = p
		i++

		for _, provides := range p.Provides {
			l.providesIndex[provides] = append(l.providesIndex[provides], p)
		}
	}

	sort.Sort(l)

	l.indexed = true
}

// Scan searches package index using full scan
func (l *PackageList) Scan(q PackageQuery) (result *PackageList) {
	result = NewPackageList()
	for _, pkg := range l.packages {
		if q.Matches(pkg) {
			result.Add(pkg)
		}
	}

	return
}

// SearchSupported returns true for PackageList
func (l *PackageList) SearchSupported() bool {
	return true
}

// SearchByKey looks up package by exact key reference
func (l *PackageList) SearchByKey(arch, name, version string) (result *PackageList) {
	result = NewPackageList()

	pkg := l.packages["P"+arch+" "+name+" "+version]
	if pkg != nil {
		result.Add(pkg)
	}

	return
}

// Search searches package index for specified package(s) using optimized queries
func (l *PackageList) Search(dep Dependency, allMatches bool) (searchResults []*Package) {
	if !l.indexed {
		panic("list not indexed, can't search")
	}

	if dep.Relation == VersionDontCare {
		for _, p := range l.providesIndex[dep.Pkg] {
			if dep.Architecture == "" || p.MatchesArchitecture(dep.Architecture) {
				searchResults = append(searchResults, p)

				if !allMatches {
					break
				}
			}
		}
	}

	i := sort.Search(len(l.packagesIndex), func(j int) bool { return l.packagesIndex[j].Name >= dep.Pkg })

	for i < len(l.packagesIndex) && l.packagesIndex[i].Name == dep.Pkg {
		p := l.packagesIndex[i]
		if p.MatchesDependency(dep) {
			searchResults = append(searchResults, p)

			if !allMatches {
				break
			}
		}

		i++
	}

	return
}

// Filter filters package index by specified queries (ORed together), possibly pulling dependencies
func (l *PackageList) Filter(queries []PackageQuery, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string) (*PackageList, error) {
	if !l.indexed {
		panic("list not indexed, can't filter")
	}

	result := NewPackageList()

	for _, query := range queries {
		result.Append(query.Query(l))
	}

	if withDependencies {
		added := result.Len()
		result.PrepareIndex()

		dependencySource := NewPackageList()
		if source != nil {
			dependencySource.Append(source)
		}
		dependencySource.Append(result)
		dependencySource.PrepareIndex()

		// while some new dependencies were discovered
		for added > 0 {
			added = 0

			// find missing dependencies
			missing, err := result.VerifyDependencies(dependencyOptions, architecturesList, dependencySource, nil)
			if err != nil {
				return nil, err
			}

			// try to satisfy dependencies
			for _, dep := range missing {
				// dependency might have already been satisfied
				// with packages already been added
				if result.Search(dep, false) != nil {
					continue
				}

				searchResults := l.Search(dep, false)
				if searchResults != nil {
					for _, p := range searchResults {
						result.Add(p)
						dependencySource.Add(p)
						added++
						if dependencyOptions&DepFollowAllVariants == 0 {
							break
						}
					}
				}
			}
		}
	}

	return result, nil
}
<|endoftext|>


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

package delegation

import (
	"fmt"
	"net"

	"golang.org/x/net/context"
	"google.golang.org/appengine"

	"go.chromium.org/luci/tokenserver/api/admin/v1"
	"go.chromium.org/luci/tokenserver/api/minter/v1"
	"go.chromium.org/luci/tokenserver/appengine/impl/utils"
	"go.chromium.org/luci/tokenserver/appengine/impl/utils/bqlog"
)

var delegationTokensLog = bqlog.Log{
	QueueName:           "bqlog-delegation-tokens", // see queues.yaml
	DatasetID:           "tokens",                  // see bq/README.md
	TableID:             "delegation_tokens",       // see bq/tables/delegation_tokens.schema
	DumpEntriesToLogger: true,
	DryRun:              appengine.IsDevAppServer(),
}

var emptyStringSlice = []string{}

// MintedTokenInfo is passed to LogToken.
//
// It carries all information about the token minting operation and the produced
// token.
type MintedTokenInfo struct {
	Request   *minter.MintDelegationTokenRequest  // RPC input, as is
	Response  *minter.MintDelegationTokenResponse // RPC output, as is
	ConfigRev string                              // revision of the delegation.cfg used
	Rule      *admin.DelegationRule               // the particular rule used to authorize the request
	PeerIP    net.IP                              // caller IP address
	RequestID string                              // GAE request ID that handled the RPC
	AuthDBRev int64                               // revision of groups database (or 0 if unknown)
}

// toBigQueryRow returns a JSON-ish map to upload to BigQuery.
//
// Its schema must match 'bq/tables/delegation_tokens.schema'.
func (i *MintedTokenInfo) toBigQueryRow() map[string]interface{} {
	subtok := i.Response.DelegationSubtoken
	tags := subtok.Tags
	if tags == nil {
		tags = emptyStringSlice // bigquery doesn't like null-value fields
	}
	return map[string]interface{}{
		// Information about the produced token.
		"fingerprint":        utils.TokenFingerprint(i.Response.Token),
		"token_kind":         subtok.Kind.String(),
		"token_id":           fmt.Sprintf("%d", subtok.SubtokenId),
		"delegated_identity": subtok.DelegatedIdentity,
		"requestor_identity": subtok.RequestorIdentity,
		"issued_at":          float64(subtok.CreationTime),
		"expiration":         float64(subtok.CreationTime + int64(subtok.ValidityDuration)),
		"target_audience":    subtok.Audience,
		"target_services":    subtok.Services,
		"tags":               tags,

		// Information about the request.
		"requested_validity": int(i.Request.ValidityDuration),
		"requested_intent":   i.Request.Intent,

		// Information about the delegation rule used.
		"config_rev":  i.ConfigRev,
		"config_rule": i.Rule.Name,

		// Information about the request handler environment.
		"peer_ip":         i.PeerIP.String(),
		"service_version": i.Response.ServiceVersion,
		"gae_request_id":  i.RequestID,
		"auth_db_rev":     i.AuthDBRev,
	}
}

// LogToken records information about the token in the BigQuery.
//
// The signed token itself is not logged. Only first 16 bytes of its SHA256 hash
// (aka 'fingerprint') is. It is used only to identify this particular token in
// logs.
//
// On dev server, logs to the GAE log only, not to BigQuery (to avoid
// accidentally pushing fake data to real BigQuery dataset).
func LogToken(c context.Context, i *MintedTokenInfo) error {
	return delegationTokensLog.Insert(c, bqlog.Entry{Data: i.toBigQueryRow()})
}

// FlushTokenLog sends all buffered logged tokens to BigQuery.
//
// It is fine to call FlushTokenLog concurrently from multiple request handlers,
// if necessary (it will effectively parallelize the flush).
func FlushTokenLog(c context.Context) error {
	_, err := delegationTokensLog.Flush(c)
	return err
}
<commit_msg>token-server: Completely omit 'tags' if empty when flushing to BQ.<commit_after>// Copyright 2017 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package delegation

import (
	"fmt"
	"net"

	"golang.org/x/net/context"
	"google.golang.org/appengine"

	"go.chromium.org/luci/tokenserver/api/admin/v1"
	"go.chromium.org/luci/tokenserver/api/minter/v1"
	"go.chromium.org/luci/tokenserver/appengine/impl/utils"
	"go.chromium.org/luci/tokenserver/appengine/impl/utils/bqlog"
)

var delegationTokensLog = bqlog.Log{
	QueueName:           "bqlog-delegation-tokens", // see queues.yaml
	DatasetID:           "tokens",                  // see bq/README.md
	TableID:             "delegation_tokens",       // see bq/tables/delegation_tokens.schema
	DumpEntriesToLogger: true,
	DryRun:              appengine.IsDevAppServer(),
}

// MintedTokenInfo is passed to LogToken.
//
// It carries all information about the token minting operation and the produced
// token.
type MintedTokenInfo struct {
	Request   *minter.MintDelegationTokenRequest  // RPC input, as is
	Response  *minter.MintDelegationTokenResponse // RPC output, as is
	ConfigRev string                              // revision of the delegation.cfg used
	Rule      *admin.DelegationRule               // the particular rule used to authorize the request
	PeerIP    net.IP                              // caller IP address
	RequestID string                              // GAE request ID that handled the RPC
	AuthDBRev int64                               // revision of groups database (or 0 if unknown)
}

// toBigQueryRow returns a JSON-ish map to upload to BigQuery.
//
// Its schema must match 'bq/tables/delegation_tokens.schema'.
func (i *MintedTokenInfo) toBigQueryRow() map[string]interface{} {
	subtok := i.Response.DelegationSubtoken

	row := map[string]interface{}{
		// Information about the produced token.
		"fingerprint":        utils.TokenFingerprint(i.Response.Token),
		"token_kind":         subtok.Kind.String(),
		"token_id":           fmt.Sprintf("%d", subtok.SubtokenId),
		"delegated_identity": subtok.DelegatedIdentity,
		"requestor_identity": subtok.RequestorIdentity,
		"issued_at":          float64(subtok.CreationTime),
		"expiration":         float64(subtok.CreationTime + int64(subtok.ValidityDuration)),
		"target_audience":    subtok.Audience,
		"target_services":    subtok.Services,

		// Information about the request.
		"requested_validity": int(i.Request.ValidityDuration),
		"requested_intent":   i.Request.Intent,

		// Information about the delegation rule used.
		"config_rev":  i.ConfigRev,
		"config_rule": i.Rule.Name,

		// Information about the request handler environment.
		"peer_ip":         i.PeerIP.String(),
		"service_version": i.Response.ServiceVersion,
		"gae_request_id":  i.RequestID,
		"auth_db_rev":     i.AuthDBRev,
	}

	// Bigquery doesn't like empty lists or nulls. Omit the column completely.
	if len(subtok.Tags) != 0 {
		row["tags"] = subtok.Tags
	}

	return row
}

// LogToken records information about the token in the BigQuery.
//
// The signed token itself is not logged. Only first 16 bytes of its SHA256 hash
// (aka 'fingerprint') is. It is used only to identify this particular token in
// logs.
//
// On dev server, logs to the GAE log only, not to BigQuery (to avoid
// accidentally pushing fake data to real BigQuery dataset).
func LogToken(c context.Context, i *MintedTokenInfo) error {
	return delegationTokensLog.Insert(c, bqlog.Entry{Data: i.toBigQueryRow()})
}

// FlushTokenLog sends all buffered logged tokens to BigQuery.
//
// It is fine to call FlushTokenLog concurrently from multiple request handlers,
// if necessary (it will effectively parallelize the flush).
func FlushTokenLog(c context.Context) error {
	_, err := delegationTokensLog.Flush(c)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/fatih/color"
)

type Reporter interface {
	Report(result TestResult)
	Flush()
}

type ConsoleReporter struct {
	total  int
	failed int
}

func (r *ConsoleReporter) Report(result TestResult) {
	r.total = r.total + 1
	if result.Cause != nil {
		r.failed = r.failed + 1
		r.reportError(result)
	} else {
		r.reportSuccess(result)
	}
}

func (r ConsoleReporter) reportSuccess(result TestResult) {
	c := color.New(color.FgGreen).Add(color.Bold)
	fmt.Printf("[")
	c.Print("PASSED")
	fmt.Printf("] %s\n", result.Case.Description)
}

func (r ConsoleReporter) reportError(result TestResult) {
	c := color.New(color.FgRed).Add(color.Bold)
	fmt.Printf("[")
	c.Print("FAILED")
	fmt.Printf("] %s\n", result.Case.Description)
	lines := strings.Split(result.Cause.Error(), "\n")

	for _, line := range lines {
		fmt.Printf("\t\t%s \n", line)
	}
}

func (r ConsoleReporter) Flush() {
	fmt.Println("~~~ Summary ~~~")
	fmt.Printf("# of test cases : %v\n", r.total)
	fmt.Printf("# Errors: %v\n", r.failed)

	if r.failed > 0 {
		fmt.Println("~~~ Test run FAILURE! ~~~")
		os.Exit(1)
		return
	} // test run failed

	fmt.Println("~~~ Test run SUCCESS ~~~")
	os.Exit(0)
}

// NewConsoleReporter returns new instance of console reporter
func NewConsoleReporter() Reporter {
	return &ConsoleReporter{}
}

// JUnitXMLReporter produces separate xml file for each test sute
type JUnitXMLReporter struct {
	// output directory
	OutPath string

	// current suite
	// when suite is being changed, flush previous one
	suite *suite
}

type suite struct {
	XMLName     string `xml:"testsuite"`
	ID          int    `xml:"id,attr"`
	Name        string `xml:"name,attr"`
	PackageName string `xml:"package,attr"`
	TimeStamp   string `xml:"timestamp,attr"`
	Time        uint16 `xml:"time,attr"`
	HostName    string `xml:"hostname,attr"`

	Tests    int `xml:"tests,attr"`
	Failures int `xml:"failures,attr"`
	Errors   int `xml:"errors,attr"`

	Properties properties `xml:"properties"`
	Cases      []tc       `xml:"testcase"`

	SystemOut string `xml:"system-out"`
	SystemErr string `xml:"system-err"`
}

type properties struct {
}

type tc struct {
	Name      string   `xml:"name,attr"`
	ClassName string   `xml:"classname,attr"`
	Time      uint16   `xml:"time,attr"`
	Failure   *failure `xml:"failure,omitempty"`
}

type failure struct {
	Type string `xml:"type,attr"`
}

func (r *JUnitXMLReporter) Report(result TestResult) {
	if r.suite == nil {
		r.suite = newSuite(result)
	}

	if r.suite.Name != result.Suite.Name {
		r.flushSuite()
		r.suite = newSuite(result)
	}

	testCase := tc{Name: result.Case.Description}
	if result.Cause != nil {
		testCase.Failure = &failure{Type: result.Cause.Error()}
		r.suite.Failures = r.suite.Failures + 1
	}
	r.suite.Tests = r.suite.Tests + 1
	r.suite.ID = r.suite.ID + 1
	r.suite.Cases = append(r.suite.Cases, testCase)
}

func (r JUnitXMLReporter) flushSuite() {
	fileName := strings.Replace(r.suite.PackageName, "/", "_", -1) + r.suite.Name + ".xml"
	fp := filepath.Join(r.OutPath, fileName)
	err := os.MkdirAll(r.OutPath, 0777)
	if err != nil {
		panic(err)
	}
	f, err := os.Create(fp)
	if err != nil {
		panic(err)
	}

	data, err := xml.Marshal(r.suite)
	if err != nil {
		panic(err)
	}

	f.Write(data)
}

func newSuite(result TestResult) *suite {
	return &suite{
		ID:          0,
		Name:        result.Suite.Name,
		PackageName: result.Suite.PackageName,
		TimeStamp:   time.Now().UTC().Format("2006-01-02T15:04:05"),
		HostName:    "test",
	}
}

func (r JUnitXMLReporter) Flush() {

}

func NewJUnitReporter(outdir string) Reporter {
	return &JUnitXMLReporter{OutPath: outdir}
}
<commit_msg>junit reporter<commit_after>package main

import (
	"encoding/xml"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/fatih/color"
)

type Reporter interface {
	Report(result TestResult)
	Flush()
}

type ConsoleReporter struct {
	total  int
	failed int
}

func (r *ConsoleReporter) Report(result TestResult) {
	r.total = r.total + 1
	if result.Cause != nil {
		r.failed = r.failed + 1
		r.reportError(result)
	} else {
		r.reportSuccess(result)
	}
}

func (r ConsoleReporter) reportSuccess(result TestResult) {
	c := color.New(color.FgGreen).Add(color.Bold)
	fmt.Printf("[")
	c.Print("PASSED")
	fmt.Printf("] %s\n", result.Case.Description)
}

func (r ConsoleReporter) reportError(result TestResult) {
	c := color.New(color.FgRed).Add(color.Bold)
	fmt.Printf("[")
	c.Print("FAILED")
	fmt.Printf("] %s\n", result.Case.Description)
	lines := strings.Split(result.Cause.Error(), "\n")

	for _, line := range lines {
		fmt.Printf("\t\t%s \n", line)
	}
}

func (r ConsoleReporter) Flush() {
	fmt.Println("~~~ Summary ~~~")
	fmt.Printf("# of test cases : %v\n", r.total)
	fmt.Printf("# Errors: %v\n", r.failed)

	if r.failed > 0 {
		fmt.Println("~~~ Test run FAILURE! ~~~")
		os.Exit(1)
		return
	} // test run failed

	fmt.Println("~~~ Test run SUCCESS ~~~")
	os.Exit(0)
}

// NewConsoleReporter returns new instance of console reporter
func NewConsoleReporter() Reporter {
	return &ConsoleReporter{}
}

// JUnitXMLReporter produces separate xml file for each test sute
type JUnitXMLReporter struct {
	// output directory
	OutPath string

	// current suite
	// when suite is being changed, flush previous one
	suite *suite
}

type suite struct {
	XMLName     string `xml:"testsuite"`
	ID          int    `xml:"id,attr"`
	Name        string `xml:"name,attr"`
	PackageName string `xml:"package,attr"`
	TimeStamp   string `xml:"timestamp,attr"`
	Time        uint16 `xml:"time,attr"`
	HostName    string `xml:"hostname,attr"`

	Tests    int `xml:"tests,attr"`
	Failures int `xml:"failures,attr"`
	Errors   int `xml:"errors,attr"`

	Properties properties `xml:"properties"`
	Cases      []tc       `xml:"testcase"`

	SystemOut string `xml:"system-out"`
	SystemErr string `xml:"system-err"`
}

type properties struct {
}

type tc struct {
	Name      string   `xml:"name,attr"`
	ClassName string   `xml:"classname,attr"`
	Time      uint16   `xml:"time,attr"`
	Failure   *failure `xml:"failure,omitempty"`
}

type failure struct {
	// not clear what type is but it's required
	Type    string `xml:"type,attr"`
	Message string `xml:"message,attr"`
}

func (r *JUnitXMLReporter) Report(result TestResult) {
	if r.suite == nil {
		r.suite = newSuite(result)
	}

	if r.suite.Name != result.Suite.Name {
		r.flushSuite()
		r.suite = newSuite(result)
	}

	testCase := tc{Name: result.Case.Description}
	if result.Cause != nil {
		testCase.Failure = &failure{Type: result.Cause.Error(), Message: result.Cause.Error()}
		r.suite.Failures = r.suite.Failures + 1
	}
	r.suite.Tests = r.suite.Tests + 1
	r.suite.ID = r.suite.ID + 1
	r.suite.Cases = append(r.suite.Cases, testCase)
}

func (r JUnitXMLReporter) flushSuite() {
	fileName := strings.Replace(r.suite.PackageName, "/", "_", -1) + r.suite.Name + ".xml"
	fp := filepath.Join(r.OutPath, fileName)
	err := os.MkdirAll(r.OutPath, 0777)
	if err != nil {
		panic(err)
	}
	f, err := os.Create(fp)
	if err != nil {
		panic(err)
	}

	data, err := xml.Marshal(r.suite)
	if err != nil {
		panic(err)
	}

	f.Write(data)
}

func newSuite(result TestResult) *suite {
	return &suite{
		ID:          0,
		Name:        result.Suite.Name,
		PackageName: result.Suite.PackageName,
		TimeStamp:   time.Now().UTC().Format("2006-01-02T15:04:05"),
		HostName:    "test",
	}
}

func (r JUnitXMLReporter) Flush() {

}

func NewJUnitReporter(outdir string) Reporter {
	return &JUnitXMLReporter{OutPath: outdir}
}
<|endoftext|>


<commit_before>package beep

import "fmt"

// Resample takes a Streamer which is assumed to stream at the old sample rate and returns a
// Streamer, which streams the data from the original Streamer resampled to the new sample rate.
//
// This is, for example, useful when mixing multiple Streamer with different sample rates, either
// through a beep.Mixer, or through a speaker. Speaker has a constant sample rate. Thus, playing
// Streamer which stream at a different sample rate will lead to a changed speed and pitch of the
// playback.
//
//   sr := beep.SampleRate(48000) speaker.Init(sr, sr.N(time.Second/2))
//   speaker.Play(beep.Resample(3, format.SampleRate, sr, s))
//
// In the example, the original sample rate of the source if format.SampleRate. We want to play it
// at the speaker's native sample rate and thus we need to resample.
//
// The quality argument specifies the quality of the resampling process. Higher quality implies
// worse performance. Values below 1 or above 64 are invalid and Resample will panic. Here's a table
// for deciding which quality to pick.
//
//   quality | use case
//   --------|---------
//   1       | very high performance, on-the-fly resampling, low quality
//   3-4     | good performance, on-the-fly resampling, good quality
//   6       | higher CPU usage, usually not suitable for on-the-fly resampling, very good quality
//   >6      | even higher CPU usage, for offline resampling, very good quality
//
// Sane quality values are usually below 16. Higher values will consume too much CPU, giving
// negligible quality improvements.
//
// Resample propagates errors from s.
func Resample(quality int, old, new SampleRate, s Streamer) Streamer {
	return ResampleRatio(quality, float64(old)/float64(new), s)
}

// ResampleRatio is same as Resample, except it takes the ratio of the old and the new sample rate,
// specifically, the old sample rate divided by the new sample rate. Aside from correcting the
// sample rate, this can be used to change the speed of the audio. For example, resampling at the
// ratio of 2 and playing at the original sample rate will cause doubled speed in playback.
func ResampleRatio(quality int, ratio float64, s Streamer) Streamer {
	if quality < 1 || 64 < quality {
		panic(fmt.Errorf("resample: invalid quality: %d", quality))
	}
	return &resample{
		s:     s,
		ratio: ratio,
		first: true,
		buf1:  make([][2]float64, 512),
		buf2:  make([][2]float64, 512),
		pts:   make([]point, quality*2),
		off:   0,
		pos:   0,
	}
}

type resample struct {
	s          Streamer     // the orignal streamer
	ratio      float64      // old sample rate / new sample rate
	first      bool         // true when Stream was not called before
	buf1, buf2 [][2]float64 // buf1 contains previous buf2, new data goes into buf2, buf1 is because interpolation might require old samples
	pts        []point      // pts is for points used for interpolation
	off        int          // off is the position of the start of buf2 in the original data
	pos        int          // pos is the current position in the resampled data
}

func (r *resample) Stream(samples [][2]float64) (n int, ok bool) {
	if r.first { // if it's the first time, we need to fill buf2 with initial data, buf1 remains zeroed
		sn, _ := r.s.Stream(r.buf2)
		r.buf2 = r.buf2[:sn]
		r.first = false
	}
	// we start resampling, sample by sample
	for len(samples) > 0 {
	reload:
		for c := range samples[0] {
			// calculate the current position in the original data
			j := float64(r.pos) * r.ratio

			// find quality*2 closest samples to j and translate them to points for interpolation
			for pi := 0; pi < len(r.pts); pi++ {
				// calculate the index of one of the closest samples
				k := int(j) + pi - len(r.pts)/2 + 1

				var y float64
				switch {
				// the sample is in buf1
				case k < r.off:
					y = r.buf1[len(r.buf1)+k-r.off][c]
				// the sample is in buf2
				case k < r.off+len(r.buf2):
					y = r.buf2[k-r.off][c]
				// the sample is beyond buf2, so we need to load new data
				case k >= r.off+len(r.buf2):
					// we load into buf1
					sn, _ := r.s.Stream(r.buf1)
					// this condition happens when the original Streamer got
					// drained and j is after the end of the
					// original data
					if int(j) >= r.off+len(r.buf2)+sn {
						return n, n > 0
					}
					// this condition happens when the original Streamer got
					// drained and this one of the closest samples is after the
					// end of the original data
					if k >= r.off+len(r.buf2)+sn {
						y = 0
						break
					}
					// otherwise everything is fine, we swap buffers and start
					// calculating the sample again
					r.off += len(r.buf2)
					r.buf1 = r.buf1[:sn]
					r.buf1, r.buf2 = r.buf2, r.buf1
					goto reload
				}

				r.pts[pi] = point{float64(k), y}
			}

			// calculate the resampled sample using polynomial interpolation from the
			// quality*2 closest samples
			samples[0][c] = lagrange(r.pts, j)
		}
		samples = samples[1:]
		n++
		r.pos++
	}
	return n, true
}

func (r *resample) Err() error {
	return r.s.Err()
}

// lagrange calculates the value at x of a polynomial of order len(pts)+1 which goes through all
// points in pts
func lagrange(pts []point, x float64) (y float64) {
	y = 0.0
	for j := range pts {
		l := 1.0
		for m := range pts {
			if j == m {
				continue
			}
			l *= (x - pts[m].X) / (pts[j].X - pts[m].X)
		}
		y += pts[j].Y * l
	}
	return y
}

type point struct {
	X, Y float64
}
<commit_msg>minor change<commit_after>package beep

import "fmt"

// Resample takes a Streamer which is assumed to stream at the old sample rate and returns a
// Streamer, which streams the data from the original Streamer resampled to the new sample rate.
//
// This is, for example, useful when mixing multiple Streamer with different sample rates, either
// through a beep.Mixer, or through a speaker. Speaker has a constant sample rate. Thus, playing
// Streamer which stream at a different sample rate will lead to a changed speed and pitch of the
// playback.
//
//   sr := beep.SampleRate(48000) speaker.Init(sr, sr.N(time.Second/2))
//   speaker.Play(beep.Resample(3, format.SampleRate, sr, s))
//
// In the example, the original sample rate of the source if format.SampleRate. We want to play it
// at the speaker's native sample rate and thus we need to resample.
//
// The quality argument specifies the quality of the resampling process. Higher quality implies
// worse performance. Values below 1 or above 64 are invalid and Resample will panic. Here's a table
// for deciding which quality to pick.
//
//   quality | use case
//   --------|---------
//   1       | very high performance, on-the-fly resampling, low quality
//   3-4     | good performance, on-the-fly resampling, good quality
//   6       | higher CPU usage, usually not suitable for on-the-fly resampling, very good quality
//   >6      | even higher CPU usage, for offline resampling, very good quality
//
// Sane quality values are usually below 16. Higher values will consume too much CPU, giving
// negligible quality improvements.
//
// Resample propagates errors from s.
func Resample(quality int, old, new SampleRate, s Streamer) Streamer {
	return ResampleRatio(quality, float64(old)/float64(new), s)
}

// ResampleRatio is same as Resample, except it takes the ratio of the old and the new sample rate,
// specifically, the old sample rate divided by the new sample rate. Aside from correcting the
// sample rate, this can be used to change the speed of the audio. For example, resampling at the
// ratio of 2 and playing at the original sample rate will cause doubled speed in playback.
func ResampleRatio(quality int, ratio float64, s Streamer) Streamer {
	if quality < 1 || 64 < quality {
		panic(fmt.Errorf("resample: invalid quality: %d", quality))
	}
	return &resample{
		s:     s,
		ratio: ratio,
		first: true,
		buf1:  make([][2]float64, 512),
		buf2:  make([][2]float64, 512),
		pts:   make([]point, quality*2),
		off:   0,
		pos:   0,
	}
}

type resample struct {
	s          Streamer     // the orignal streamer
	ratio      float64      // old sample rate / new sample rate
	first      bool         // true when Stream was not called before
	buf1, buf2 [][2]float64 // buf1 contains previous buf2, new data goes into buf2, buf1 is because interpolation might require old samples
	pts        []point      // pts is for points used for interpolation
	off        int          // off is the position of the start of buf2 in the original data
	pos        int          // pos is the current position in the resampled data
}

func (r *resample) Stream(samples [][2]float64) (n int, ok bool) {
	if r.first { // if it's the first time, we need to fill buf2 with initial data, buf1 remains zeroed
		sn, _ := r.s.Stream(r.buf2)
		r.buf2 = r.buf2[:sn]
		r.first = false
	}
	// we start resampling, sample by sample
	for len(samples) > 0 {
	again:
		for c := range samples[0] {
			// calculate the current position in the original data
			j := float64(r.pos) * r.ratio

			// find quality*2 closest samples to j and translate them to points for interpolation
			for pi := 0; pi < len(r.pts); pi++ {
				// calculate the index of one of the closest samples
				k := int(j) + pi - len(r.pts)/2 + 1

				var y float64
				switch {
				// the sample is in buf1
				case k < r.off:
					y = r.buf1[len(r.buf1)+k-r.off][c]
				// the sample is in buf2
				case k < r.off+len(r.buf2):
					y = r.buf2[k-r.off][c]
				// the sample is beyond buf2, so we need to load new data
				case k >= r.off+len(r.buf2):
					// we load into buf1
					sn, _ := r.s.Stream(r.buf1)
					// this condition happens when the original Streamer got
					// drained and j is after the end of the
					// original data
					if int(j) >= r.off+len(r.buf2)+sn {
						return n, n > 0
					}
					// this condition happens when the original Streamer got
					// drained and this one of the closest samples is after the
					// end of the original data
					if k >= r.off+len(r.buf2)+sn {
						y = 0
						break
					}
					// otherwise everything is fine, we swap buffers and start
					// calculating the sample again
					r.off += len(r.buf2)
					r.buf1 = r.buf1[:sn]
					r.buf1, r.buf2 = r.buf2, r.buf1
					goto again
				}

				r.pts[pi] = point{float64(k), y}
			}

			// calculate the resampled sample using polynomial interpolation from the
			// quality*2 closest samples
			samples[0][c] = lagrange(r.pts, j)
		}
		samples = samples[1:]
		n++
		r.pos++
	}
	return n, true
}

func (r *resample) Err() error {
	return r.s.Err()
}

// lagrange calculates the value at x of a polynomial of order len(pts)+1 which goes through all
// points in pts
func lagrange(pts []point, x float64) (y float64) {
	y = 0.0
	for j := range pts {
		l := 1.0
		for m := range pts {
			if j == m {
				continue
			}
			l *= (x - pts[m].X) / (pts[j].X - pts[m].X)
		}
		y += pts[j].Y * l
	}
	return y
}

type point struct {
	X, Y float64
}
<|endoftext|>


<commit_before>// deepcopy deep copies maps, slices, etc. A standard copy will copy the
// pointers: deep copy copies the values pointed to.
package deepcopy

import (
	"reflect"
)

// deepCopyInterfaceToSliceString takes an interface that is a slice of strings
// and returns a deep copy of it as a slice of strings. An error is returned if
// the interface is not a slice of strings
func deepCopyInterfaceToSliceString(v interface{}) []string {
	if v == nil {
		return nil
	}
	var sl []string

	switch reflect.TypeOf(v).Kind() {
	case reflect.Slice:
		s := reflect.ValueOf(v)
		sLen := s.Len()

		for i := 0; i < sLen; i++ {
			sl = append(sl, s.Index(i).Interface().(string))
		}

	default:
		return nil
	}
	return sl
}

// deepCopyMapStringInterface makes a deep copy of a map[string]interface{} and
// returns the copy of the map[string]interface{}
//
// notes: This assumes that the interface{} is a []string. Adjust as needed.
func deepCopyMapStringInterface(m map[string]interface{}) map[string]interface{} {
	c := map[string]interface{}{}
	var tmp  []string
	for k, v := range m {
		switch reflect.TypeOf(v).Kind() {
		case reflect.Slice:
			tmp = deepCopyInterfaceToSliceString(v)
		}
		c[k] = tmp
	}

	return c
}

<commit_msg>updated function names<commit_after>// deepcopy deep copies maps, slices, etc. A standard copy will copy the
// pointers: deep copy copies the values pointed to.
package deepcopy

import (
	"reflect"
)

// InterfaceToSliceString takes an interface that is a slice of strings
// and returns a deep copy of it as a slice of strings. An error is returned if
// the interface is not a slice of strings
func InterfaceToSliceString(v interface{}) []string {
	if v == nil {
		return nil
	}
	var sl []string

	switch reflect.TypeOf(v).Kind() {
	case reflect.Slice:
		s := reflect.ValueOf(v)
		sLen := s.Len()

		for i := 0; i < sLen; i++ {
			sl = append(sl, s.Index(i).Interface().(string))
		}

	default:
		return nil
	}
	return sl
}

// MapStringInterface makes a deep copy of a map[string]interface{} and
// returns the copy of the map[string]interface{}
//
// notes: This assumes that the interface{} is a []string. Adjust as needed.
func MapStringInterface(m map[string]interface{}) map[string]interface{} {
	c := map[string]interface{}{}
	var tmp  []string
	for k, v := range m {
		switch reflect.TypeOf(v).Kind() {
		case reflect.Slice:
			tmp = deepCopyInterfaceToSliceString(v)
		}
		c[k] = tmp
	}

	return c
}

<|endoftext|>


<commit_before>package typhon

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/golang/protobuf/proto"
	"github.com/monzo/terrors"
)

// A Response is Typhon's wrapper around http.Response, used by both clients and servers.
//
// Note that Typhon makes no guarantees that a Response is safe to access or mutate concurrently. If a single Response
// object is to be used by multiple goroutines concurrently, callers must make sure to properly synchronise accesses.
type Response struct {
	*http.Response
	Error    error
	Request  *Request // The Request that we are responding to
	hijacked bool
}

// Encode serialises the passed object into the body (and sets appropriate headers).
func (r *Response) Encode(v interface{}) {
	if r.Response == nil {
		r.Response = newHTTPResponse(Request{}, http.StatusOK)
	}

	// If we were given an io.ReadCloser or an io.Reader (that is not also
	// a json.Marshaler or proto.Message), use it directly
	switch v := v.(type) {
	case proto.Message, json.Marshaler:
	case io.ReadCloser:
		r.Body = v
		r.ContentLength = -1
		return
	case io.Reader:
		r.Body = ioutil.NopCloser(v)
		r.ContentLength = -1
		return
	}

	// If our request indicates protobuf support and we have a protobuf message
	// then prefer to encode it as a protobuf response body
	acceptsProtobuf := r.Request != nil && strings.Contains(r.Request.Header.Get("Accept"), "application/protobuf")
	if m, ok := v.(proto.Message); ok && acceptsProtobuf {
		r.encodeAsProtobuf(m)
		return
	}

	if err := json.NewEncoder(r).Encode(v); err != nil {
		r.Error = terrors.Wrap(err, nil)
		return
	}
	r.Header.Set("Content-Type", "application/json")
}

func (r *Response) encodeAsProtobuf(m proto.Message) {
	b, err := proto.Marshal(m)
	if err != nil {
		r.Error = terrors.Wrap(err, nil)
		return
	}

	n, err := r.Write(b)
	r.Error = terrors.Wrap(err, nil)
	r.Header.Set("Content-Type", "application/protobuf")
	r.ContentLength = int64(n)
}

// WrapDownstreamErrors is a context key that can be used to enable
// wrapping of downstream response errors on a per-request basis.
//
// This is implemented as a context key to allow us to migrate individual
// services from the old behaviour to the new behaviour without adding a
// dependency on config to Typhon.
type WrapDownstreamErrors struct{}

// Decode de-serialises the body into the passed object.
func (r *Response) Decode(v interface{}) error {
	if r.Error != nil {
		if r.Request != nil && r.Request.Context != nil {
			if s, ok := r.Request.Context.Value(WrapDownstreamErrors{}).(string); ok && s != "" {
				return terrors.NewInternalWithCause(r.Error, "Downstream request error", nil, "downstream")
			}
		}

		return r.Error
	}

	if r.Response == nil {
		r.Error = terrors.InternalService("", "Response has no body", nil)
		return r.Error
	}

	var b []byte
	b, err := r.BodyBytes(true)
	if err != nil {
		r.Error = terrors.WrapWithCode(err, nil, terrors.ErrBadResponse)
		return r.Error
	}

	switch r.Header.Get("Content-Type") {
	case "application/octet-stream", "application/x-google-protobuf", "application/protobuf":
		m, ok := v.(proto.Message)
		if !ok {
			return terrors.InternalService("invalid_type", "could not decode proto message", nil)
		}
		err = proto.Unmarshal(b, m)
	default:
		err = json.Unmarshal(b, v)
	}

	if err != nil {
		r.Error = err
	}
	return err
}

// Write writes the passed bytes to the response's body.
func (r *Response) Write(b []byte) (n int, err error) {
	if r.Response == nil {
		r.Response = newHTTPResponse(Request{}, http.StatusOK)
	}
	switch rc := r.Body.(type) {
	// In the "regular" case, the response body will be a bufCloser; we can write
	case io.Writer:
		n, err = rc.Write(b)
		if err != nil {
			return n, err
		}
	// If a caller manually sets Response.Body, then we may not be able to write to it. In that case, we need to be
	// cleverer.
	default:
		buf := &bufCloser{}
		if rc != nil {
			if _, err := io.Copy(buf, rc); err != nil {
				// This can be quite bad; we have consumed (and possibly lost) some of the original body
				return 0, err
			}
			// rc will never again be accessible: once it's copied it must be closed
			rc.Close()
		}
		r.Body = buf
		n, err = buf.Write(b)
		if err != nil {
			return n, err
		}
	}

	if r.ContentLength >= 0 {
		r.ContentLength += int64(n)
		// If this write pushed the content length above the chunking threshold,
		// set to -1 (unknown) to trigger chunked encoding
		if r.ContentLength >= chunkThreshold {
			r.ContentLength = -1
		}
	}
	return n, nil
}

// BodyBytes fully reads the response body and returns the bytes read. If consume is false, the body is copied into a
// new buffer such that it may be read again.
func (r *Response) BodyBytes(consume bool) ([]byte, error) {
	if consume {
		defer r.Body.Close()
		return ioutil.ReadAll(r.Body)
	}

	switch rc := r.Body.(type) {
	case *bufCloser:
		return rc.Bytes(), nil

	default:
		buf := &bufCloser{}
		r.Body = buf
		rdr := io.TeeReader(rc, buf)
		// rc will never again be accessible: once it's copied it must be closed
		defer rc.Close()
		return ioutil.ReadAll(rdr)
	}
}

// Writer returns a ResponseWriter which can be used to populate the response.
//
// This is useful when you want to use another HTTP library that is used to wrapping net/http directly. For example,
// it allows a Typhon Service to use a http.Handler internally.
func (r *Response) Writer() ResponseWriter {
	if r.Request != nil && r.Request.hijacker != nil {
		return hijackerRw{
			responseWriterWrapper: responseWriterWrapper{
				r: r},
			Hijacker: r.Request.hijacker}
	}
	return responseWriterWrapper{
		r: r}
}

func (r Response) String() string {
	b := new(bytes.Buffer)
	fmt.Fprint(b, "Response(")
	if r.Response != nil {
		fmt.Fprintf(b, "%d", r.StatusCode)
	} else {
		fmt.Fprint(b, "???")
	}
	if r.Error != nil {
		fmt.Fprintf(b, ", error: %v", r.Error)
	}
	fmt.Fprint(b, ")")
	return b.String()
}

func newHTTPResponse(req Request, statusCode int) *http.Response {
	return &http.Response{
		StatusCode:    statusCode,
		Proto:         req.Proto,
		ProtoMajor:    req.ProtoMajor,
		ProtoMinor:    req.ProtoMinor,
		ContentLength: 0,
		Header:        make(http.Header, 5),
		Body:          &bufCloser{}}
}

// NewResponse constructs a Response with status code 200.
func NewResponse(req Request) Response {
	return NewResponseWithCode(req, http.StatusOK)
}

// NewResponseWithCode constructs a Response with the given status code.
func NewResponseWithCode(req Request, statusCode int) Response {
	return Response{
		Request:  &req,
		Error:    nil,
		Response: newHTTPResponse(req, statusCode)}
}
<commit_msg>Export the EncodeAsProtobuf on typhon.Response for easier testing<commit_after>package typhon

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/golang/protobuf/proto"
	"github.com/monzo/terrors"
)

// A Response is Typhon's wrapper around http.Response, used by both clients and servers.
//
// Note that Typhon makes no guarantees that a Response is safe to access or mutate concurrently. If a single Response
// object is to be used by multiple goroutines concurrently, callers must make sure to properly synchronise accesses.
type Response struct {
	*http.Response
	Error    error
	Request  *Request // The Request that we are responding to
	hijacked bool
}

// Encode serialises the passed object into the body (and sets appropriate headers).
func (r *Response) Encode(v interface{}) {
	if r.Response == nil {
		r.Response = newHTTPResponse(Request{}, http.StatusOK)
	}

	// If we were given an io.ReadCloser or an io.Reader (that is not also
	// a json.Marshaler or proto.Message), use it directly
	switch v := v.(type) {
	case proto.Message, json.Marshaler:
	case io.ReadCloser:
		r.Body = v
		r.ContentLength = -1
		return
	case io.Reader:
		r.Body = ioutil.NopCloser(v)
		r.ContentLength = -1
		return
	}

	// If our request indicates protobuf support and we have a protobuf message
	// then prefer to encode it as a protobuf response body
	acceptsProtobuf := r.Request != nil && strings.Contains(r.Request.Header.Get("Accept"), "application/protobuf")
	if m, ok := v.(proto.Message); ok && acceptsProtobuf {
		r.EncodeAsProtobuf(m)
		return
	}

	if err := json.NewEncoder(r).Encode(v); err != nil {
		r.Error = terrors.Wrap(err, nil)
		return
	}
	r.Header.Set("Content-Type", "application/json")
}

// EncodeAsProtobuf serialises the passed object as protobuf into the body
func (r *Response) EncodeAsProtobuf(m proto.Message) {
	b, err := proto.Marshal(m)
	if err != nil {
		r.Error = terrors.Wrap(err, nil)
		return
	}

	n, err := r.Write(b)
	r.Error = terrors.Wrap(err, nil)
	r.Header.Set("Content-Type", "application/protobuf")
	r.ContentLength = int64(n)
}

// WrapDownstreamErrors is a context key that can be used to enable
// wrapping of downstream response errors on a per-request basis.
//
// This is implemented as a context key to allow us to migrate individual
// services from the old behaviour to the new behaviour without adding a
// dependency on config to Typhon.
type WrapDownstreamErrors struct{}

// Decode de-serialises the body into the passed object.
func (r *Response) Decode(v interface{}) error {
	if r.Error != nil {
		if r.Request != nil && r.Request.Context != nil {
			if s, ok := r.Request.Context.Value(WrapDownstreamErrors{}).(string); ok && s != "" {
				return terrors.NewInternalWithCause(r.Error, "Downstream request error", nil, "downstream")
			}
		}

		return r.Error
	}

	if r.Response == nil {
		r.Error = terrors.InternalService("", "Response has no body", nil)
		return r.Error
	}

	var b []byte
	b, err := r.BodyBytes(true)
	if err != nil {
		r.Error = terrors.WrapWithCode(err, nil, terrors.ErrBadResponse)
		return r.Error
	}

	switch r.Header.Get("Content-Type") {
	case "application/octet-stream", "application/x-google-protobuf", "application/protobuf":
		m, ok := v.(proto.Message)
		if !ok {
			return terrors.InternalService("invalid_type", "could not decode proto message", nil)
		}
		err = proto.Unmarshal(b, m)
	default:
		err = json.Unmarshal(b, v)
	}

	if err != nil {
		r.Error = err
	}
	return err
}

// Write writes the passed bytes to the response's body.
func (r *Response) Write(b []byte) (n int, err error) {
	if r.Response == nil {
		r.Response = newHTTPResponse(Request{}, http.StatusOK)
	}
	switch rc := r.Body.(type) {
	// In the "regular" case, the response body will be a bufCloser; we can write
	case io.Writer:
		n, err = rc.Write(b)
		if err != nil {
			return n, err
		}
	// If a caller manually sets Response.Body, then we may not be able to write to it. In that case, we need to be
	// cleverer.
	default:
		buf := &bufCloser{}
		if rc != nil {
			if _, err := io.Copy(buf, rc); err != nil {
				// This can be quite bad; we have consumed (and possibly lost) some of the original body
				return 0, err
			}
			// rc will never again be accessible: once it's copied it must be closed
			rc.Close()
		}
		r.Body = buf
		n, err = buf.Write(b)
		if err != nil {
			return n, err
		}
	}

	if r.ContentLength >= 0 {
		r.ContentLength += int64(n)
		// If this write pushed the content length above the chunking threshold,
		// set to -1 (unknown) to trigger chunked encoding
		if r.ContentLength >= chunkThreshold {
			r.ContentLength = -1
		}
	}
	return n, nil
}

// BodyBytes fully reads the response body and returns the bytes read. If consume is false, the body is copied into a
// new buffer such that it may be read again.
func (r *Response) BodyBytes(consume bool) ([]byte, error) {
	if consume {
		defer r.Body.Close()
		return ioutil.ReadAll(r.Body)
	}

	switch rc := r.Body.(type) {
	case *bufCloser:
		return rc.Bytes(), nil

	default:
		buf := &bufCloser{}
		r.Body = buf
		rdr := io.TeeReader(rc, buf)
		// rc will never again be accessible: once it's copied it must be closed
		defer rc.Close()
		return ioutil.ReadAll(rdr)
	}
}

// Writer returns a ResponseWriter which can be used to populate the response.
//
// This is useful when you want to use another HTTP library that is used to wrapping net/http directly. For example,
// it allows a Typhon Service to use a http.Handler internally.
func (r *Response) Writer() ResponseWriter {
	if r.Request != nil && r.Request.hijacker != nil {
		return hijackerRw{
			responseWriterWrapper: responseWriterWrapper{
				r: r},
			Hijacker: r.Request.hijacker}
	}
	return responseWriterWrapper{
		r: r}
}

func (r Response) String() string {
	b := new(bytes.Buffer)
	fmt.Fprint(b, "Response(")
	if r.Response != nil {
		fmt.Fprintf(b, "%d", r.StatusCode)
	} else {
		fmt.Fprint(b, "???")
	}
	if r.Error != nil {
		fmt.Fprintf(b, ", error: %v", r.Error)
	}
	fmt.Fprint(b, ")")
	return b.String()
}

func newHTTPResponse(req Request, statusCode int) *http.Response {
	return &http.Response{
		StatusCode:    statusCode,
		Proto:         req.Proto,
		ProtoMajor:    req.ProtoMajor,
		ProtoMinor:    req.ProtoMinor,
		ContentLength: 0,
		Header:        make(http.Header, 5),
		Body:          &bufCloser{}}
}

// NewResponse constructs a Response with status code 200.
func NewResponse(req Request) Response {
	return NewResponseWithCode(req, http.StatusOK)
}

// NewResponseWithCode constructs a Response with the given status code.
func NewResponseWithCode(req Request, statusCode int) Response {
	return Response{
		Request:  &req,
		Error:    nil,
		Response: newHTTPResponse(req, statusCode)}
}
<|endoftext|>


<commit_before>// Copyright 2015 Afshin Darian. All rights reserved.
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package forest

import (
	"encoding/json"
	"github.com/ursiform/bear"
	"log"
	"net/http"
	"time"
)

type Response struct {
	app     *App
	Code    int `json:"-"`
	ctx     *bear.Context
	Data    interface{} `json:"data,omitempty"`
	Success bool        `json:"success"`
	Message string      `json:"message,omitempty"`
}

func (res *Response) SetCookie(
	path, key, value string, duration time.Duration) {
	http.SetCookie(res.ctx.ResponseWriter, &http.Cookie{
		Name:     key,
		Value:    value,
		Expires:  time.Now().Add(duration),
		HttpOnly: true,
		MaxAge:   int(duration / time.Second),
		Path:     path,
		Secure:   true})
}

func (res *Response) Write(data interface{}) (bytes int, err error) {
	res.Data = data
	output, _ := json.Marshal(res)
	res.ctx.ResponseWriter.Header().Set("Content-Type", "application/json")
	if 0 < len(res.app.PoweredBy) {
		res.ctx.ResponseWriter.Header().Set("X-Powered-By", res.app.PoweredBy)
	}
	res.ctx.ResponseWriter.WriteHeader(res.Code)
	bytes, err = res.ctx.ResponseWriter.Write(output)
	if !res.app.Debug {
		return
	}
	// First, try the X-Real-IP header from the reverse proxy.
	ip := res.ctx.Request.Header.Get("X-Real-IP")
	// If X-Real-IP does not exist, try the REMOTE_ADDR.
	if ip == "" {
		ip = res.ctx.Request.RemoteAddr
	}
	// If IP is still blank (perhaps in tests), display UnknownIP.
	if ip == "" {
		ip = UnknownIP
	}
	method := res.ctx.Request.Method
	uri := res.ctx.Request.URL.RequestURI()
	proto := res.ctx.Request.Proto
	code := res.Code
	agent := res.ctx.Request.UserAgent()
	if agent == "" {
		agent = UnknownAgent
	}
	sessionID, ok := res.ctx.Get(SessionID).(string)
	if !ok || sessionID == "" {
		sessionID = UnknownSession
	}
	log.Printf("[%s/%s] \"%s %s %s\" %d %d \"%s\"\n",
		ip, sessionID, method, uri, proto, code, bytes, agent)
	return
}
<commit_msg>Add response messages to log output<commit_after>// Copyright 2015 Afshin Darian. All rights reserved.
// Use of this source code is governed by The MIT License
// that can be found in the LICENSE file.

package forest

import (
	"encoding/json"
	"github.com/ursiform/bear"
	"log"
	"net/http"
	"time"
)

type Response struct {
	app     *App
	Code    int `json:"-"`
	ctx     *bear.Context
	Data    interface{} `json:"data,omitempty"`
	Success bool        `json:"success"`
	Message string      `json:"message,omitempty"`
}

func (res *Response) SetCookie(
	path, key, value string, duration time.Duration) {
	http.SetCookie(res.ctx.ResponseWriter, &http.Cookie{
		Name:     key,
		Value:    value,
		Expires:  time.Now().Add(duration),
		HttpOnly: true,
		MaxAge:   int(duration / time.Second),
		Path:     path,
		Secure:   true})
}

func (res *Response) Write(data interface{}) (bytes int, err error) {
	res.Data = data
	output, _ := json.Marshal(res)
	res.ctx.ResponseWriter.Header().Set("Content-Type", "application/json")
	if 0 < len(res.app.PoweredBy) {
		res.ctx.ResponseWriter.Header().Set("X-Powered-By", res.app.PoweredBy)
	}
	res.ctx.ResponseWriter.WriteHeader(res.Code)
	bytes, err = res.ctx.ResponseWriter.Write(output)
	if !res.app.Debug {
		return
	}
	// First, try the X-Real-IP header from the reverse proxy.
	ip := res.ctx.Request.Header.Get("X-Real-IP")
	// If X-Real-IP does not exist, try the REMOTE_ADDR.
	if ip == "" {
		ip = res.ctx.Request.RemoteAddr
	}
	// If IP is still blank (perhaps in tests), display UnknownIP.
	if ip == "" {
		ip = UnknownIP
	}
	method := res.ctx.Request.Method
	uri := res.ctx.Request.URL.RequestURI()
	proto := res.ctx.Request.Proto
	code := res.Code
	agent := res.ctx.Request.UserAgent()
	if agent == "" {
		agent = UnknownAgent
	}
	sessionID, ok := res.ctx.Get(SessionID).(string)
	message := res.Message
	if !ok || sessionID == "" {
		sessionID = UnknownSession
	}
	log.Printf("[%s/%s] \"%s %s %s\" %d %d \"%s\" %s\n",
		ip, sessionID, method, uri, proto, code, bytes, agent, message)
	return
}
<|endoftext|>


<commit_before>package typhon

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

	log "github.com/mondough/slog"
	"github.com/mondough/terrors"
	"golang.org/x/net/context"
)

type Response struct {
	*http.Response
	Error error
	ctx   context.Context
}

// Encode serialises the passed object as JSON into the body (and sets appropriate headers).
func (r *Response) Encode(v interface{}) {
	if err := json.NewEncoder(r).Encode(v); err != nil {
		r.Error = terrors.Wrap(err, nil)
		log.Warn(r.ctx, "Failed to encode response body: %v", err)
		return
	}
	r.Header.Set("Content-Type", "application/json")
}

// Decode de-serialises the JSON body into the passed object.
func (r *Response) Decode(v interface{}) error {
	err := error(nil)
	if r.Response == nil {
		err = terrors.InternalService("", "Response has no body", nil)
	} else {
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			log.Warn(r.ctx, "Failed to decode response body: %v", err)
		}
		err = terrors.WrapWithCode(err, nil, terrors.ErrBadResponse)
	}
	if r.Error == nil {
		r.Error = err
	}
	return err
}

func (r *Response) Write(b []byte) (int, error) {
	switch rc := r.Body.(type) {
	// In the "regular" case, the response body will be a bufCloser; we can write
	case io.Writer:
		return rc.Write(b)
	// If a caller manually sets Response.Body, then we may not be able to write to it. In that case, we need to be
	// cleverer.
	default:
		buf := &bufCloser{}
		if _, err := io.Copy(buf, rc); err != nil {
			// This can be quite bad; we have consumed (and possibly lost) some of the original body
			return 0, err
		}
		r.Body = buf
		return buf.Write(b)
	}
}

func (r *Response) BodyBytes(consume bool) ([]byte, error) {
	if consume {
		return ioutil.ReadAll(r.Body)
	}

	switch rc := r.Body.(type) {
	case *bufCloser:
		return rc.Bytes(), nil
	default:
		rdr := io.Reader(rc)
		buf := &bufCloser{}
		r.Body = buf
		rdr = io.TeeReader(rdr, buf)
		return ioutil.ReadAll(rdr)
	}
}

// Writer returns a ResponseWriter proxy.
func (r *Response) Writer() ResponseWriter {
	return responseWriterWrapper{
		r: r}
}

func newHttpResponse(req Request) *http.Response {
	return &http.Response{
		StatusCode: http.StatusOK, // Seems like a reasonable default
		Proto:      req.Proto,
		ProtoMajor: req.ProtoMajor,
		ProtoMinor: req.ProtoMinor,
		Header:     make(http.Header, 5),
		Body:       &bufCloser{}}
}

// NewResponse constructs a Response
func NewResponse(req Request) Response {
	return Response{
		ctx:      req.Context,
		Error:    nil,
		Response: newHttpResponse(req)}
}
<commit_msg>Fix nil-pointer panic<commit_after>package typhon

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

	log "github.com/mondough/slog"
	"github.com/mondough/terrors"
	"golang.org/x/net/context"
)

type Response struct {
	*http.Response
	Error error
	ctx   context.Context
}

// Encode serialises the passed object as JSON into the body (and sets appropriate headers).
func (r *Response) Encode(v interface{}) {
	if err := json.NewEncoder(r).Encode(v); err != nil {
		r.Error = terrors.Wrap(err, nil)
		log.Warn(r.ctx, "Failed to encode response body: %v", err)
		return
	}
	r.Header.Set("Content-Type", "application/json")
}

// Decode de-serialises the JSON body into the passed object.
func (r *Response) Decode(v interface{}) error {
	err := error(nil)
	if r.Response == nil {
		err = terrors.InternalService("", "Response has no body", nil)
	} else {
		err := json.NewDecoder(r.Body).Decode(v)
		if err != nil {
			log.Warn(r.ctx, "Failed to decode response body: %v", err)
		}
		err = terrors.WrapWithCode(err, nil, terrors.ErrBadResponse)
	}
	if r.Error == nil {
		r.Error = err
	}
	return err
}

func (r *Response) Write(b []byte) (int, error) {
	switch rc := r.Body.(type) {
	// In the "regular" case, the response body will be a bufCloser; we can write
	case io.Writer:
		return rc.Write(b)
	// If a caller manually sets Response.Body, then we may not be able to write to it. In that case, we need to be
	// cleverer.
	default:
		buf := &bufCloser{}
		if rc != nil {
			if _, err := io.Copy(buf, rc); err != nil {
				// This can be quite bad; we have consumed (and possibly lost) some of the original body
				return 0, err
			}
		}
		r.Body = buf
		return buf.Write(b)
	}
}

func (r *Response) BodyBytes(consume bool) ([]byte, error) {
	if consume {
		return ioutil.ReadAll(r.Body)
	}

	switch rc := r.Body.(type) {
	case *bufCloser:
		return rc.Bytes(), nil
	default:
		rdr := io.Reader(rc)
		buf := &bufCloser{}
		r.Body = buf
		rdr = io.TeeReader(rdr, buf)
		return ioutil.ReadAll(rdr)
	}
}

// Writer returns a ResponseWriter proxy.
func (r *Response) Writer() ResponseWriter {
	return responseWriterWrapper{
		r: r}
}

func newHttpResponse(req Request) *http.Response {
	return &http.Response{
		StatusCode: http.StatusOK, // Seems like a reasonable default
		Proto:      req.Proto,
		ProtoMajor: req.ProtoMajor,
		ProtoMinor: req.ProtoMinor,
		Header:     make(http.Header, 5),
		Body:       &bufCloser{}}
}

// NewResponse constructs a Response
func NewResponse(req Request) Response {
	return Response{
		ctx:      req.Context,
		Error:    nil,
		Response: newHttpResponse(req)}
}
<|endoftext|>


<commit_before>package amazing

import (
	"encoding/xml"
	"fmt"
)

const (
	errorFormat = "ErrorCode: %s\nMessage: %s\nRequest:%s"
)

type AmazonItemLookupResponse struct {
	XMLName          xml.Name `xml:"ItemLookupResponse"`
	OperationRequest AmazonOperationRequest
	AmazonItems      AmazonItems `xml:"Items"`
}

type AmazonItemSearchResponse struct {
	XMLName          xml.Name `xml:"ItemSearchResponse"`
	OperationRequest AmazonOperationRequest
	AmazonItems      AmazonItems `xml:"Items"`
}

type AmazonSimilarityLookupResponse struct {
	XMLName          xml.Name `xml:"SimilarityLookupResponse"`
	OperationRequest AmazonOperationRequest
	AmazonItems      AmazonItems `xml:"Items"`
}

type AmazonOperationRequest struct {
	HTTPHeaders           []AmazonOperationRequestHeader   `xml:"HTTPHeaders>Header"`
	Arguments             []AmazonOperationRequestArgument `xml:"Arguments>Argument"`
	RequestId             string
	RequestProcessingTime float64
}

type AmazonOperationRequestHeader struct {
	Name  string `xml:"Name,attr"`
	Value string `xml:"Value,attr"`
}

type AmazonOperationRequestArgument struct {
	Name  string `xml:"Name,attr"`
	Value string `xml:"Value,attr"`
}

type AmazonItems struct {
	Request AmazonRequest
	Items   []AmazonItem `xml:"Item"`
}

type AmazonItem struct {
	ASIN             string
	ParentASIN       string
	DetailPageURL    string
	SalesRank        string
	ItemLinks        []AmazonItemLink `xml:"ItemLinks>ItemLink"`
	SmallImage       AmazonImage
	MediumImage      AmazonImage
	LargeImage       AmazonImage
	ImageSets        []AmazonImageSet `xml:"ImageSets>ImageSet"`
	ItemAttributes   AmazonItemAttributes
	OfferSummary     AmazonItemOfferSummary
	EditorialReviews []AmazonEditorialReview `xml:"EditorialReviews>EditorialReview"`
	BrowseNodes      []AmazonBrowseNode      `xml:"BrowseNodes>BrowseNode"`
}
type AmazonBrowseNode struct {
	BrowseNodeId string              `xml:"BrowseNodeId"`
	Name         string              `xml:"Name"`
	Ancestors    *[]AmazonBrowseNode `xml:"Ancestors>BrowseNode"`
}

type AmazonEditorialReview struct {
	Source  string
	Content string
}

type AmazonItemAtributes AmazonItemAttributes

type AmazonItemAttributes struct {
	Title     string
	Brand     string
	ListPrice AmazonItemPrice
}

type AmazonItemOfferSummary struct {
	LowestUsedPrice        AmazonItemPrice
	LowestNewPrice         AmazonItemPrice
	LowestCollectiblePrice AmazonItemPrice
}

type AmazonItemPrice struct {
	Amount         int64
	CurrencyCode   string
	FormattedPrice string
}

type AmazonItemLink struct {
	Description string
	URL         string
}

type AmazonImageSet struct {
	Category       string `xml:"Category,attr"`
	SwatchImage    AmazonImage
	SmallImage     AmazonImage
	ThumbnailImage AmazonImage
	TinyImage      AmazonImage
	MediumImage    AmazonImage
	LargeImage     AmazonImage
}

type AmazonRequest struct {
	IsValid           bool
	ItemLookupRequest AmazonItemLookupRequest
	Errors            []AmazonError
}

type AmazonItemLookupRequest struct {
	Condition      string
	IdType         string
	ItemId         string
	ResponseGroups []string `xml:"ResponseGroup"`
	VariationPage  string
}

type AmazonItemLookupErrorResponse struct {
	XMLName xml.Name
	AmazonError
}

type AmazonError struct {
	Code      string `xml:"Error>Code"`
	Message   string `xml:"Error>Message"`
	RequestId string
}

type AmazonImage struct {
	URL    string
	Height uint16
	Width  uint16
}

func (a *AmazonError) Error() string {
	return fmt.Sprintf(errorFormat, a.Code, a.Message, a.RequestId)
}
<commit_msg>Changing type for Ancestors field on AmazonBrowseNode struct<commit_after>package amazing

import (
	"encoding/xml"
	"fmt"
)

const (
	errorFormat = "ErrorCode: %s\nMessage: %s\nRequest:%s"
)

type AmazonItemLookupResponse struct {
	XMLName          xml.Name `xml:"ItemLookupResponse"`
	OperationRequest AmazonOperationRequest
	AmazonItems      AmazonItems `xml:"Items"`
}

type AmazonItemSearchResponse struct {
	XMLName          xml.Name `xml:"ItemSearchResponse"`
	OperationRequest AmazonOperationRequest
	AmazonItems      AmazonItems `xml:"Items"`
}

type AmazonSimilarityLookupResponse struct {
	XMLName          xml.Name `xml:"SimilarityLookupResponse"`
	OperationRequest AmazonOperationRequest
	AmazonItems      AmazonItems `xml:"Items"`
}

type AmazonOperationRequest struct {
	HTTPHeaders           []AmazonOperationRequestHeader   `xml:"HTTPHeaders>Header"`
	Arguments             []AmazonOperationRequestArgument `xml:"Arguments>Argument"`
	RequestId             string
	RequestProcessingTime float64
}

type AmazonOperationRequestHeader struct {
	Name  string `xml:"Name,attr"`
	Value string `xml:"Value,attr"`
}

type AmazonOperationRequestArgument struct {
	Name  string `xml:"Name,attr"`
	Value string `xml:"Value,attr"`
}

type AmazonItems struct {
	Request AmazonRequest
	Items   []AmazonItem `xml:"Item"`
}

type AmazonItem struct {
	ASIN             string
	ParentASIN       string
	DetailPageURL    string
	SalesRank        string
	ItemLinks        []AmazonItemLink `xml:"ItemLinks>ItemLink"`
	SmallImage       AmazonImage
	MediumImage      AmazonImage
	LargeImage       AmazonImage
	ImageSets        []AmazonImageSet `xml:"ImageSets>ImageSet"`
	ItemAttributes   AmazonItemAttributes
	OfferSummary     AmazonItemOfferSummary
	EditorialReviews []AmazonEditorialReview `xml:"EditorialReviews>EditorialReview"`
	BrowseNodes      []AmazonBrowseNode      `xml:"BrowseNodes>BrowseNode"`
}

type AmazonBrowseNode struct {
	BrowseNodeId string             `xml:"BrowseNodeId"`
	Name         string             `xml:"Name"`
	Ancestors    []AmazonBrowseNode `xml:"Ancestors>BrowseNode"`
}

type AmazonEditorialReview struct {
	Source  string
	Content string
}

type AmazonItemAtributes AmazonItemAttributes

type AmazonItemAttributes struct {
	Title     string
	Brand     string
	ListPrice AmazonItemPrice
}

type AmazonItemOfferSummary struct {
	LowestUsedPrice        AmazonItemPrice
	LowestNewPrice         AmazonItemPrice
	LowestCollectiblePrice AmazonItemPrice
}

type AmazonItemPrice struct {
	Amount         int64
	CurrencyCode   string
	FormattedPrice string
}

type AmazonItemLink struct {
	Description string
	URL         string
}

type AmazonImageSet struct {
	Category       string `xml:"Category,attr"`
	SwatchImage    AmazonImage
	SmallImage     AmazonImage
	ThumbnailImage AmazonImage
	TinyImage      AmazonImage
	MediumImage    AmazonImage
	LargeImage     AmazonImage
}

type AmazonRequest struct {
	IsValid           bool
	ItemLookupRequest AmazonItemLookupRequest
	Errors            []AmazonError
}

type AmazonItemLookupRequest struct {
	Condition      string
	IdType         string
	ItemId         string
	ResponseGroups []string `xml:"ResponseGroup"`
	VariationPage  string
}

type AmazonItemLookupErrorResponse struct {
	XMLName xml.Name
	AmazonError
}

type AmazonError struct {
	Code      string `xml:"Error>Code"`
	Message   string `xml:"Error>Message"`
	RequestId string
}

type AmazonImage struct {
	URL    string
	Height uint16
	Width  uint16
}

func (a *AmazonError) Error() string {
	return fmt.Sprintf(errorFormat, a.Code, a.Message, a.RequestId)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	//"fmt"
)

var cmdDescribe = &Command{
	Usage: "describe (metadata|sobject) [-n=<name> -json]",
	Short: "Describe the object or list of available objects",
	Long: `
  -n, -name       # name of specific metadata to retrieve
  -json           # output in JSON format

  Examples

  force describe metadata -n=CustomObject
  force describe sobject -n=Account
  force describe metata
  force describe sobject
  `,
}

var (
	jsonout  bool
	metaItem string
)

func init() {
	cmdDescribe.Flag.StringVar(&metaItem, "name", "", "name of metadata")
	cmdDescribe.Flag.StringVar(&metaItem, "n", "", "name of metadata")
	cmdDescribe.Flag.StringVar(&metadataType, "t", "", "Type of metadata to describe")
	cmdDescribe.Flag.StringVar(&metadataType, "type", "", "Type of metadata to describe")
	cmdDescribe.Flag.BoolVar(&jsonout, "j", false, "Unpage any static resources")
	cmdDescribe.Flag.BoolVar(&jsonout, "json", false, "Unpage any static resources")
	cmdDescribe.Run = runDescribe
}

func runDescribe(cmd *Command, args []string) {
	if len(metadataType) == 0 {
		ErrorAndExit("You must specify metadata or sobject for description\nexample: force describe -t metadata")
	}
	if metadataType != "metadata" && metadataType != "sobject" {
		ErrorAndExit("Only metadata and sobject can be described")
	}

	force, _ := ActiveForce()

	if metadataType == "metadata" {
		if len(metaItem) == 0 {
			// List all metadata
			describe, err := force.Metadata.DescribeMetadata()
			if err != nil {
				ErrorAndExit(err.Error())
			}
			if jsonout {
				DisplayMetadataListJson(describe.MetadataObjects)
			} else {
				DisplayMetadataList(describe.MetadataObjects)
			}
		} else {
			// List all metdata object of metaItem type
			body, err := force.Metadata.ListMetadata(metaItem)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			var res struct {
				Response ListMetadataResponse `xml:"Body>listMetadataResponse"`
			}
			if err = xml.Unmarshal(body, &res); err != nil {
				ErrorAndExit(err.Error())
			}
			if jsonout {
				DisplayListMetadataResponseJson(res.Response)
			} else {
				DisplayListMetadataResponse(res.Response)
			}
		}
	} else {
		if len(metaItem) == 0 {
			// list all sobject
			if jsonout {
				l := getSobjectList(make([]string, 0))
				DisplayForceSobjectsJson(l)
			} else {
				runSobjectList(make([]string, 0))
			}
		} else {
			// describe sobject
			desc, err := force.DescribeSObject(metaItem)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			DisplayForceSobjectDescribe(desc)
		}
	}
}
<commit_msg>Update describe help text<commit_after>package main

import (
	"encoding/xml"
	//"fmt"
)

var cmdDescribe = &Command{
	Usage: "describe (metadata|sobject) [-n=<name> -json]",
	Short: "Describe the object or list of available objects",
	Long: `
  -n, -name       # name of specific metadata to retrieve
  -json           # output in JSON format

  Examples

  force describe -t=metadata -n=CustomObject
  force describe -t=sobject -n=Account
  `,
}

var (
	jsonout  bool
	metaItem string
)

func init() {
	cmdDescribe.Flag.StringVar(&metaItem, "name", "", "name of metadata")
	cmdDescribe.Flag.StringVar(&metaItem, "n", "", "name of metadata")
	cmdDescribe.Flag.StringVar(&metadataType, "t", "", "Type of metadata to describe")
	cmdDescribe.Flag.StringVar(&metadataType, "type", "", "Type of metadata to describe")
	cmdDescribe.Flag.BoolVar(&jsonout, "j", false, "Unpage any static resources")
	cmdDescribe.Flag.BoolVar(&jsonout, "json", false, "Unpage any static resources")
	cmdDescribe.Run = runDescribe
}

func runDescribe(cmd *Command, args []string) {
	if len(metadataType) == 0 {
		ErrorAndExit("You must specify metadata or sobject for description\nexample: force describe -t metadata")
	}
	if metadataType != "metadata" && metadataType != "sobject" {
		ErrorAndExit("Only metadata and sobject can be described")
	}

	force, _ := ActiveForce()

	if metadataType == "metadata" {
		if len(metaItem) == 0 {
			// List all metadata
			describe, err := force.Metadata.DescribeMetadata()
			if err != nil {
				ErrorAndExit(err.Error())
			}
			if jsonout {
				DisplayMetadataListJson(describe.MetadataObjects)
			} else {
				DisplayMetadataList(describe.MetadataObjects)
			}
		} else {
			// List all metdata object of metaItem type
			body, err := force.Metadata.ListMetadata(metaItem)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			var res struct {
				Response ListMetadataResponse `xml:"Body>listMetadataResponse"`
			}
			if err = xml.Unmarshal(body, &res); err != nil {
				ErrorAndExit(err.Error())
			}
			if jsonout {
				DisplayListMetadataResponseJson(res.Response)
			} else {
				DisplayListMetadataResponse(res.Response)
			}
		}
	} else {
		if len(metaItem) == 0 {
			// list all sobject
			if jsonout {
				l := getSobjectList(make([]string, 0))
				DisplayForceSobjectsJson(l)
			} else {
				runSobjectList(make([]string, 0))
			}
		} else {
			// describe sobject
			desc, err := force.DescribeSObject(metaItem)
			if err != nil {
				ErrorAndExit(err.Error())
			}
			DisplayForceSobjectDescribe(desc)
		}
	}
}
<|endoftext|>


<commit_before>package libfss

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/binary"
	//"fmt"
)

type Fss struct {
	// store keys used in fixedBlocks so that they can be sent to the server
	PrfKeys     [][]byte
	FixedBlocks []cipher.Block
	N           uint
	NumBits     uint   // number of bits in domain
	Temp        []byte // temporary slices so that we only need to allocate memory at the beginning
	Out         []byte
}

type FssKey struct {
	SInit   []byte
	TInit   byte
	CW      [][]byte // there are n
	FinalCW int
}

const initPRFLen int = 4

// initialize client with this function
// numBits represents the input domain for the function, i.e. the number
// of bits to check
func ClientInitialize(numBits uint) *Fss {
	f := new(Fss)
	f.NumBits = numBits
	f.PrfKeys = make([][]byte, initPRFLen)
	// Create fixed AES blocks
	f.FixedBlocks = make([]cipher.Block, initPRFLen)
	for i := 0; i < initPRFLen; i++ {
		f.PrfKeys[i] = make([]byte, aes.BlockSize)
		rand.Read(f.PrfKeys[i])
		//fmt.Println("client")
		//fmt.Println(f.PrfKeys[i])
		block, err := aes.NewCipher(f.PrfKeys[i])
		if err != nil {
			panic(err.Error())
		}
		f.FixedBlocks[i] = block
	}
	// Check if int is 32 or 64 bit
	var x uint64 = 1 << 32
	if uint(x) == 0 {
		f.N = 32
	} else {
		f.N = 64
	}
	f.Temp = make([]byte, aes.BlockSize)
	f.Out = make([]byte, aes.BlockSize*initPRFLen)
	return f
}

// upon receiving query from server, initialize server with
// this function. The server, unlike the client
// receives prfKeys, so it doesn't need to pick random ones
func ServerInitialize(prfKeys [][]byte, numBits uint) *Fss {
	f := new(Fss)
	f.NumBits = numBits
	f.PrfKeys = make([][]byte, initPRFLen)
	f.FixedBlocks = make([]cipher.Block, initPRFLen)
	for i := range prfKeys {
		f.PrfKeys[i] = make([]byte, aes.BlockSize)
		copy(f.PrfKeys[i], prfKeys[i])
		//fmt.Println("server")
		//fmt.Println(f.PrfKeys[i])
		block, err := aes.NewCipher(f.PrfKeys[i])
		if err != nil {
			panic(err.Error())
		}
		f.FixedBlocks[i] = block
	}
	// Check if int is 32 or 64 bit
	var x uint64 = 1 << 32
	if uint(x) == 0 {
		f.N = 32
	} else {
		f.N = 64
	}
	f.Temp = make([]byte, aes.BlockSize)
	f.Out = make([]byte, aes.BlockSize*initPRFLen)

	return f
}

// Generate Keys for point functions
func (f Fss) GenerateTreePF(a, b uint) []FssKey {
	fssKeys := make([]FssKey, 2)
	// Set up initial values
	tempRand1 := make([]byte, aes.BlockSize+1)
	rand.Read(tempRand1)
	fssKeys[0].SInit = tempRand1[:aes.BlockSize]
	fssKeys[0].TInit = tempRand1[aes.BlockSize] % 2
	fssKeys[1].SInit = make([]byte, aes.BlockSize)
	rand.Read(fssKeys[1].SInit)
	fssKeys[1].TInit = fssKeys[0].TInit ^ 1

	// Set current seed being used
	sCurr0 := make([]byte, aes.BlockSize)
	sCurr1 := make([]byte, aes.BlockSize)
	copy(sCurr0, fssKeys[0].SInit)
	copy(sCurr1, fssKeys[1].SInit)
	tCurr0 := fssKeys[0].TInit
	tCurr1 := fssKeys[1].TInit

	// Initialize correction words in FSS keys
	fssKeys[0].CW = make([][]byte, f.NumBits)
	fssKeys[1].CW = make([][]byte, f.NumBits)
	for i := uint(0); i < f.NumBits; i++ {
		// make AES block size + 2 bytes
		fssKeys[0].CW[i] = make([]byte, aes.BlockSize+2)
		fssKeys[1].CW[i] = make([]byte, aes.BlockSize+2)
	}

	leftStart := 0
	rightStart := aes.BlockSize + 1
	for i := uint(0); i < f.NumBits; i++ {
		// "expand" seed into two seeds + 2 bits
		prf(sCurr0, f.FixedBlocks, 3, f.Temp, f.Out)
		prfOut0 := make([]byte, aes.BlockSize*3)
		copy(prfOut0, f.Out[:aes.BlockSize*3])
		prf(sCurr1, f.FixedBlocks, 3, f.Temp, f.Out)
		prfOut1 := make([]byte, aes.BlockSize*3)
		copy(prfOut1, f.Out[:aes.BlockSize*3])

		//fmt.Println(i, sCurr0)
		//fmt.Println(i, sCurr1)
		// Parse out "t" bits
		t0Left := prfOut0[aes.BlockSize] % 2
		t0Right := prfOut0[(aes.BlockSize*2)+1] % 2
		t1Left := prfOut1[aes.BlockSize] % 2
		t1Right := prfOut1[(aes.BlockSize*2)+1] % 2
		// Find bit in a
		aBit := getBit(a, (f.N - f.NumBits + i + 1), f.N)

		// Figure out which half of expanded seeds to keep and lose
		keep := rightStart
		lose := leftStart
		if aBit == 0 {
			keep = leftStart
			lose = rightStart
		}
		//fmt.Println("keep", keep)
		//fmt.Println("aBit", aBit)
		// Set correction words for both keys. Note: they are the same
		for j := 0; j < aes.BlockSize; j++ {
			fssKeys[0].CW[i][j] = prfOut0[lose+j] ^ prfOut1[lose+j]
			fssKeys[1].CW[i][j] = fssKeys[0].CW[i][j]
		}
		fssKeys[0].CW[i][aes.BlockSize] = t0Left ^ t1Left ^ aBit ^ 1
		fssKeys[1].CW[i][aes.BlockSize] = fssKeys[0].CW[i][aes.BlockSize]
		fssKeys[0].CW[i][aes.BlockSize+1] = t0Right ^ t1Right ^ aBit
		fssKeys[1].CW[i][aes.BlockSize+1] = fssKeys[0].CW[i][aes.BlockSize+1]

		for j := 0; j < aes.BlockSize; j++ {
			sCurr0[j] = prfOut0[keep+j] ^ (tCurr0 * fssKeys[0].CW[i][j])
			sCurr1[j] = prfOut1[keep+j] ^ (tCurr1 * fssKeys[0].CW[i][j])
		}
		//fmt.Println("sKeep0:", prfOut0[keep:keep+aes.BlockSize])
		//fmt.Println("sKeep1:", prfOut1[keep:keep+aes.BlockSize])
		tCWKeep := fssKeys[0].CW[i][aes.BlockSize]
		if keep == rightStart {
			tCWKeep = fssKeys[0].CW[i][aes.BlockSize+1]
		}
		tCurr0 = (prfOut0[keep+aes.BlockSize] % 2) ^ tCWKeep*tCurr0
		tCurr1 = (prfOut1[keep+aes.BlockSize] % 2) ^ tCWKeep*tCurr1
	}
	// Convert final CW to integer
	sFinal0, _ := binary.Varint(sCurr0[:8])
	sFinal1, _ := binary.Varint(sCurr1[:8])
	fssKeys[0].FinalCW = (int(b) - int(sFinal0) + int(sFinal1))
	fssKeys[1].FinalCW = fssKeys[0].FinalCW
	if tCurr1 == 1 {
		fssKeys[0].FinalCW = fssKeys[0].FinalCW * -1
		fssKeys[1].FinalCW = fssKeys[0].FinalCW
	}
	return fssKeys
}

func (f Fss) EvaluatePF(serverNum byte, k FssKey, x uint) int {
	sCurr := make([]byte, aes.BlockSize)
	copy(sCurr, k.SInit)
	tCurr := k.TInit
	for i := uint(0); i < f.NumBits; i++ {
		prf(sCurr, f.FixedBlocks, 3, f.Temp, f.Out)
		//fmt.Println(i, sCurr)
		//fmt.Println(i, "f.Out:", f.Out)
		// Keep counter to ensure we are accessing CW correctly
		count := 0
		for j := 0; j < aes.BlockSize*2+2; j++ {
			// Make sure we are doing G(s) ^ (t*sCW||tLCW||sCW||tRCW)
			if j == aes.BlockSize+1 {
				count = 0
			} else if j == aes.BlockSize*2+1 {
				count = aes.BlockSize + 1
			}
			f.Out[j] = f.Out[j] ^ (tCurr * k.CW[i][count])
			count++
		}
		xBit := getBit(x, (f.N - f.NumBits + i + 1), f.N)
		//fmt.Println("xBit", xBit)
		// Pick right seed expansion based on
		if xBit == 0 {
			copy(sCurr, f.Out[:aes.BlockSize])
			tCurr = f.Out[aes.BlockSize] % 2
		} else {
			copy(sCurr, f.Out[(aes.BlockSize+1):(aes.BlockSize*2+1)])
			tCurr = f.Out[aes.BlockSize*2+1] % 2
		}
		//fmt.Println(f.Out)
	}
	sFinal, _ := binary.Varint(sCurr[:8])
	if serverNum == 0 {
		return int(sFinal) + int(tCurr)*k.FinalCW
	} else {
		return -1 * (int(sFinal) + int(tCurr)*k.FinalCW)
	}
}
<commit_msg>some changes<commit_after><|endoftext|>