<commit_before>package feature

import (
	"encoding/json"
	"errors"
	"fmt"
	"hash/crc32"
	"net/url"
	"strings"
	"time"

	"github.com/cozy/cozy-stack/model/instance"
	"github.com/cozy/cozy-stack/pkg/config/config"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/couchdb"
)

type Flags struct {
	DocID   string
	DocRev  string
	M       map[string]interface{}
	Sources []*Flags
}

func (f *Flags) ID() string        { return f.DocID }
func (f *Flags) Rev() string       { return f.DocRev }
func (f *Flags) DocType() string   { return consts.Settings }
func (f *Flags) SetID(id string)   { f.DocID = id }
func (f *Flags) SetRev(rev string) { f.DocRev = rev }
func (f *Flags) Clone() couchdb.Doc {
	clone := Flags{DocID: f.DocID, DocRev: f.DocRev}
	clone.M = make(map[string]interface{})
	for k, v := range f.M {
		clone.M[k] = v
	}
	return &clone
}
func (f *Flags) MarshalJSON() ([]byte, error) {
	return json.Marshal(f.M)
}

func (f *Flags) UnmarshalJSON(bytes []byte) error {
	err := json.Unmarshal(bytes, &f.M)
	if err != nil {
		return err
	}
	if id, ok := f.M["_id"].(string); ok {
		f.SetID(id)
		delete(f.M, "_id")
	}
	if rev, ok := f.M["_rev"].(string); ok {
		f.SetRev(rev)
		delete(f.M, "_rev")
	}
	return nil
}

func GetFlags(inst *instance.Instance) (*Flags, error) {
	sources := make([]*Flags, 0)
	m := make(map[string]interface{})
	flags := &Flags{
		DocID:   consts.FlagsSettingsID,
		M:       m,
		Sources: sources,
	}
	flags.addInstanceFlags(inst)
	if err := flags.addManager(inst); err != nil {
		return nil, err
	}
	if err := flags.addConfig(inst); err != nil {
		return nil, err
	}
	if err := flags.addContext(inst); err != nil {
		return nil, err
	}
	if err := flags.addDefaults(inst); err != nil {
		return nil, err
	}
	return flags, nil
}

func (f *Flags) addInstanceFlags(inst *instance.Instance) {
	if len(inst.FeatureFlags) == 0 {
		return
	}
	m := make(map[string]interface{})
	for k, v := range inst.FeatureFlags {
		m[k] = v
	}
	flags := &Flags{
		DocID: consts.InstanceFlagsSettingsID,
		M:     m,
	}
	f.Sources = append(f.Sources, flags)
	for k, v := range flags.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
}

func (f *Flags) addManager(inst *instance.Instance) error {
	if len(inst.FeatureSets) == 0 {
		return nil
	}
	m, err := getFlagsFromManager(inst)
	if err != nil || len(m) == 0 {
		return err
	}
	flags := &Flags{
		DocID: consts.ManagerFlagsSettingsID,
		M:     m,
	}
	f.Sources = append(f.Sources, flags)
	for k, v := range flags.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
	return nil
}

var (
	cacheDuration      = 12 * time.Hour
	errInvalidResponse = errors.New("Invalid response from the manager")
)

func getFlagsFromManager(inst *instance.Instance) (map[string]interface{}, error) {
	cache := config.GetConfig().CacheStorage
	cacheKey := fmt.Sprintf("flags:%s:%v", inst.ContextName, inst.FeatureSets)
	var flags map[string]interface{}
	if buf, ok := cache.Get(cacheKey); ok {
		if err := json.Unmarshal(buf, &flags); err == nil {
			return flags, nil
		}
	}

	client := instance.APIManagerClient(inst)
	if client == nil {
		return flags, nil
	}
	query := url.Values{
		"sets":    {strings.Join(inst.FeatureSets, ",")},
		"context": {inst.ContextName},
	}.Encode()
	var data map[string]interface{}
	if err := client.Get(fmt.Sprintf("/api/v1/flags?%s", query), &data); err != nil {
		return nil, err
	}
	var ok bool
	if flags, ok = data["flags"].(map[string]interface{}); !ok {
		return nil, errInvalidResponse
	}

	if buf, err := json.Marshal(flags); err == nil {
		cache.Set(cacheKey, buf, cacheDuration)
	}
	return flags, nil
}

func (f *Flags) addConfig(inst *instance.Instance) error {
	ctx, err := inst.SettingsContext()
	if err == instance.ErrContextNotFound {
		return nil
	} else if err != nil {
		return err
	}
	m, ok := ctx["features"].(map[interface{}]interface{})
	if !ok {
		return nil
	}
	normalized := make(map[string]interface{})
	for k, v := range m {
		normalized[fmt.Sprintf("%v", k)] = v
	}
	ctxFlags := &Flags{
		DocID: consts.ConfigFlagsSettingsID,
		M:     normalized,
	}
	f.Sources = append(f.Sources, ctxFlags)
	for k, v := range ctxFlags.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
	return nil
}

func (f *Flags) addContext(inst *instance.Instance) error {
	id := fmt.Sprintf("%s.%s", consts.ContextFlagsSettingsID, inst.ContextName)
	var context Flags
	err := couchdb.GetDoc(couchdb.GlobalDB, consts.Settings, id, &context)
	if couchdb.IsNotFoundError(err) {
		return nil
	} else if err != nil {
		return err
	}
	context.SetID(consts.ContextFlagsSettingsID)
	f.Sources = append(f.Sources, &context)
	for k, v := range context.M {
		if _, ok := f.M[k]; !ok {
			if value := applyRatio(inst, k, v); value != nil {
				f.M[k] = value
			}
		}
	}
	return nil
}

const maxUint32 = 1<<32 - 1

func applyRatio(inst *instance.Instance, key string, data interface{}) interface{} {
	items, ok := data.([]interface{})
	if !ok || len(items) == 0 {
		return nil
	}
	sum := crc32.ChecksumIEEE([]byte(fmt.Sprintf("%s:%s", inst.ContextName, key)))
	for i := range items {
		item, ok := items[i].(map[string]interface{})
		if !ok {
			continue
		}
		ratio, ok := item["ratio"].(float64)
		if !ok || ratio == 0.0 {
			continue
		}
		if ratio == 1.0 {
			return item["value"]
		}
		computed := uint32(ratio * maxUint32)
		if computed >= sum {
			return item["value"]
		}
		sum -= computed
	}
	return nil
}

func (f *Flags) addDefaults(inst *instance.Instance) error {
	var defaults Flags
	err := couchdb.GetDoc(couchdb.GlobalDB, consts.Settings, consts.DefaultFlagsSettingsID, &defaults)
	if couchdb.IsNotFoundError(err) {
		return nil
	} else if err != nil {
		return err
	}
	defaults.SetID(consts.DefaultFlagsSettingsID)
	f.Sources = append(f.Sources, &defaults)
	for k, v := range defaults.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
	return nil
}

var _ couchdb.Doc = &Flags{}
<commit_msg>Respond with default feature flags when manager is unavailable<commit_after>package feature

import (
	"encoding/json"
	"errors"
	"fmt"
	"hash/crc32"
	"net/url"
	"strings"
	"time"

	"github.com/cozy/cozy-stack/model/instance"
	"github.com/cozy/cozy-stack/pkg/config/config"
	"github.com/cozy/cozy-stack/pkg/consts"
	"github.com/cozy/cozy-stack/pkg/couchdb"
)

type Flags struct {
	DocID   string
	DocRev  string
	M       map[string]interface{}
	Sources []*Flags
}

func (f *Flags) ID() string        { return f.DocID }
func (f *Flags) Rev() string       { return f.DocRev }
func (f *Flags) DocType() string   { return consts.Settings }
func (f *Flags) SetID(id string)   { f.DocID = id }
func (f *Flags) SetRev(rev string) { f.DocRev = rev }
func (f *Flags) Clone() couchdb.Doc {
	clone := Flags{DocID: f.DocID, DocRev: f.DocRev}
	clone.M = make(map[string]interface{})
	for k, v := range f.M {
		clone.M[k] = v
	}
	return &clone
}
func (f *Flags) MarshalJSON() ([]byte, error) {
	return json.Marshal(f.M)
}

func (f *Flags) UnmarshalJSON(bytes []byte) error {
	err := json.Unmarshal(bytes, &f.M)
	if err != nil {
		return err
	}
	if id, ok := f.M["_id"].(string); ok {
		f.SetID(id)
		delete(f.M, "_id")
	}
	if rev, ok := f.M["_rev"].(string); ok {
		f.SetRev(rev)
		delete(f.M, "_rev")
	}
	return nil
}

func GetFlags(inst *instance.Instance) (*Flags, error) {
	sources := make([]*Flags, 0)
	m := make(map[string]interface{})
	flags := &Flags{
		DocID:   consts.FlagsSettingsID,
		M:       m,
		Sources: sources,
	}
	flags.addInstanceFlags(inst)
	if err := flags.addManager(inst); err != nil {
		inst.Logger().WithField("nspace", "flags").
			Warnf("Cannot get the flags from the manager: %s", err)
	}
	if err := flags.addConfig(inst); err != nil {
		inst.Logger().WithField("nspace", "flags").
			Warnf("Cannot get the flags from the config: %s", err)
	}
	if err := flags.addContext(inst); err != nil {
		inst.Logger().WithField("nspace", "flags").
			Warnf("Cannot get the flags from the context: %s", err)
	}
	if err := flags.addDefaults(inst); err != nil {
		inst.Logger().WithField("nspace", "flags").
			Warnf("Cannot get the flags from the defaults: %s", err)
	}
	return flags, nil
}

func (f *Flags) addInstanceFlags(inst *instance.Instance) {
	if len(inst.FeatureFlags) == 0 {
		return
	}
	m := make(map[string]interface{})
	for k, v := range inst.FeatureFlags {
		m[k] = v
	}
	flags := &Flags{
		DocID: consts.InstanceFlagsSettingsID,
		M:     m,
	}
	f.Sources = append(f.Sources, flags)
	for k, v := range flags.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
}

func (f *Flags) addManager(inst *instance.Instance) error {
	if len(inst.FeatureSets) == 0 {
		return nil
	}
	m, err := getFlagsFromManager(inst)
	if err != nil || len(m) == 0 {
		return err
	}
	flags := &Flags{
		DocID: consts.ManagerFlagsSettingsID,
		M:     m,
	}
	f.Sources = append(f.Sources, flags)
	for k, v := range flags.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
	return nil
}

var (
	cacheDuration      = 12 * time.Hour
	errInvalidResponse = errors.New("Invalid response from the manager")
)

func getFlagsFromManager(inst *instance.Instance) (map[string]interface{}, error) {
	cache := config.GetConfig().CacheStorage
	cacheKey := fmt.Sprintf("flags:%s:%v", inst.ContextName, inst.FeatureSets)
	var flags map[string]interface{}
	if buf, ok := cache.Get(cacheKey); ok {
		if err := json.Unmarshal(buf, &flags); err == nil {
			return flags, nil
		}
	}

	client := instance.APIManagerClient(inst)
	if client == nil {
		return flags, nil
	}
	query := url.Values{
		"sets":    {strings.Join(inst.FeatureSets, ",")},
		"context": {inst.ContextName},
	}.Encode()
	var data map[string]interface{}
	if err := client.Get(fmt.Sprintf("/api/v1/flags?%s", query), &data); err != nil {
		return nil, err
	}
	var ok bool
	if flags, ok = data["flags"].(map[string]interface{}); !ok {
		return nil, errInvalidResponse
	}

	if buf, err := json.Marshal(flags); err == nil {
		cache.Set(cacheKey, buf, cacheDuration)
	}
	return flags, nil
}

func (f *Flags) addConfig(inst *instance.Instance) error {
	ctx, err := inst.SettingsContext()
	if err == instance.ErrContextNotFound {
		return nil
	} else if err != nil {
		return err
	}
	m, ok := ctx["features"].(map[interface{}]interface{})
	if !ok {
		return nil
	}
	normalized := make(map[string]interface{})
	for k, v := range m {
		normalized[fmt.Sprintf("%v", k)] = v
	}
	ctxFlags := &Flags{
		DocID: consts.ConfigFlagsSettingsID,
		M:     normalized,
	}
	f.Sources = append(f.Sources, ctxFlags)
	for k, v := range ctxFlags.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
	return nil
}

func (f *Flags) addContext(inst *instance.Instance) error {
	id := fmt.Sprintf("%s.%s", consts.ContextFlagsSettingsID, inst.ContextName)
	var context Flags
	err := couchdb.GetDoc(couchdb.GlobalDB, consts.Settings, id, &context)
	if couchdb.IsNotFoundError(err) {
		return nil
	} else if err != nil {
		return err
	}
	context.SetID(consts.ContextFlagsSettingsID)
	f.Sources = append(f.Sources, &context)
	for k, v := range context.M {
		if _, ok := f.M[k]; !ok {
			if value := applyRatio(inst, k, v); value != nil {
				f.M[k] = value
			}
		}
	}
	return nil
}

const maxUint32 = 1<<32 - 1

func applyRatio(inst *instance.Instance, key string, data interface{}) interface{} {
	items, ok := data.([]interface{})
	if !ok || len(items) == 0 {
		return nil
	}
	sum := crc32.ChecksumIEEE([]byte(fmt.Sprintf("%s:%s", inst.ContextName, key)))
	for i := range items {
		item, ok := items[i].(map[string]interface{})
		if !ok {
			continue
		}
		ratio, ok := item["ratio"].(float64)
		if !ok || ratio == 0.0 {
			continue
		}
		if ratio == 1.0 {
			return item["value"]
		}
		computed := uint32(ratio * maxUint32)
		if computed >= sum {
			return item["value"]
		}
		sum -= computed
	}
	return nil
}

func (f *Flags) addDefaults(inst *instance.Instance) error {
	var defaults Flags
	err := couchdb.GetDoc(couchdb.GlobalDB, consts.Settings, consts.DefaultFlagsSettingsID, &defaults)
	if couchdb.IsNotFoundError(err) {
		return nil
	} else if err != nil {
		return err
	}
	defaults.SetID(consts.DefaultFlagsSettingsID)
	f.Sources = append(f.Sources, &defaults)
	for k, v := range defaults.M {
		if _, ok := f.M[k]; !ok {
			f.M[k] = v
		}
	}
	return nil
}

var _ couchdb.Doc = &Flags{}
<|endoftext|>


<commit_before>package commands

import (
    "fmt"
    "os"
    "strings"

    "github.com/spf13/cobra"
    "google.golang.org/grpc"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"

    pb "github.com/jaypipes/procession/proto"
)

const (
    permissionsHelpExtended = `

    NOTE: To find out what permissions may be applied to a role, use
          the p7n permissions command.
`
)

const (
    rolesHelpExtended = `

    NOTE: To find out what roles a user may be added to, use
          the p7n role list command.
`
)

const (
    errUnsetUser = `Error: unable to find the authenticating user.

Please set the PROCESSION_USER environment variable or supply a value
for the --user CLI option.
`
    errConnect = `Error: unable to connect to the Procession server.

Please check the PROCESSION_HOST and PROCESSION_PORT environment
variables or --host and --port  CLI options.
`
    errForbidden = `Error: you are not authorized to perform that action.`
    errBadVisibility = `Error: incorrect value for visibility.

Valid values are PUBLIC or PRIVATE.
`
)

const (
    msgNoRecords = "No records found matching search criteria."
)

// Some commonly-used CLI options
const (
    defaultListLimit = 20
)

var (
    listLimit int
    listMarker string
)

// Checks the given string to ensure it matches an appropriate value for a
// visibility setting and returns the matching integer value or exits with a
// usage message
func checkVisibility(cmd *cobra.Command, value string) pb.Visibility {
    ival, found := pb.Visibility_value[strings.ToUpper(value)]
    if ! found {
        fmt.Println(errBadVisibility)
        cmd.Usage()
        os.Exit(1)
    }
    return pb.Visibility(ival)
}

func exitIfConnectErr(err error) {
    if err != nil {
        fmt.Println(errConnect)
        os.Exit(1)
    }
}

func exitIfForbidden(err error) {
    if s, ok := status.FromError(err); ok {
        if s.Code() == codes.PermissionDenied {
            fmt.Println(errForbidden)
            os.Exit(int(s.Code()))
        }
    }
}

// Writes a generic error to output and exits if supplied error is an error
func exitIfError(err error) {
    if s, ok := status.FromError(err); ok {
        if s.Code() != codes.OK {
            fmt.Printf("Error: %s\n", s.Message())
            os.Exit(int(s.Code()))
        }
    }
}

func exitNoRecords() {
    if ! quiet {
        fmt.Println(msgNoRecords)
    }
    os.Exit(0)
}

func checkAuthUser(cmd *cobra.Command) {
    if authUser == "" && ! cmd.Flags().Changed("user") {
        fmt.Println(errUnsetUser)
        cmd.Usage()
        os.Exit(1)
    }
}

func connect() (*grpc.ClientConn) {
    var opts []grpc.DialOption
    opts = append(opts, grpc.WithInsecure())
    connectAddress := fmt.Sprintf("%s:%d", connectHost, connectPort)
    conn, err := grpc.Dial(connectAddress, opts...)
    if err != nil {
        fmt.Println(errConnect)
        os.Exit(1)
        return nil
    }
    return conn
}

func printIf(b bool, msg string, args ...interface{}) {
    if b {
        fmt.Printf(msg, args...)
    }
}

// Appends the standard listing CLI options to the supplied command struct
func addListOptions(cmd *cobra.Command) {
    cmd.Flags().IntVarP(
        &listLimit,
        "limit", "",
        defaultListLimit,
        "Number of records to limit results to.",
    )
    cmd.Flags().StringVarP(
        &listMarker,
        "marker", "",
        "",
        "Identifier of the last record on the previous page of results.",
    )
}

// Examines the supplied search listing options and returns a constructed
// pb.SearchOptions message struct for use in the request to the Procession
// service
func buildSearchOptions(cmd *cobra.Command) *pb.SearchOptions {
    res := &pb.SearchOptions{
        Limit: uint32(listLimit),
        Marker: listMarker,
    }
    return res
}
<commit_msg>add client --sort CLI option<commit_after>package commands

import (
    "fmt"
    "os"
    "strings"

    "github.com/spf13/cobra"
    "google.golang.org/grpc"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"

    pb "github.com/jaypipes/procession/proto"
)

const (
    permissionsHelpExtended = `

    NOTE: To find out what permissions may be applied to a role, use
          the p7n permissions command.
`
)

const (
    rolesHelpExtended = `

    NOTE: To find out what roles a user may be added to, use
          the p7n role list command.
`
)

const (
    errUnsetUser = `Error: unable to find the authenticating user.

Please set the PROCESSION_USER environment variable or supply a value
for the --user CLI option.
`
    errConnect = `Error: unable to connect to the Procession server.

Please check the PROCESSION_HOST and PROCESSION_PORT environment
variables or --host and --port  CLI options.
`
    errForbidden = `Error: you are not authorized to perform that action.`
    errBadVisibility = `Error: incorrect value for visibility.

Valid values are PUBLIC or PRIVATE.
`
)

const (
    msgNoRecords = "No records found matching search criteria."
)

// Some commonly-used CLI options
const (
    defaultListLimit = 20
    defaultListSort = "uuid:asc"
)

var (
    listLimit int
    listMarker string
    listSort string
)

// Checks the given string to ensure it matches an appropriate value for a
// visibility setting and returns the matching integer value or exits with a
// usage message
func checkVisibility(cmd *cobra.Command, value string) pb.Visibility {
    ival, found := pb.Visibility_value[strings.ToUpper(value)]
    if ! found {
        fmt.Println(errBadVisibility)
        cmd.Usage()
        os.Exit(1)
    }
    return pb.Visibility(ival)
}

func exitIfConnectErr(err error) {
    if err != nil {
        fmt.Println(errConnect)
        os.Exit(1)
    }
}

func exitIfForbidden(err error) {
    if s, ok := status.FromError(err); ok {
        if s.Code() == codes.PermissionDenied {
            fmt.Println(errForbidden)
            os.Exit(int(s.Code()))
        }
    }
}

// Writes a generic error to output and exits if supplied error is an error
func exitIfError(err error) {
    if s, ok := status.FromError(err); ok {
        if s.Code() != codes.OK {
            fmt.Printf("Error: %s\n", s.Message())
            os.Exit(int(s.Code()))
        }
    }
}

func exitNoRecords() {
    if ! quiet {
        fmt.Println(msgNoRecords)
    }
    os.Exit(0)
}

func checkAuthUser(cmd *cobra.Command) {
    if authUser == "" && ! cmd.Flags().Changed("user") {
        fmt.Println(errUnsetUser)
        cmd.Usage()
        os.Exit(1)
    }
}

func connect() (*grpc.ClientConn) {
    var opts []grpc.DialOption
    opts = append(opts, grpc.WithInsecure())
    connectAddress := fmt.Sprintf("%s:%d", connectHost, connectPort)
    conn, err := grpc.Dial(connectAddress, opts...)
    if err != nil {
        fmt.Println(errConnect)
        os.Exit(1)
        return nil
    }
    return conn
}

func printIf(b bool, msg string, args ...interface{}) {
    if b {
        fmt.Printf(msg, args...)
    }
}

// Appends the standard listing CLI options to the supplied command struct
func addListOptions(cmd *cobra.Command) {
    cmd.Flags().IntVarP(
        &listLimit,
        "limit", "",
        defaultListLimit,
        "Number of records to limit results to.",
    )
    cmd.Flags().StringVarP(
        &listMarker,
        "marker", "",
        "",
        "Identifier of the last record on the previous page of results.",
    )
    cmd.Flags().StringVarP(
        &listSort,
        "sort", "",
        defaultListSort,
        "Comma-delimited list of 'field:direction' indicators for sorting results",
    )
}

// Examines the supplied search listing options and returns a constructed
// pb.SearchOptions message struct for use in the request to the Procession
// service
func buildSearchOptions(cmd *cobra.Command) *pb.SearchOptions {
    sortIndicators := strings.Split(listSort, ",")
    sortFields := make([]*pb.SortField, len(sortIndicators))
    for x, indicator := range sortIndicators {
        parts := strings.Split(indicator, ":")
        direction := pb.SortDirection_ASC
        if len(parts) == 2 {
            askedDir := strings.ToUpper(parts[1])
            if val, ok := pb.SortDirection_value[askedDir]; ! ok {
                validVals := make([]string, 0)
                for _, validVal := range pb.SortDirection_name {
                    validVals = append(validVals, validVal)
                }
                fmt.Printf(
                    "Error: unknown sort direction '%s'. Valid values: %v\n",
                    askedDir,
                    validVals,
                )
                os.Exit(1)
            } else {
                direction = pb.SortDirection(val)
            }
        }
        sortField := &pb.SortField{
            Field: parts[0],
            Direction: direction,
        }
        sortFields[x] = sortField
    }
    res := &pb.SearchOptions{
        Limit: uint32(listLimit),
        Marker: listMarker,
        SortFields: sortFields,
    }
    return res
}
<|endoftext|>


<commit_before>package template

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

	"github.com/aymerick/raymond"
)

func init() {
	raymond.RegisterHelpers(funcs)
}

// Render parses and executes a template, returning the results
// in string format.
func Render(template string, args interface{}) (string, error) {

	return raymond.Render(template, args)
}

// Render parses and executes a template, returning the results
// in string format. The result is trimmed to remove left and right
// padding and newlines that may be added unintentially in the
// template markup.
func RenderTrim(template string, args interface{}) (string, error) {
	out, err := Render(template, normalize(args))
	return strings.Trim(out, " \n"), err
}

// Write parses and executes a template, writing the results to
// writer w.
func Write(w io.Writer, template string, args interface{}) error {
	out, err := Render(template, args)
	if err != nil {
		return err
	}
	_, err = io.WriteString(w, out)
	return err
}

var funcs = map[string]interface{}{
	"uppercase": strings.ToUpper,
	"lowercase": strings.ToLower,
	"duration":  toDuration,
	"datetime":  toDatetime,
	"success":   isSuccess,
	"failure":   isFailure,
}

// toDuration is a helper function that calculates a duration for a start and
// and end time, and returns the duration in string format.
func toDuration(started, finished float64) string {
	dur := time.Duration(int64(finished - started))
	return fmt.Sprintln(dur)
}

// toDatetime is a helper function that converts a unix timestamp to a string.
func toDatetime(timestamp float64, layout string) string {
	return time.Unix(int64(timestamp), 0).Format(layout)
}

// isSuccess is a helper function that executes a block iff the status
// is success, else it executes the else block.
func isSuccess(conditional bool, options *raymond.Options) string {
	if !conditional {
		return options.Inverse()
	}

	switch options.ParamStr(0) {
	case "success":
		return options.Fn()
	default:
		return options.Inverse()
	}
}

// isFailure is a helper function that executes a block iff the status
// is a form of failure, else it executes the else block.
func isFailure(conditional bool, options *raymond.Options) string {
	if !conditional {
		return options.Inverse()
	}

	switch options.ParamStr(0) {
	case "failure", "error", "killed":
		return options.Fn()
	default:
		return options.Inverse()
	}
}

// normalize takes a Go representation of the variable, marshals
// to json and then unmarshals to a map[string]interfacce{}. This
// is important because it let's us use the JSON variable names
// in our template
func normalize(in interface{}) map[string]interface{} {
	data, _ := json.Marshal(in) // we own the types, so this should never fail

	out := map[string]interface{}{}
	json.Unmarshal(data, &out)
	return out
}
<commit_msg>added default args type<commit_after>package template

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

	"github.com/aymerick/raymond"
	"github.com/drone/drone-go/drone"
)

func init() {
	raymond.RegisterHelpers(funcs)
}

type Args struct {
	Repo   *drone.Repo            `json:"repo"`
	Build  *drone.Build           `json:"build"`
	System *drone.System          `json:"system"`
	Vargs  map[string]interface{} `json:"vargs"`
}

// Render parses and executes a template, returning the results
// in string format.
func Render(template string, args interface{}) (string, error) {

	return raymond.Render(template, args)
}

// Render parses and executes a template, returning the results
// in string format. The result is trimmed to remove left and right
// padding and newlines that may be added unintentially in the
// template markup.
func RenderTrim(template string, args interface{}) (string, error) {
	out, err := Render(template, normalize(args))
	return strings.Trim(out, " \n"), err
}

// Write parses and executes a template, writing the results to
// writer w.
func Write(w io.Writer, template string, args interface{}) error {
	out, err := Render(template, args)
	if err != nil {
		return err
	}
	_, err = io.WriteString(w, out)
	return err
}

var funcs = map[string]interface{}{
	"uppercase": strings.ToUpper,
	"lowercase": strings.ToLower,
	"duration":  toDuration,
	"datetime":  toDatetime,
	"success":   isSuccess,
	"failure":   isFailure,
}

// toDuration is a helper function that calculates a duration for a start and
// and end time, and returns the duration in string format.
func toDuration(started, finished float64) string {
	dur := time.Duration(int64(finished - started))
	return fmt.Sprintln(dur)
}

// toDatetime is a helper function that converts a unix timestamp to a string.
func toDatetime(timestamp float64, layout string) string {
	return time.Unix(int64(timestamp), 0).Format(layout)
}

// isSuccess is a helper function that executes a block iff the status
// is success, else it executes the else block.
func isSuccess(conditional bool, options *raymond.Options) string {
	if !conditional {
		return options.Inverse()
	}

	switch options.ParamStr(0) {
	case "success":
		return options.Fn()
	default:
		return options.Inverse()
	}
}

// isFailure is a helper function that executes a block iff the status
// is a form of failure, else it executes the else block.
func isFailure(conditional bool, options *raymond.Options) string {
	if !conditional {
		return options.Inverse()
	}

	switch options.ParamStr(0) {
	case "failure", "error", "killed":
		return options.Fn()
	default:
		return options.Inverse()
	}
}

// normalize takes a Go representation of the variable, marshals
// to json and then unmarshals to a map[string]interfacce{}. This
// is important because it let's us use the JSON variable names
// in our template
func normalize(in interface{}) map[string]interface{} {
	data, _ := json.Marshal(in) // we own the types, so this should never fail

	out := map[string]interface{}{}
	json.Unmarshal(data, &out)
	return out
}
<|endoftext|>


<commit_before>package toolbox

import "fmt"

//Dump prints passed in data as JSON
func Dump(data interface{}) {
	if text, err := AsJSONText(data); err == nil {
		fmt.Printf("%v\n", text)
		return
	}
}
<commit_msg>added utiliy method<commit_after>package toolbox

import "fmt"

//Dump prints passed in data as JSON
func Dump(data interface{}) {
	if text, err := AsJSONText(data); err == nil {
		fmt.Printf("%v\n", text)
		return
	}
}

//DumpIndent prints passed in data as indented JSON
func DumpIndent(data interface{}, removeEmptyKeys bool) error {
	if IsMap(data) || IsStruct(data) {
		var aMap= map[string]interface{}{}
		if err := DefaultConverter.AssignConverted(&aMap, data);err != nil {
			return err
		}
		data = aMap
		if removeEmptyKeys {
			data = DeleteEmptyKeys(aMap)
		}
	}

	text, err := AsIndentJSONText(data);
	if err != nil {
		return err
	}
	fmt.Printf("%v\n", text)
	return nil
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 cli

import (
	"fmt"
	"strconv"

	"mynewt.apache.org/newt/newtmgr/protocol"

	"github.com/spf13/cobra"
)

const (
	LEVEL_DEBUG    uint64 = 0
	LEVEL_INFO     uint64 = 1
	LEVEL_WARN     uint64 = 2
	LEVEL_ERROR    uint64 = 3
	LEVEL_CRITICAL uint64 = 4
	/* Upto 7 custom loglevels */
	LEVEL_MAX uint64 = 255
)

const (
	STREAM_LOG  uint64 = 0
	MEMORY_LOG  uint64 = 1
	STORAGE_LOG uint64 = 2
)

const (
	MODULE_DEFAULT     uint64 = 0
	MODULE_OS          uint64 = 1
	MODULE_NEWTMGR     uint64 = 2
	MODULE_NIMBLE_CTLR uint64 = 3
	MODULE_NIMBLE_HOST uint64 = 4
	MODULE_NFFS        uint64 = 5
	MODULE_REBOOT      uint64 = 6
	MODULE_TEST        uint64 = 8
	MODULE_MAX         uint64 = 255
)

func LogModuleToString(lm uint64) string {
	s := ""
	switch lm {
	case MODULE_DEFAULT:
		s = "DEFAULT"
	case MODULE_OS:
		s = "OS"
	case MODULE_NEWTMGR:
		s = "NEWTMGR"
	case MODULE_NIMBLE_CTLR:
		s = "NIMBLE_CTLR"
	case MODULE_NIMBLE_HOST:
		s = "NIMBLE_HOST"
	case MODULE_NFFS:
		s = "NFFS"
	case MODULE_REBOOT:
		s = "REBOOT"
	case MODULE_TEST:
		s = "TEST"
	default:
		s = "CUSTOM"
	}
	return s
}

func LoglevelToString(ll uint64) string {
	s := ""
	switch ll {
	case LEVEL_DEBUG:
		s = "DEBUG"
	case LEVEL_INFO:
		s = "INFO"
	case LEVEL_WARN:
		s = "WARN"
	case LEVEL_ERROR:
		s = "ERROR"
	case LEVEL_CRITICAL:
		s = "CRITICAL"
	default:
		s = "CUSTOM"
	}
	return s
}

func LogTypeToString(lt uint64) string {
	s := ""
	switch lt {
	case STREAM_LOG:
		s = "STREAM"
	case MEMORY_LOG:
		s = "MEMORY"
	case STORAGE_LOG:
		s = "STORAGE"
	default:
		s = "UNDEFINED"
	}
	return s
}

func logsShowCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()

	req, err := protocol.NewLogsShowReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	if len(args) >= 1 {
		req.Name = args[0]
	}

	if len(args) >= 2 {
		if args[1] == "last" {
			req.Index = 0
			req.Timestamp = -1
		} else {
			req.Index, err = strconv.ParseUint(args[1], 0, 64)
			if err != nil {
				nmUsage(cmd, err)
			}
		}
	}

	if len(args) >= 3 && req.Timestamp != -1 {
		req.Timestamp, err = strconv.ParseInt(args[1], 0, 64)
		if err != nil {
			nmUsage(cmd, err)
		}
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsShowResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	for j := 0; j < len(decodedResponse.Logs); j++ {
		fmt.Println("Name:", decodedResponse.Logs[j].Name)
		fmt.Println("Type:", LogTypeToString(decodedResponse.Logs[j].Type))

		for i := 0; i < len(decodedResponse.Logs[j].Entries); i++ {
			fmt.Println(fmt.Sprintf("%20d usecs %10d > %s: %s: %s",
				decodedResponse.Logs[j].Entries[i].Timestamp,
				decodedResponse.Logs[j].Entries[i].Index,
				LogModuleToString(decodedResponse.Logs[j].Entries[i].Module),
				LoglevelToString(decodedResponse.Logs[j].Entries[i].Level),
				decodedResponse.Logs[j].Entries[i].Msg))
		}
	}

	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsModuleListCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()

	req, err := protocol.NewLogsModuleListReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsModuleListResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Println(decodedResponse.Map)
	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)

}

func logsListCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()
	req, err := protocol.NewLogsListReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsListResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Println(decodedResponse.List)
	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsLevelListCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()
	req, err := protocol.NewLogsLevelListReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsLevelListResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Println(decodedResponse.Map)
	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsClearCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()

	req, err := protocol.NewLogsClearReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsClearResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsCmd() *cobra.Command {
	logsCmd := &cobra.Command{
		Use:   "logs",
		Short: "Handles logs on remote instance",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.HelpFunc()(cmd, args)
		},
	}

	showCmd := &cobra.Command{
		Use:   "show [log-name] [min-index] [min-timestamp]",
		Short: "Show logs on target",
		Run:   logsShowCmd,
	}
	logsCmd.AddCommand(showCmd)

	clearCmd := &cobra.Command{
		Use:   "clear",
		Short: "Clear logs on target",
		Run:   logsClearCmd,
	}
	logsCmd.AddCommand(clearCmd)

	moduleListCmd := &cobra.Command{
		Use:   "module_list",
		Short: "Module List Command",
		Run:   logsModuleListCmd,
	}
	logsCmd.AddCommand(moduleListCmd)

	levelListCmd := &cobra.Command{
		Use:   "level_list",
		Short: "Level List Command",
		Run:   logsLevelListCmd,
	}

	logsCmd.AddCommand(levelListCmd)

	ListCmd := &cobra.Command{
		Use:   "log_list",
		Short: "Log List Command",
		Run:   logsListCmd,
	}

	logsCmd.AddCommand(ListCmd)
	return logsCmd
}
<commit_msg>newtmgr - improve log usability.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 cli

import (
	"fmt"
	"strconv"

	"mynewt.apache.org/newt/newtmgr/protocol"

	"github.com/spf13/cobra"
)

const (
	LEVEL_DEBUG    uint64 = 0
	LEVEL_INFO     uint64 = 1
	LEVEL_WARN     uint64 = 2
	LEVEL_ERROR    uint64 = 3
	LEVEL_CRITICAL uint64 = 4
	/* Upto 7 custom loglevels */
	LEVEL_MAX uint64 = 255
)

const (
	STREAM_LOG  uint64 = 0
	MEMORY_LOG  uint64 = 1
	STORAGE_LOG uint64 = 2
)

const (
	MODULE_DEFAULT     uint64 = 0
	MODULE_OS          uint64 = 1
	MODULE_NEWTMGR     uint64 = 2
	MODULE_NIMBLE_CTLR uint64 = 3
	MODULE_NIMBLE_HOST uint64 = 4
	MODULE_NFFS        uint64 = 5
	MODULE_REBOOT      uint64 = 6
	MODULE_TEST        uint64 = 8
	MODULE_MAX         uint64 = 255
)

func LogModuleToString(lm uint64) string {
	s := ""
	switch lm {
	case MODULE_DEFAULT:
		s = "DEFAULT"
	case MODULE_OS:
		s = "OS"
	case MODULE_NEWTMGR:
		s = "NEWTMGR"
	case MODULE_NIMBLE_CTLR:
		s = "NIMBLE_CTLR"
	case MODULE_NIMBLE_HOST:
		s = "NIMBLE_HOST"
	case MODULE_NFFS:
		s = "NFFS"
	case MODULE_REBOOT:
		s = "REBOOT"
	case MODULE_TEST:
		s = "TEST"
	default:
		s = "CUSTOM"
	}
	return s
}

func LoglevelToString(ll uint64) string {
	s := ""
	switch ll {
	case LEVEL_DEBUG:
		s = "DEBUG"
	case LEVEL_INFO:
		s = "INFO"
	case LEVEL_WARN:
		s = "WARN"
	case LEVEL_ERROR:
		s = "ERROR"
	case LEVEL_CRITICAL:
		s = "CRITICAL"
	default:
		s = "CUSTOM"
	}
	return s
}

func LogTypeToString(lt uint64) string {
	s := ""
	switch lt {
	case STREAM_LOG:
		s = "STREAM"
	case MEMORY_LOG:
		s = "MEMORY"
	case STORAGE_LOG:
		s = "STORAGE"
	default:
		s = "UNDEFINED"
	}
	return s
}

func logsShowCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()

	req, err := protocol.NewLogsShowReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	if len(args) >= 1 {
		req.Name = args[0]
	}

	if len(args) >= 2 {
		if args[1] == "last" {
			req.Index = 0
			req.Timestamp = -1
		} else {
			req.Index, err = strconv.ParseUint(args[1], 0, 64)
			if err != nil {
				nmUsage(cmd, err)
			}
		}
	}

	if len(args) >= 3 && req.Timestamp != -1 {
		req.Timestamp, err = strconv.ParseInt(args[1], 0, 64)
		if err != nil {
			nmUsage(cmd, err)
		}
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsShowResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	for j := 0; j < len(decodedResponse.Logs); j++ {
		fmt.Println("Name:", decodedResponse.Logs[j].Name)
		fmt.Println("Type:", LogTypeToString(decodedResponse.Logs[j].Type))

		for i := 0; i < len(decodedResponse.Logs[j].Entries); i++ {
			fmt.Println(fmt.Sprintf("%20d usecs %10d > %s: %s: %s",
				decodedResponse.Logs[j].Entries[i].Timestamp,
				decodedResponse.Logs[j].Entries[i].Index,
				LogModuleToString(decodedResponse.Logs[j].Entries[i].Module),
				LoglevelToString(decodedResponse.Logs[j].Entries[i].Level),
				decodedResponse.Logs[j].Entries[i].Msg))
		}
	}

	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsModuleListCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()

	req, err := protocol.NewLogsModuleListReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsModuleListResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Println(decodedResponse.Map)
	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)

}

func logsListCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()
	req, err := protocol.NewLogsListReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsListResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Println(decodedResponse.List)
	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsLevelListCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()
	req, err := protocol.NewLogsLevelListReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsLevelListResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Println(decodedResponse.Map)
	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsClearCmd(cmd *cobra.Command, args []string) {
	runner, err := getTargetCmdRunner()
	if err != nil {
		nmUsage(cmd, err)
	}
	defer runner.Conn.Close()

	req, err := protocol.NewLogsClearReq()
	if err != nil {
		nmUsage(cmd, err)
	}

	nmr, err := req.Encode()
	if err != nil {
		nmUsage(cmd, err)
	}

	if err := runner.WriteReq(nmr); err != nil {
		nmUsage(cmd, err)
	}

	rsp, err := runner.ReadResp()
	if err != nil {
		nmUsage(cmd, err)
	}

	decodedResponse, err := protocol.DecodeLogsClearResponse(rsp.Data)
	if err != nil {
		nmUsage(cmd, err)
	}

	fmt.Printf("Return Code = %d\n", decodedResponse.ReturnCode)
}

func logsCmd() *cobra.Command {
	logsCmd := &cobra.Command{
		Use:   "log",
		Short: "Handles logs on remote instance",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.HelpFunc()(cmd, args)
		},
	}

	showCmd := &cobra.Command{
		Use:   "show [log-name] [min-index] [min-timestamp]",
		Short: "Show logs on target",
		Run:   logsShowCmd,
	}
	logsCmd.AddCommand(showCmd)

	clearCmd := &cobra.Command{
		Use:   "clear",
		Short: "Clear logs on target",
		Run:   logsClearCmd,
	}
	logsCmd.AddCommand(clearCmd)

	moduleListCmd := &cobra.Command{
		Use:   "module_list",
		Short: "Module List Command",
		Run:   logsModuleListCmd,
	}
	logsCmd.AddCommand(moduleListCmd)

	levelListCmd := &cobra.Command{
		Use:   "level_list",
		Short: "Level List Command",
		Run:   logsLevelListCmd,
	}

	logsCmd.AddCommand(levelListCmd)

	ListCmd := &cobra.Command{
		Use:   "list",
		Short: "Log List Command",
		Run:   logsListCmd,
	}

	logsCmd.AddCommand(ListCmd)
	return logsCmd
}
<|endoftext|>


<commit_before>// Package edison provides simplified Go development for Intel Edison.
package edison
<commit_msg>Add edison Init function<commit_after>// Package edison provides simplified Go development for Intel Edison.
package edison

func Init() error {
	var err error
	tristate := newDigitalPin(214)
	if err = tristate.Export(); err != nil {
		return err
	}
	if err = tristate.Direction(OUT); err != nil {
		return err
	}
	if err = tristate.DigitalWrite(LOW); err != nil {
		return err
	}

	for _, i := range []int{263, 262} {
		io := newDigitalPin(i)
		if err = io.Export(); err != nil {
			return err
		}
		if err = io.Direction(OUT); err != nil {
			return err
		}
		if err = io.DigitalWrite(HIGH); err != nil {
			return err
		}
		if err = io.Unexport(); err != nil {
			return err
		}
	}

	for _, i := range []int{240, 241, 242, 243} {
		io := newDigitalPin(i)
		if err = io.Export(); err != nil {
			return err
		}
		if err = io.Direction(OUT); err != nil {
			return err
		}
		if err = io.DigitalWrite(LOW); err != nil {
			return err
		}
		if err = io.Unexport(); err != nil {
			return err
		}

	}

	for _, i := range []int{111, 115, 114, 109} {
		if err = changePinMode(i, "1"); err != nil {
			return err
		}
	}

	for _, i := range []int{131, 129, 40} {
		if err = changePinMode(i, "0"); err != nil {
			return err
		}
	}

	err = tristate.DigitalWrite(HIGH)
	return nil
}
<|endoftext|>


<commit_before>package multasgt

import (
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"sync"

	"github.com/PuerkitoBio/goquery"
)

// Ensure interface implementation.
var _ TicketChecker = &Emetra{}

const (
	emetraURL = "http://consulta.muniguate.com/emetra/despliega.php"
)

// Emetra implementation.
type Emetra struct {
	Client *http.Client
}

func (e *Emetra) processEmetraTicket(wg *sync.WaitGroup, tickets []Ticket, idx int, sel *goquery.Selection) {
	defer wg.Done()
	info := sel.Find(".texto")
	if len(info.Nodes) < 3 {
		return
	}
	photoURL := "http://consultas.muniguate.com/consultas/remisiones/remision_pic.jsp?r=%v"

	rURL, err := url.Parse(getAttribute("href", info.Get(1)))
	if err != nil {
		return
	}

	date := info.Get(0).FirstChild.Data
	loc := info.Get(1).FirstChild.Data
	ammount := info.Get(2).FirstChild.Data
	parsedPhotoURL := fmt.Sprintf(photoURL, rURL.Query().Get("r"))
	var photo string
	tickets[idx] = Ticket{
		Entity:   "EMETRA",
		Date:     date,
		Ammount:  ammount,
		Photo:    photo,
		Location: loc,
	}

	res, err := e.Client.Get(parsedPhotoURL)
	if err != nil {
		return
	}

	photoDoc, err := goquery.NewDocumentFromResponse(res)
	m := photoDoc.Find(`strong:contains("MOTIVO DE REMISION:")`).Parent().Text()
	tickets[idx].Info = cleanStrings(strings.Replace(m, "MOTIVO DE REMISION:", "", -1))
	regex := `[src#=(^http:\/\/consultas.muniguate.com\/consultas\/fotos)]`
	// URL comes with an extra \n.
	tickets[idx].Photo = cleanStrings(getAttribute("src", photoDoc.Find(regex).Get(0)))

}

// Check retrieves all tickes and aditional information.
func (e *Emetra) Check(plateType, plateNumber string) ([]Ticket, error) {
	resp, err := e.Client.PostForm(emetraURL, url.Values{
		"tplaca": {plateType},
		"nplaca": {plateNumber},
	})

	if err != nil {
		return nil, err
	}
	doc, err := goquery.NewDocumentFromResponse(resp)

	var wg sync.WaitGroup

	rows := doc.Find("tr.row")
	tickets := make([]Ticket, len(rows.Nodes))
	rows.Each(func(idx int, sel *goquery.Selection) {
		wg.Add(1)
		e.processEmetraTicket(&wg, tickets, idx, sel)
	})
	wg.Wait()
	return tickets, nil
}
<commit_msg>Add ID to emetra<commit_after>package multasgt

import (
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"sync"

	"github.com/PuerkitoBio/goquery"
)

// Ensure interface implementation.
var _ TicketChecker = &Emetra{}

const (
	emetraURL = "http://consulta.muniguate.com/emetra/despliega.php"
)

// Emetra implementation.
type Emetra struct {
	Client *http.Client
}

func (e *Emetra) processEmetraTicket(wg *sync.WaitGroup, tickets []Ticket, idx int, sel *goquery.Selection) {
	defer wg.Done()
	info := sel.Find(".texto")
	if len(info.Nodes) < 3 {
		return
	}
	photoURL := "http://consultas.muniguate.com/consultas/remisiones/remision_pic.jsp?r=%v"

	rURL, err := url.Parse(getAttribute("href", info.Get(1)))
	if err != nil {
		return
	}

	date := info.Get(0).FirstChild.Data
	loc := info.Get(1).FirstChild.Data
	ammount := info.Get(2).FirstChild.Data
	id := rURL.Query().Get("r")
	parsedPhotoURL := fmt.Sprintf(photoURL, id)
	var photo string
	tickets[idx] = Ticket{
		Entity:   "EMETRA",
		ID:       id,
		Date:     date,
		Ammount:  ammount,
		Photo:    photo,
		Location: loc,
	}

	res, err := e.Client.Get(parsedPhotoURL)
	if err != nil {
		return
	}

	photoDoc, err := goquery.NewDocumentFromResponse(res)
	m := photoDoc.Find(`strong:contains("MOTIVO DE REMISION:")`).Parent().Text()
	tickets[idx].Info = cleanStrings(strings.Replace(m, "MOTIVO DE REMISION:", "", -1))
	regex := `[src#=(^http:\/\/consultas.muniguate.com\/consultas\/fotos)]`
	// URL comes with an extra \n.
	tickets[idx].Photo = cleanStrings(getAttribute("src", photoDoc.Find(regex).Get(0)))

}

// Check retrieves all tickes and aditional information.
func (e *Emetra) Check(plateType, plateNumber string) ([]Ticket, error) {
	resp, err := e.Client.PostForm(emetraURL, url.Values{
		"tplaca": {plateType},
		"nplaca": {plateNumber},
	})

	if err != nil {
		return nil, err
	}
	doc, err := goquery.NewDocumentFromResponse(resp)

	var wg sync.WaitGroup

	rows := doc.Find("tr.row")
	tickets := make([]Ticket, len(rows.Nodes))
	rows.Each(func(idx int, sel *goquery.Selection) {
		wg.Add(1)
		e.processEmetraTicket(&wg, tickets, idx, sel)
	})
	wg.Wait()
	return tickets, nil
}
<|endoftext|>


<commit_before>package tnetstring

import (
	"errors"
	"math"
	"reflect"
	"strconv"
)

func Marshal(v interface{}) (s string, err error) {
	defer func() {
		if s, ok := recover().(string); ok {
			err = errors.New(s)
		}
	}()
	val := reflect.ValueOf(v)
	var b outbuf
	b.n = 20
	b.buf = make([]byte, b.n)
	lookupEncode(val.Kind())(&b, val)
	return string(b.buf[b.n:]), nil
}

var encodeTable []func(*outbuf, reflect.Value)

func init() {
	encodeTable = []func(*outbuf, reflect.Value){
		reflect.Invalid:   encodeNull,
		reflect.Bool:      encodeBool,
		reflect.Int:       encodeInt,
		reflect.Int8:      encodeInt,
		reflect.Int16:     encodeInt,
		reflect.Int32:     encodeInt,
		reflect.Int64:     encodeInt,
		reflect.Uint:      encodeUint,
		reflect.Uint8:     encodeUint,
		reflect.Uint16:    encodeUint,
		reflect.Uint32:    encodeUint,
		reflect.Uint64:    encodeUint,
		reflect.Uintptr:   encodeUint,
		reflect.String:    encodeString,
		reflect.Array:     encodeArray,
		reflect.Slice:     encodeArray,
		reflect.Map:       encodeMap,
		reflect.Struct:    encodeStruct,
		reflect.Ptr:       encodeIndirect,
		reflect.Interface: encodeIndirect,
		// include last item so the array has the right length
		reflect.UnsafePointer: nil,
	}
}

func encodeNull(b *outbuf, v reflect.Value) {
	b.writeRawString("0:~")
}

func encodeBool(b *outbuf, v reflect.Value) {
	if v.Bool() {
		b.writeRawString("4:true!")
		return
	}
	b.writeRawString("5:false!")
}

func encodeInt(b *outbuf, v reflect.Value) {
	val := v.Int()
	var vallen int
	llen := 1
	switch {
	case val < -999999999:
		llen = 3
		fallthrough
	case val < 0:
		vallen = digitCount(uint64(-val)) + 1
	case val > 999999999:
		llen = 2
		fallthrough
	default:
		vallen = digitCount(uint64(val))
	}
	n := llen + 1 + vallen + 1
	if b.n < n {
		b.grow(n)
	}
	b.n--
	b.buf[b.n] = '#'
	b.n -= vallen
	valstr := strconv.AppendInt(b.buf[b.n:b.n], val, 10)
	l := len(valstr)
	b.n--
	b.buf[b.n] = ':'
	b.n -= llen
	strconv.AppendUint(b.buf[:b.n], uint64(l), 10)
}

func encodeUint(b *outbuf, v reflect.Value) {
	val := v.Uint()
	vallen := digitCount(val)
	llen := 1
	if val > 999999999 {
		llen = 2
	}
	n := llen + 1 + vallen + 1
	if b.n < n {
		b.grow(n)
	}
	b.n--
	b.buf[b.n] = '#'
	b.n -= vallen
	valstr := strconv.AppendUint(b.buf[b.n:b.n], val, 10)
	l := len(valstr)
	b.n--
	b.buf[b.n] = ':'
	b.n -= llen
	strconv.AppendUint(b.buf[:b.n], uint64(l), 10)
}

func encodeString(b *outbuf, v reflect.Value) {
	b.writeTString(',', v.String())
}

func encodeArray(b *outbuf, v reflect.Value) {
	mark := b.mark(']')
	encodeFunc := lookupEncode(v.Type().Elem().Kind())
	for i := v.Len() - 1; i >= 0; i-- {
		encodeFunc(b, v.Index(i))
	}
	b.writeLen(mark)
}

func encodeMap(b *outbuf, v reflect.Value) {
	mark := b.mark('}')
	mapType := v.Type()
	if mapType.Key().Kind() != reflect.String {
		panic("tnetstring: only maps with string keys can be encoded")
	}
	encodeFunc := lookupEncode(mapType.Elem().Kind())
	for _, key := range v.MapKeys() {
		encodeFunc(b, v.MapIndex(key))
		b.writeTString(',', key.String())
	}
	b.writeLen(mark)
}

func encodeStruct(b *outbuf, v reflect.Value) {
	mark := b.mark('}')
	t := v.Type()
	l := t.NumField()
	for i := l - 1; i >= 0; i-- {
		field := t.Field(i)
		str := field.Tag.Get("tnetstring")
		if str == "" {
			str = field.Name
		}
		lookupEncode(field.Type.Kind())(b, v.Field(i))
		b.writeTString(',', str)
	}
	b.writeLen(mark)
}

func encodeIndirect(b *outbuf, v reflect.Value) {
	for {
		switch kind := v.Kind(); kind {
		case reflect.Ptr, reflect.Interface:
			v = v.Elem()
		default:
			lookupEncode(kind)(b, v)
			return
		}
	}
}

func lookupEncode(k reflect.Kind) func(*outbuf, reflect.Value) {
	if f := encodeTable[k]; f != nil {
		return f
	}
	panic("tnetstring: unsupported type")
}

type outbuf struct {
	buf []byte
	// n is the index we last wrote to or the amount of space left,
	// depending on how you look at it
	n int
}

func (b *outbuf) writeRawString(s string) {
	n := len(s)
	if b.n < n {
		b.grow(n)
	}
	b.n -= n
	copy(b.buf[b.n:], s)
}

func (buf *outbuf) writeByte(b byte) {
	if buf.n <= 0 {
		buf.grow(1)
	}
	buf.n--
	buf.buf[buf.n] = b
}

func (b *outbuf) mark(typ byte) int {
	b.writeByte(typ)
	return len(b.buf) - b.n
}

func (b *outbuf) writeTString(typ byte, s string) {
	l := len(s)
	llen := digitCount(uint64(l))
	n := llen + 1 + l + 1
	if b.n < n {
		b.grow(n)
	}
	b.n--
	b.buf[b.n] = typ
	b.n -= l
	copy(b.buf[b.n:], s)
	b.n--
	b.buf[b.n] = ':'
	b.n -= llen
	strconv.AppendInt(b.buf[:b.n], int64(l), 10)
}

func (b *outbuf) writeLen(mark int) {
	l := uint64(len(b.buf) - b.n - mark)
	b.writeByte(':')
	llen := digitCount(l)
	if b.n < llen {
		b.grow(llen)
	}
	b.n -= llen
	strconv.AppendUint(b.buf[:b.n], l, 10)
}

func (b *outbuf) grow(n int) {
	l := len(b.buf)
	need := 2 * l
	if need < l+n-b.n {
		need = l + n - b.n
	}
	buf := make([]byte, need)
	copy(buf[need-l+b.n:], b.buf[b.n:])
	b.buf = buf
	b.n = need - l + b.n
}

func digitCount(n uint64) int {
	if n == 0 {
		return 1
	}
	return int(math.Log10(float64(n)))+1
}
<commit_msg>Change writeTString to writeString<commit_after>package tnetstring

import (
	"errors"
	"math"
	"reflect"
	"strconv"
)

func Marshal(v interface{}) (s string, err error) {
	defer func() {
		if s, ok := recover().(string); ok {
			err = errors.New(s)
		}
	}()
	val := reflect.ValueOf(v)
	var b outbuf
	b.n = 20
	b.buf = make([]byte, b.n)
	lookupEncode(val.Kind())(&b, val)
	return string(b.buf[b.n:]), nil
}

var encodeTable []func(*outbuf, reflect.Value)

func init() {
	encodeTable = []func(*outbuf, reflect.Value){
		reflect.Invalid:   encodeNull,
		reflect.Bool:      encodeBool,
		reflect.Int:       encodeInt,
		reflect.Int8:      encodeInt,
		reflect.Int16:     encodeInt,
		reflect.Int32:     encodeInt,
		reflect.Int64:     encodeInt,
		reflect.Uint:      encodeUint,
		reflect.Uint8:     encodeUint,
		reflect.Uint16:    encodeUint,
		reflect.Uint32:    encodeUint,
		reflect.Uint64:    encodeUint,
		reflect.Uintptr:   encodeUint,
		reflect.String:    encodeString,
		reflect.Array:     encodeArray,
		reflect.Slice:     encodeArray,
		reflect.Map:       encodeMap,
		reflect.Struct:    encodeStruct,
		reflect.Ptr:       encodeIndirect,
		reflect.Interface: encodeIndirect,
		// include last item so the array has the right length
		reflect.UnsafePointer: nil,
	}
}

func encodeNull(b *outbuf, v reflect.Value) {
	b.writeRawString("0:~")
}

func encodeBool(b *outbuf, v reflect.Value) {
	if v.Bool() {
		b.writeRawString("4:true!")
		return
	}
	b.writeRawString("5:false!")
}

func encodeInt(b *outbuf, v reflect.Value) {
	val := v.Int()
	var vallen int
	llen := 1
	switch {
	case val < -999999999:
		llen = 3
		fallthrough
	case val < 0:
		vallen = digitCount(uint64(-val)) + 1
	case val > 999999999:
		llen = 2
		fallthrough
	default:
		vallen = digitCount(uint64(val))
	}
	n := llen + 1 + vallen + 1
	if b.n < n {
		b.grow(n)
	}
	b.n--
	b.buf[b.n] = '#'
	b.n -= vallen
	valstr := strconv.AppendInt(b.buf[b.n:b.n], val, 10)
	l := len(valstr)
	b.n--
	b.buf[b.n] = ':'
	b.n -= llen
	strconv.AppendUint(b.buf[:b.n], uint64(l), 10)
}

func encodeUint(b *outbuf, v reflect.Value) {
	val := v.Uint()
	vallen := digitCount(val)
	llen := 1
	if val > 999999999 {
		llen = 2
	}
	n := llen + 1 + vallen + 1
	if b.n < n {
		b.grow(n)
	}
	b.n--
	b.buf[b.n] = '#'
	b.n -= vallen
	valstr := strconv.AppendUint(b.buf[b.n:b.n], val, 10)
	l := len(valstr)
	b.n--
	b.buf[b.n] = ':'
	b.n -= llen
	strconv.AppendUint(b.buf[:b.n], uint64(l), 10)
}

func encodeString(b *outbuf, v reflect.Value) {
	b.writeString(v.String())
}

func encodeArray(b *outbuf, v reflect.Value) {
	mark := b.mark(']')
	encodeFunc := lookupEncode(v.Type().Elem().Kind())
	for i := v.Len() - 1; i >= 0; i-- {
		encodeFunc(b, v.Index(i))
	}
	b.writeLen(mark)
}

func encodeMap(b *outbuf, v reflect.Value) {
	mark := b.mark('}')
	mapType := v.Type()
	if mapType.Key().Kind() != reflect.String {
		panic("tnetstring: only maps with string keys can be encoded")
	}
	encodeFunc := lookupEncode(mapType.Elem().Kind())
	for _, key := range v.MapKeys() {
		encodeFunc(b, v.MapIndex(key))
		b.writeString(key.String())
	}
	b.writeLen(mark)
}

func encodeStruct(b *outbuf, v reflect.Value) {
	mark := b.mark('}')
	t := v.Type()
	l := t.NumField()
	for i := l - 1; i >= 0; i-- {
		field := t.Field(i)
		str := field.Tag.Get("tnetstring")
		if str == "" {
			str = field.Name
		}
		lookupEncode(field.Type.Kind())(b, v.Field(i))
		b.writeString(str)
	}
	b.writeLen(mark)
}

func encodeIndirect(b *outbuf, v reflect.Value) {
	for {
		switch kind := v.Kind(); kind {
		case reflect.Ptr, reflect.Interface:
			v = v.Elem()
		default:
			lookupEncode(kind)(b, v)
			return
		}
	}
}

func lookupEncode(k reflect.Kind) func(*outbuf, reflect.Value) {
	if f := encodeTable[k]; f != nil {
		return f
	}
	panic("tnetstring: unsupported type")
}

type outbuf struct {
	buf []byte
	// n is the index we last wrote to or the amount of space left,
	// depending on how you look at it
	n int
}

func (b *outbuf) writeRawString(s string) {
	n := len(s)
	if b.n < n {
		b.grow(n)
	}
	b.n -= n
	copy(b.buf[b.n:], s)
}

func (buf *outbuf) writeByte(b byte) {
	if buf.n <= 0 {
		buf.grow(1)
	}
	buf.n--
	buf.buf[buf.n] = b
}

func (b *outbuf) mark(typ byte) int {
	b.writeByte(typ)
	return len(b.buf) - b.n
}

func (b *outbuf) writeString(s string) {
	l := len(s)
	llen := digitCount(uint64(l))
	n := llen + 1 + l + 1
	if b.n < n {
		b.grow(n)
	}
	b.n--
	b.buf[b.n] = ','
	b.n -= l
	copy(b.buf[b.n:], s)
	b.n--
	b.buf[b.n] = ':'
	b.n -= llen
	strconv.AppendInt(b.buf[:b.n], int64(l), 10)
}

func (b *outbuf) writeLen(mark int) {
	l := uint64(len(b.buf) - b.n - mark)
	b.writeByte(':')
	llen := digitCount(l)
	if b.n < llen {
		b.grow(llen)
	}
	b.n -= llen
	strconv.AppendUint(b.buf[:b.n], l, 10)
}

func (b *outbuf) grow(n int) {
	l := len(b.buf)
	need := 2 * l
	if need < l+n-b.n {
		need = l + n - b.n
	}
	buf := make([]byte, need)
	copy(buf[need-l+b.n:], b.buf[b.n:])
	b.buf = buf
	b.n = need - l + b.n
}

func digitCount(n uint64) int {
	if n == 0 {
		return 1
	}
	return int(math.Log10(float64(n)))+1
}
<|endoftext|>


<commit_before>package yaml

import (
	"bytes"
	"fmt"
	"strconv"
)

func Encode(obj map[string]interface{}) (string, error) {
	var buf bytes.Buffer
	encode(&buf, obj, "", false)
	return buf.String(), nil
}

func encode(buf *bytes.Buffer, obj interface{}, indent string, inList bool) {
	firstIndent := ""
	if inList {
		firstIndent = indent[2:] + "- "
	}
	switch o := obj.(type) {
	case string:
		buf.WriteString(firstIndent)
		buf.WriteString(encodeString(o, len(indent)))
		buf.WriteString("\n")
	case int, int32, int64:
		buf.WriteString(firstIndent)
		buf.WriteString(strconv.FormatInt(o.(int64), 10))
		buf.WriteString("\n")
	case float32, float64:
		buf.WriteString(firstIndent)
		buf.WriteString(strconv.FormatFloat(o.(float64), 'g', -1, 64))
		buf.WriteString("\n")
	case map[string]interface{}:
		indent2 := indent + "    "
		nonFirstIndent := indent
		if inList {
			nonFirstIndent = indent[2:] + "  "
			indent = firstIndent
		}
		for key, val := range o {
			s := encodeString(key, len(firstIndent))
			switch val.(type) {
			case map[string]interface{}, []interface{}:
				buf.WriteString(indent + s + ":\n")
			default:
				buf.WriteString(indent + s + ": ")
			}
			encode(buf, val, indent2, false)
			indent = nonFirstIndent
		}
	case []interface{}:
		indent2 := indent + "  "
		for _, item := range o {
			encode(buf, item, indent2, true)
		}
	default:
		buf.WriteString(fmt.Sprintf("Whoops: %v", o))
	}
}

func encodeString(s string, level int) string {
	buf := []byte{}
	needsQuote := false
	needsBlock := false
	for _, c := range s {
		switch c {
		case '\t', '\f', '\b', '\r':
			needsQuote = true
		case '\n':
			needsBlock = true
		}
	}
	needsIndent := false
	if needsQuote {
		buf = append(buf, '"')
	} else if needsBlock {
		buf = append(buf, '|')
		buf = append(buf, '\n')
		for i := 0; i < level; i++ {
			buf = append(buf, ' ')
		}
	}

	for _, c := range s {
		if needsIndent {
			needsIndent = false
			buf = append(buf, '\n')
			for i := 0; i < level; i++ {
				buf = append(buf, ' ')
			}
		}
		switch c {
		case '"':
			if needsQuote {
				buf = append(buf, '\\')
			}
			buf = append(buf, '"')
		case '\\':
			buf = append(buf, '\\')
			buf = append(buf, '\\')
		case '\n':
			if needsBlock {
				needsIndent = true
			} else {
				buf = append(buf, '\\')
				buf = append(buf, 'n')
			}
		case '\t':
			buf = append(buf, '\\')
			buf = append(buf, 't')
		case '\f':
			buf = append(buf, '\\')
			buf = append(buf, 'f')
		case '\b':
			buf = append(buf, '\\')
			buf = append(buf, 'b')
		case '\r':
			buf = append(buf, '\\')
			buf = append(buf, 'r')
			//to do: handle non-byte unicode by encoding as "\uhhhh"
		default:
			buf = append(buf, byte(c))
		}
	}
	if needsQuote {
		buf = append(buf, '"')
	}
	return string(buf)
}
<commit_msg>Use reflect to handle objects<commit_after>package yaml

import (
	"bytes"
	"fmt"
	"reflect"
)

func Encode(obj interface{}) (string, error) {
	var buf bytes.Buffer
	encode(&buf, obj, "", false)
	return buf.String(), nil
}

func encode(buf *bytes.Buffer, obj interface{}, indent string, inList bool) {
	firstIndent := ""
	if inList {
		firstIndent = indent[2:] + "- "
	}
	switch o := obj.(type) {
	case string:
		buf.WriteString(firstIndent)
		buf.WriteString(encodeString(o, len(indent)))
		buf.WriteString("\n")
	case int, int32, int64:
		buf.WriteString(firstIndent)
		buf.WriteString(fmt.Sprintf("%d", o))
		buf.WriteString("\n")
	case float32, float64:
		buf.WriteString(firstIndent)
		buf.WriteString(fmt.Sprintf("%g", o))
		buf.WriteString("\n")
	case map[string]interface{}:
		indent2 := indent + "    "
		nonFirstIndent := indent
		if inList {
			nonFirstIndent = indent[2:] + "  "
			indent = firstIndent
		}
		for key, val := range o {
			s := encodeString(key, len(firstIndent))
			switch val.(type) {
			case map[string]interface{}, []interface{}:
				buf.WriteString(indent + s + ":\n")
			default:
				buf.WriteString(indent + s + ": ")
			}
			encode(buf, val, indent2, false)
			indent = nonFirstIndent
		}
	case []interface{}:
		indent2 := indent + "  "
		for _, item := range o {
			encode(buf, item, indent2, true)
		}
	default:
		typ := reflect.TypeOf(o)
		if typ.Kind() == reflect.Ptr{
			typ = typ.Elem()
		}
		if typ.Kind() == reflect.Struct {
			val := reflect.ValueOf(o)
			indent2 := indent + "    "
			nonFirstIndent := indent
			if inList {
				nonFirstIndent = indent[2:] + "  "
				indent = firstIndent
			}
			for i := 0; i < typ.NumField(); i++ {
				p := typ.Field(i)
				if !p.Anonymous {
					tag := p.Tag.Get("json")
					if tag != "-" { //avoid those marked to ignore
						if tag == "" {
							tag = p.Name
							//lower case preferred, but this is whan encoding/json does
						}
						s := encodeString(tag, len(firstIndent))
						value := val.Field(i).Interface()
						switch oo := value.(type) {
						case map[string]interface{}, []interface{}:
							buf.WriteString(indent + s + ":\n")
						default:
							typ2 := reflect.TypeOf(oo)
							if typ2.Kind() == reflect.Ptr {
								typ2 = typ2.Elem()
							}
							if typ2.Kind() == reflect.Struct {
								buf.WriteString(indent + s + ":\n")
							} else {
								buf.WriteString(indent + s + ": ")
							}
						}
						encode(buf, value, indent2, false)
						indent = nonFirstIndent
					}
				}
			}
		} else {
			buf.WriteString(fmt.Sprintf("Whoops: %v", o))
		}
	}
}

func encodeString(s string, level int) string {
	buf := []byte{}
	needsQuote := false
	needsBlock := false
	for _, c := range s {
		switch c {
		case '\t', '\f', '\b', '\r':
			needsQuote = true
		case '\n':
			needsBlock = true
		}
	}
	needsIndent := false
	if needsQuote {
		buf = append(buf, '"')
	} else if needsBlock {
		buf = append(buf, '|')
		buf = append(buf, '\n')
		for i := 0; i < level; i++ {
			buf = append(buf, ' ')
		}
	}

	for _, c := range s {
		if needsIndent {
			needsIndent = false
			buf = append(buf, '\n')
			for i := 0; i < level; i++ {
				buf = append(buf, ' ')
			}
		}
		switch c {
		case '"':
			if needsQuote {
				buf = append(buf, '\\')
			}
			buf = append(buf, '"')
		case '\\':
			buf = append(buf, '\\')
			buf = append(buf, '\\')
		case '\n':
			if needsBlock {
				needsIndent = true
			} else {
				buf = append(buf, '\\')
				buf = append(buf, 'n')
			}
		case '\t':
			buf = append(buf, '\\')
			buf = append(buf, 't')
		case '\f':
			buf = append(buf, '\\')
			buf = append(buf, 'f')
		case '\b':
			buf = append(buf, '\\')
			buf = append(buf, 'b')
		case '\r':
			buf = append(buf, '\\')
			buf = append(buf, 'r')
			//to do: handle non-byte unicode by encoding as "\uhhhh"
		default:
			buf = append(buf, byte(c))
		}
	}
	if needsQuote {
		buf = append(buf, '"')
	}
	return string(buf)
}
<|endoftext|>


<commit_before>// © 2014 Steve McCoy under the MIT license. See LICENSE for details.

package ogg

import (
	"bytes"
	"encoding/binary"
	"hash/crc32"
	"io"
)

// An Encoder encodes raw bytes into an ogg stream.
type Encoder struct {
	serial uint32
	w      io.Writer
	buf    [maxPageSize]byte
}

// NewEncoder creates an ogg encoder with the given serial ID.
// Multiple Encoders can be used to encode multiplexed logical streams
// by giving them distinct IDs. Users must be sure to encode the streams
// as specified by the ogg RFC:
// When Grouping, all BOS pages must come before the data
// and EOS pages, with the order of BOS pages defined by the encapsulated encoding.
// When Chaining, the EOS page of the first stream must be immediately followed by
// the BOS of the second stream, and so on.
//
// For more details, see
// http://xiph.org/ogg/doc/rfc3533.txt and
// http://xiph.org/ogg/doc/framing.html
func NewEncoder(id uint32, w io.Writer) *Encoder {
	return &Encoder{serial: id, w: w}
}

// EncodeBOS writes a beginning-of-stream packet to the ogg stream,
// using the provided granule position.
// If the packet is larger than can fit in a page, it is split into multiple
// pages with the continuation-of-packet flag set.
func (w *Encoder) EncodeBOS(granule int64, packet []byte) error {
	_, err := w.writePacket(BOS, granule, packet)
	return err
}

// Encode writes a data packet to the ogg stream,
// using the provided granule position.
// If the packet is larger than can fit in a page, it is split into multiple
// pages with the continuation-of-packet flag set.
func (w *Encoder) Encode(granule int64, packet []byte) (int, error) {
	return w.writePacket(0, granule, packet)
}

// EncodeBOS writes an end-of-stream packet to the ogg stream,
// using the provided granule position.
// If the packet is larger than can fit in a page, it is split into multiple
// pages with the continuation-of-packet flag set.
func (w *Encoder) EncodeEOS() error {
	_, err := w.writePacket(EOS, 0, nil)
	return err
}

func (w *Encoder) writePacket(kind byte, granule int64, packet []byte) (int, error) {
	h := pageHeader{
		OggS:       [4]byte{'O', 'g', 'g', 'S'},
		HeaderType: kind,
		Serial:     w.serial,
		Granule:    granule,
	}

	var err error
	n, m := 0, 0

	s := 0
	e := s + mps
	if e > len(packet) {
		e = len(packet)
	}
	page := packet[s:e]
	n, err = w.writePage(page, &h)
	if err != nil {
		return n, err
	}
	s = e

	last := (len(packet) / mps) * mps
	h.HeaderType &= COP
	for s < last {
		h.Page++
		e = s + mps
		page = packet[s:e]
		m, err = w.writePage(page, &h)
		n += m
		if err != nil {
			return n, err
		}
		s = e
	}

	if s != len(packet) {
		m, err = w.writePage(packet[s:], &h)
		n += m
	}
	return n, err
}

func (w *Encoder) writePage(page []byte, h *pageHeader) (int, error) {
	h.Nsegs = byte(len(page)/255 + 1)
	segtbl := make([]byte, h.Nsegs)
	for i := 0; i < len(segtbl)-1; i++ {
		segtbl[i] = 255
	}
	segtbl[len(segtbl)-1] = byte(len(page) % 255)

	hb := bytes.NewBuffer(w.buf[0:0:cap(w.buf)])
	err := binary.Write(hb, byteOrder, h)
	if err != nil {
		return 0, err
	}

	hb.Write(segtbl)
	hb.Write(page)

	bb := hb.Bytes()
	crc := crc32.Checksum(bb, crcTable)
	err = binary.Write(bytes.NewBuffer(bb[22:22:26]), byteOrder, crc)
	if err != nil {
		return 0, nil
	}

	n64, err := hb.WriteTo(w.w)
	return int(n64), err
}
<commit_msg>Fix spelling<commit_after>// © 2014 Steve McCoy under the MIT license. See LICENSE for details.

package ogg

import (
	"bytes"
	"encoding/binary"
	"hash/crc32"
	"io"
)

// An Encoder encodes raw bytes into an ogg stream.
type Encoder struct {
	serial uint32
	w      io.Writer
	buf    [maxPageSize]byte
}

// NewEncoder creates an ogg encoder with the given serial ID.
// Multiple Encoders can be used to encode multiplexed logical streams
// by giving them distinct IDs. Users must be sure to encode the streams
// as specified by the ogg RFC:
// When Grouping, all BOS pages must come before the data
// and EOS pages, with the order of BOS pages defined by the encapsulated encoding.
// When Chaining, the EOS page of the first stream must be immediately followed by
// the BOS of the second stream, and so on.
//
// For more details, see
// http://xiph.org/ogg/doc/rfc3533.txt and
// http://xiph.org/ogg/doc/framing.html
func NewEncoder(id uint32, w io.Writer) *Encoder {
	return &Encoder{serial: id, w: w}
}

// EncodeBOS writes a beginning-of-stream packet to the ogg stream,
// using the provided granule position.
// If the packet is larger than can fit in a page, it is split into multiple
// pages with the continuation-of-packet flag set.
func (w *Encoder) EncodeBOS(granule int64, packet []byte) error {
	_, err := w.writePacket(BOS, granule, packet)
	return err
}

// Encode writes a data packet to the ogg stream,
// using the provided granule position.
// If the packet is larger than can fit in a page, it is split into multiple
// pages with the continuation-of-packet flag set.
func (w *Encoder) Encode(granule int64, packet []byte) (int, error) {
	return w.writePacket(0, granule, packet)
}

// EncodeEOS writes an end-of-stream packet to the ogg stream,
// using the provided granule position.
// If the packet is larger than can fit in a page, it is split into multiple
// pages with the continuation-of-packet flag set.
func (w *Encoder) EncodeEOS() error {
	_, err := w.writePacket(EOS, 0, nil)
	return err
}

func (w *Encoder) writePacket(kind byte, granule int64, packet []byte) (int, error) {
	h := pageHeader{
		OggS:       [4]byte{'O', 'g', 'g', 'S'},
		HeaderType: kind,
		Serial:     w.serial,
		Granule:    granule,
	}

	var err error
	n, m := 0, 0

	s := 0
	e := s + mps
	if e > len(packet) {
		e = len(packet)
	}
	page := packet[s:e]
	n, err = w.writePage(page, &h)
	if err != nil {
		return n, err
	}
	s = e

	last := (len(packet) / mps) * mps
	h.HeaderType &= COP
	for s < last {
		h.Page++
		e = s + mps
		page = packet[s:e]
		m, err = w.writePage(page, &h)
		n += m
		if err != nil {
			return n, err
		}
		s = e
	}

	if s != len(packet) {
		m, err = w.writePage(packet[s:], &h)
		n += m
	}
	return n, err
}

func (w *Encoder) writePage(page []byte, h *pageHeader) (int, error) {
	h.Nsegs = byte(len(page)/255 + 1)
	segtbl := make([]byte, h.Nsegs)
	for i := 0; i < len(segtbl)-1; i++ {
		segtbl[i] = 255
	}
	segtbl[len(segtbl)-1] = byte(len(page) % 255)

	hb := bytes.NewBuffer(w.buf[0:0:cap(w.buf)])
	err := binary.Write(hb, byteOrder, h)
	if err != nil {
		return 0, err
	}

	hb.Write(segtbl)
	hb.Write(page)

	bb := hb.Bytes()
	crc := crc32.Checksum(bb, crcTable)
	err = binary.Write(bytes.NewBuffer(bb[22:22:26]), byteOrder, crc)
	if err != nil {
		return 0, nil
	}

	n64, err := hb.WriteTo(w.w)
	return int(n64), err
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package rpc

import (
	"sync"

	"go.uber.org/fx/modules"
	"go.uber.org/fx/service"

	"github.com/pkg/errors"
	"go.uber.org/yarpc/api/transport"
)

var _setupMu sync.Mutex

// CreateThriftServiceFunc creates a Thrift service from a service host
type CreateThriftServiceFunc func(svc service.Host) ([]transport.Procedure, error)

// ThriftModule creates a Thrift Module from a service func
func ThriftModule(hookup CreateThriftServiceFunc, options ...modules.Option) service.ModuleCreateFunc {
	return func(mi service.ModuleCreateInfo) ([]service.Module, error) {
		mod, err := newYARPCThriftModule(mi, hookup, options...)
		if err != nil {
			return nil, errors.Wrap(err, "unable to instantiate Thrift module")
		}

		return []service.Module{mod}, nil
	}
}

func newYARPCThriftModule(
	mi service.ModuleCreateInfo,
	createService CreateThriftServiceFunc,
	options ...modules.Option,
) (*YARPCModule, error) {
	registrants, err := createService(mi.Host)
	if err != nil {
		return nil, errors.Wrap(err, "unable to create YARPC thrift handler")
	}

	reg := func(mod *YARPCModule) {
		_setupMu.Lock()
		defer _setupMu.Unlock()
		Dispatcher().Register(registrants)
	}

	return newYARPCModule(mi, reg, options...)
}
<commit_msg>Default rpc name (#300)<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package rpc

import (
	"sync"

	"go.uber.org/fx/modules"
	"go.uber.org/fx/service"

	"github.com/pkg/errors"
	"go.uber.org/yarpc/api/transport"
)

var _setupMu sync.Mutex

// CreateThriftServiceFunc creates a Thrift service from a service host
type CreateThriftServiceFunc func(svc service.Host) ([]transport.Procedure, error)

// ThriftModule creates a Thrift Module from a service func
func ThriftModule(hookup CreateThriftServiceFunc, options ...modules.Option) service.ModuleCreateFunc {
	return func(mi service.ModuleCreateInfo) ([]service.Module, error) {
		if mi.Name == "" {
			mi.Name = "rpc"
		}

		mod, err := newYARPCThriftModule(mi, hookup, options...)
		if err != nil {
			return nil, errors.Wrap(err, "unable to instantiate Thrift module")
		}

		return []service.Module{mod}, nil
	}
}

func newYARPCThriftModule(
	mi service.ModuleCreateInfo,
	createService CreateThriftServiceFunc,
	options ...modules.Option,
) (*YARPCModule, error) {
	registrants, err := createService(mi.Host)
	if err != nil {
		return nil, errors.Wrap(err, "unable to create YARPC thrift handler")
	}

	reg := func(mod *YARPCModule) {
		_setupMu.Lock()
		defer _setupMu.Unlock()
		Dispatcher().Register(registrants)
	}

	return newYARPCModule(mi, reg, options...)
}
<|endoftext|>


<commit_before>package epochs

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"math/big"
	"time"
)

const secondsPerDay = 24 * 60 * 60
const nanosecondsPerDay = secondsPerDay * 1e9

// epoch2time gets a Unix time of the given x after dividing by q and
// adding s.
func epoch2time(x, q, s *big.Int) time.Time {
	z := new(big.Int)
	m := new(big.Int)
	z.DivMod(x, q, m)
	z.Add(z, s)
	r := m.Mul(m, big.NewInt(1e9)).Div(m, q)
	return time.Unix(z.Int64(), r.Int64()).UTC()
}

// time2epoch reverses epoch2time.
func time2epoch(t time.Time, m, s *big.Int) int64 {
	bf := new(big.Float).SetInt(big.NewInt(t.UnixNano()))
	bf.Quo(bf, big.NewFloat(1e9))
	bf.Sub(bf, new(big.Float).SetInt(s))
	bf.Mul(bf, new(big.Float).SetInt(m))

	r, acc := bf.Int64()
	if acc != big.Exact {
		fmt.Println(acc)
	}

	return r
}

// Chrome time is the number of microseconds since 1601-01-01, which
// is 11,644,473,600 seconds before the Unix epoch.
func Chrome(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}

// ToChrome returns the Chrome time for the given time.Time.
func ToChrome(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}

// Cocoa time is the number of seconds since 2001-01-01, which
// is 978,307,200 seconds after the Unix epoch.
func Cocoa(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1),
		big.NewInt(978307200),
	)
}

// ToCocoa returns the Cocoa time for the given time.Time.
func ToCocoa(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1),
		big.NewInt(978307200),
	)
}

// GoogleCalendar seems to count 32-day months from the day before the
// Unix epoch. @noppers worked out how to do this.
func GoogleCalendar(num int64) time.Time {

	n := int(num)

	totalDays := n / secondsPerDay
	seconds := n % secondsPerDay

	// A "Google month" has 32 days!
	months := totalDays / 32
	days := totalDays % 32

	// The "Google epoch" is apparently off by a day.
	t := time.Unix(-secondsPerDay, 0).UTC()

	// Add the days first...
	u := t.AddDate(0, 0, days)

	// ...then the months...
	v := u.AddDate(0, months, 0)

	// ...then the seconds.
	w := v.Add(time.Duration(seconds * 1e9))

	return w
}

// ToGoogleCalendar returns the GoogleCalendar time for the given time.Time.
func ToGoogleCalendar(t time.Time) int64 {
	y := t.Year() - 1970
	m := int(t.Month()) - 1
	r := ((((y*12+m)*32+t.Day())*24+t.Hour())*60+t.Minute())*60 + t.Second()
	return int64(r)
}

// ICQ time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part.
func ICQ(days float64) time.Time {

	t := time.Unix(-2209161600, 0).UTC()

	intdays := int(days)

	// Want the fractional part of the day in nanoseconds.
	fracday := int64((days - float64(intdays)) * nanosecondsPerDay)

	return t.AddDate(0, 0, intdays).Add(time.Duration(fracday))
}

// ToICQ returns the ICQ time for the given time.Time.
func ToICQ(t time.Time) float64 {
	t2 := time.Unix(-2209161600, 0)
	return float64(t.Sub(t2).Nanoseconds()) / float64(nanosecondsPerDay)
}

// Java time is the number of milliseconds since the Unix epoch.
func Java(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1000),
		big.NewInt(0),
	)
}

// ToJava returns the Java time for the given time.Time.
func ToJava(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1000),
		big.NewInt(0),
	)
}

// Mozilla time (e.g., formhistory.sqlite) is the number of
// microseconds since the Unix epoch.
func Mozilla(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(0),
	)
}

// ToMozilla returns the Mozilla time for the given time.Time.
func ToMozilla(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(0),
	)
}

// OLE time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part and is given as a string of hex characters
// representing an IEEE 8-byte floating-point number.
func OLE(days string) time.Time {
	var d [8]byte
	var f float64

	n, err := fmt.Sscanf(
		days,
		"%02x%02x%02x%02x%02x%02x%02x%02x",
		&d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7],
	)
	if err != nil {
		fmt.Println("fmt.Sscanf failed:", err)
	}
	if n != 8 {
		fmt.Println("fmt.Sscanf did not scan 8 items:", n)
	}

	buf := bytes.NewReader(d[:])
	if err := binary.Read(buf, binary.LittleEndian, &f); err != nil {
		fmt.Println("binary.Read failed:", err)
	}

	return ICQ(f)
}

// ToOLE returns the OLE time for the given time.Time.
func ToOLE(t time.Time) string {
	icq := ToICQ(t)
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.LittleEndian, math.Float64bits(icq))
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	return fmt.Sprintf("%016x", buf.Bytes())
}

// Symbian time is the number of microseconds since the year 0, which
// is 62,167,219,200 seconds before the Unix epoch.
func Symbian(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}

// ToSymbian returns the Symbian time for the given time.Time.
func ToSymbian(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}

// Unix time is the number of seconds since 1970-01-01.
func Unix(num int64) time.Time {
	return time.Unix(num, 0).UTC()
}

// ToUnix returns the Unix time for the given time.Time.
func ToUnix(t time.Time) int64 {
	return t.Unix()
}

// UUIDv1 time (RFC 4122) is the number of hectonanoseconds (100 ns)
// since 1582-10-15, which is 12,219,292,800 seconds before the Unix
// epoch.
func UUIDv1(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}

// ToUUIDv1 returns the UUIDv1 time for the given time.Time.
func ToUUIDv1(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}

// WindowsDate time (e.g., .NET) is the number of hectonanoseconds
// (100 ns) since 0001-01-01, which is 62,135,596,800 seconds before
// the Unix epoch.
func WindowsDate(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}

// ToWindowsDate returns the WindowsDate time for the given time.Time.
func ToWindowsDate(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}

// WindowsFile time (e.g., NTFS) is the number of hectonanoseconds
// (100 ns) since 1601-01-01, which is 11,644,473,600 seconds before
// the Unix epoch.
func WindowsFile(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}

// ToWindowsFile returns the WindowsFile time for the given time.Time.
func ToWindowsFile(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}
<commit_msg>spell it out<commit_after>package epochs

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"math/big"
	"time"
)

const secondsPerDay = 24 * 60 * 60
const nanosecondsPerDay = secondsPerDay * 1e9

// epoch2time gets a Unix time of the given x after dividing by q and
// adding s.
func epoch2time(x, q, s *big.Int) time.Time {
	z := new(big.Int)
	m := new(big.Int)
	z.DivMod(x, q, m)
	z.Add(z, s)
	r := m.Mul(m, big.NewInt(1e9)).Div(m, q)
	return time.Unix(z.Int64(), r.Int64()).UTC()
}

// time2epoch reverses epoch2time.
func time2epoch(t time.Time, m, s *big.Int) int64 {
	bf := new(big.Float).SetInt(big.NewInt(t.UnixNano()))
	bf.Quo(bf, big.NewFloat(1e9))
	bf.Sub(bf, new(big.Float).SetInt(s))
	bf.Mul(bf, new(big.Float).SetInt(m))

	r, acc := bf.Int64()
	if acc != big.Exact {
		fmt.Println(acc)
	}

	return r
}

// Chrome time is the number of microseconds since 1601-01-01, which
// is 11,644,473,600 seconds before the Unix epoch.
func Chrome(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}

// ToChrome returns the Chrome time for the given time.Time.
func ToChrome(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-11644473600),
	)
}

// Cocoa time is the number of seconds since 2001-01-01, which
// is 978,307,200 seconds after the Unix epoch.
func Cocoa(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1),
		big.NewInt(978307200),
	)
}

// ToCocoa returns the Cocoa time for the given time.Time.
func ToCocoa(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1),
		big.NewInt(978307200),
	)
}

// GoogleCalendar seems to count 32-day months from the day before the
// Unix epoch. @noppers worked out how to do this.
func GoogleCalendar(num int64) time.Time {

	n := int(num)

	totalDays := n / secondsPerDay
	seconds := n % secondsPerDay

	// A "Google month" has 32 days!
	months := totalDays / 32
	days := totalDays % 32

	// The "Google epoch" is apparently off by a day.
	t := time.Unix(-secondsPerDay, 0).UTC()

	// Add the days first...
	u := t.AddDate(0, 0, days)

	// ...then the months...
	v := u.AddDate(0, months, 0)

	// ...then the seconds.
	w := v.Add(time.Duration(seconds * 1e9))

	return w
}

// ToGoogleCalendar returns the GoogleCalendar time for the given time.Time.
func ToGoogleCalendar(t time.Time) int64 {
	y := t.Year() - 1970
	m := int(t.Month()) - 1
	r := ((((y*12+m)*32+t.Day())*24+t.Hour())*60+t.Minute())*60 + t.Second()
	return int64(r)
}

// ICQ time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part.
func ICQ(days float64) time.Time {

	t := time.Unix(-2209161600, 0).UTC()

	intdays := int(days)

	// Want the fractional part of the day in nanoseconds.
	fracday := int64((days - float64(intdays)) * nanosecondsPerDay)

	return t.AddDate(0, 0, intdays).Add(time.Duration(fracday))
}

// ToICQ returns the ICQ time for the given time.Time.
func ToICQ(t time.Time) float64 {
	t2 := time.Unix(-2209161600, 0)
	return float64(t.Sub(t2).Nanoseconds()) / float64(nanosecondsPerDay)
}

// Java time is the number of milliseconds since the Unix epoch.
func Java(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1000),
		big.NewInt(0),
	)
}

// ToJava returns the Java time for the given time.Time.
func ToJava(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1000),
		big.NewInt(0),
	)
}

// Mozilla time (e.g., formhistory.sqlite) is the number of
// microseconds since the Unix epoch.
func Mozilla(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(0),
	)
}

// ToMozilla returns the Mozilla time for the given time.Time.
func ToMozilla(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(0),
	)
}

// OLE time is the number of days since 1899-12-30, which is
// 2,209,161,600 seconds before the Unix epoch. Days can have a
// fractional part and is given as a string of hex characters
// representing an IEEE 8-byte floating-point number.
func OLE(days string) time.Time {
	var d [8]byte
	var f float64

	n, err := fmt.Sscanf(
		days,
		"%02x%02x%02x%02x%02x%02x%02x%02x",
		&d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7],
	)
	if err != nil {
		fmt.Println("fmt.Sscanf failed:", err)
	}
	if n != 8 {
		fmt.Println("fmt.Sscanf did not scan 8 items:", n)
	}

	buf := bytes.NewReader(d[:])
	if err := binary.Read(buf, binary.LittleEndian, &f); err != nil {
		fmt.Println("binary.Read failed:", err)
	}

	return ICQ(f)
}

// ToOLE returns the OLE time for the given time.Time.
func ToOLE(t time.Time) string {
	icq := ToICQ(t)
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.LittleEndian, math.Float64bits(icq))
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	return fmt.Sprintf("%016x", buf.Bytes())
}

// Symbian time is the number of microseconds since the year 0, which
// is 62,167,219,200 seconds before the Unix epoch.
func Symbian(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}

// ToSymbian returns the Symbian time for the given time.Time.
func ToSymbian(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e6),
		big.NewInt(-62167219200),
	)
}

// Unix time is the number of seconds since 1970-01-01.
func Unix(num int64) time.Time {
	return time.Unix(num, 0).UTC()
}

// ToUnix returns the Unix time for the given time.Time.
func ToUnix(t time.Time) int64 {
	return t.Unix()
}

// UUIDv1 time (RFC 4122) is the number of hectonanoseconds (100 ns)
// since 1582-10-15, which is 12,219,292,800 seconds before the Unix
// epoch.
func UUIDv1(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}

// ToUUIDv1 returns the UUID version 1 time for the given time.Time.
func ToUUIDv1(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-12219292800),
	)
}

// WindowsDate time (e.g., .NET) is the number of hectonanoseconds
// (100 ns) since 0001-01-01, which is 62,135,596,800 seconds before
// the Unix epoch.
func WindowsDate(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}

// ToWindowsDate returns the WindowsDate time for the given time.Time.
func ToWindowsDate(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-62135596800),
	)
}

// WindowsFile time (e.g., NTFS) is the number of hectonanoseconds
// (100 ns) since 1601-01-01, which is 11,644,473,600 seconds before
// the Unix epoch.
func WindowsFile(num int64) time.Time {
	return epoch2time(
		big.NewInt(num),
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}

// ToWindowsFile returns the WindowsFile time for the given time.Time.
func ToWindowsFile(t time.Time) int64 {
	return time2epoch(
		t,
		big.NewInt(1e7),
		big.NewInt(-11644473600),
	)
}
<|endoftext|>