util

package
v2.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2023 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnmarshalJSON = errors.New("unmarshalling JSON failed")
	ErrTooLargeJSON  = errors.New("too large JSON")
)

Errors for UnmarshalJSON and UnmarshalJSONWithLimit functions

View Source
var ErrLimitReached = errors.New("limit reached")

ErrLimitReached is the error returned by the Limiter and LimitWriter when the predefined limit has been reached

Functions

func BasicAuth

func BasicAuth(user, pass string) string

BasicAuth encodes the Authorization header value for basic auth

func BearerAuth

func BearerAuth(token string) string

BearerAuth encodes the Authorization header value for a bearer/token auth

func Contains

func Contains[T comparable](haystack []T, needle T) bool

Contains returns true if needle is contained in haystack

func ContainsAll

func ContainsAll[T comparable](haystack []T, needles []T) bool

ContainsAll returns true if all needles are contained in haystack

func ContainsIP

func ContainsIP(haystack []netip.Prefix, needle netip.Addr) bool

ContainsIP returns true if any one of the of prefixes contains the ip.

func DetectContentType

func DetectContentType(b []byte, filename string) (mimeType string, ext string)

DetectContentType probes the byte array b and returns mime type and file extension. The filename is only used to override certain special cases.

func FileExists

func FileExists(filename string) bool

FileExists checks if a file exists, and returns true if it does

func FormatSize

func FormatSize(b int64) string

FormatSize formats bytes into a human-readable notation, e.g. 2.1 MB

func FormatTime

func FormatTime(t time.Time) string

FormatTime formats a time.Time in a RFC339-like format that includes milliseconds

func Gzip

func Gzip(next http.Handler) http.Handler

Gzip is a HTTP middleware to transparently compress responses using gzip. Original code from https://gist.github.com/CJEnright/bc2d8b8dc0c1389a9feeddb110f822d7 (MIT)

func Int

func Int(v int) *int

Int turns an int into a pointer of an int

func LastString

func LastString(s []string, def string) string

LastString returns the last string in a slice, or def if s is empty

func Max

func Max[T int | int64 | rate.Limit](a, b T) T

Max returns the maximum value of the two given values

func MaybeMarshalJSON

func MaybeMarshalJSON(v any) string

MaybeMarshalJSON returns a JSON string of the given object, or "<cannot serialize>" if serialization failed. This is useful for logging purposes where a failure doesn't matter that much.

func MinMax

func MinMax[T int | int64](value, min, max T) T

MinMax returns value if it is between min and max, or either min or max if it is out of range

func NextOccurrenceUTC

func NextOccurrenceUTC(timeOfDay, base time.Time) time.Time

NextOccurrenceUTC takes a time of day (e.g. 9:00am), and returns the next occurrence of that time from the current time (in UTC).

func ParseDuration

func ParseDuration(s string) (time.Duration, error)

ParseDuration is like time.ParseDuration, except that it also understands days (d), which translates to 24 hours, e.g. "2d" or "20h".

func ParseFutureTime

func ParseFutureTime(s string, now time.Time) (time.Time, error)

ParseFutureTime parses a date/time string to a time.Time. It supports unix timestamps, durations and natural language dates

func ParsePriority

func ParsePriority(priority string) (int, error)

ParsePriority parses a priority string into its equivalent integer value

func ParseSize

func ParseSize(s string) (int64, error)

ParseSize parses a size string like 2K or 2M into bytes. If no unit is found, e.g. 123, bytes is assumed.

func PriorityString

func PriorityString(priority int) (string, error)

PriorityString converts a priority number to a string

func QuoteCommand

func QuoteCommand(command []string) string

QuoteCommand combines a command array to a string, quoting arguments that need quoting. This function is naive, and sometimes wrong. It is only meant for lo pretty-printing a command.

Warning: Never use this function with the intent to run the resulting command.

Example:

[]string{"ls", "-al", "Document Folder"} -> ls -al "Document Folder"

func RandomLowerStringPrefix

func RandomLowerStringPrefix(prefix string, length int) string

RandomLowerStringPrefix returns a random lowercase-only string with a given length, with a prefix

func RandomString

func RandomString(length int) string

RandomString returns a random string with a given length

func RandomStringPrefix

func RandomStringPrefix(prefix string, length int) string

RandomStringPrefix returns a random string with a given length, with a prefix

func ReadPassword

func ReadPassword(in io.Reader) ([]byte, error)

ReadPassword will read a password from STDIN. If the terminal supports it, it will not print the input characters to the screen. If not, it'll just read using normal readline semantics (useful for testing).

func Retry

func Retry[T any](f func() (*T, error), after ...time.Duration) (t *T, err error)

Retry executes function f until if succeeds, and then returns t. If f fails, it sleeps and tries again. The sleep durations are passed as the after params.

func ShortTopicURL

func ShortTopicURL(s string) string

ShortTopicURL shortens the topic URL to be human-friendly, removing the http:// or https://

func SplitKV

func SplitKV(s string, sep string) (key string, value string)

SplitKV splits a string into a key/value pair using a separator, and trimming space. If the separator is not found, key is empty.

func SplitNoEmpty

func SplitNoEmpty(s string, sep string) []string

SplitNoEmpty splits a string using strings.Split, but filters out empty strings

func String

func String(v string) *string

String turns a string into a pointer of a string

func Time

func Time(v time.Time) *time.Time

Time turns a time.Time into a pointer

func UnmarshalJSON

func UnmarshalJSON[T any](body io.ReadCloser) (*T, error)

UnmarshalJSON reads the given io.ReadCloser into a struct

func UnmarshalJSONWithLimit

func UnmarshalJSONWithLimit[T any](r io.ReadCloser, limit int, allowEmpty bool) (*T, error)

UnmarshalJSONWithLimit reads the given io.ReadCloser into a struct, but only until limit is reached

func ValidRandomString

func ValidRandomString(s string, length int) bool

ValidRandomString returns true if the given string matches the format created by RandomString

Types

type BatchingQueue

type BatchingQueue[T any] struct {
	// contains filtered or unexported fields
}

BatchingQueue is a queue that creates batches of the enqueued elements based on a max batch size and a batch timeout.

Example:

q := NewBatchingQueue[int](2, 500 * time.Millisecond)
go func() {
  for batch := range q.Dequeue() {
    fmt.Println(batch)
  }
}()
q.Enqueue(1)
q.Enqueue(2)
q.Enqueue(3)
time.Sleep(time.Second)

This example will emit batch [1, 2] immediately (because the batch size is 2), and a batch [3] after 500ms.

func NewBatchingQueue

func NewBatchingQueue[T any](batchSize int, timeout time.Duration) *BatchingQueue[T]

NewBatchingQueue creates a new BatchingQueue

func (*BatchingQueue[T]) Dequeue

func (q *BatchingQueue[T]) Dequeue() <-chan []T

Dequeue returns a channel emitting batches of elements

func (*BatchingQueue[T]) Enqueue

func (q *BatchingQueue[T]) Enqueue(element T)

Enqueue enqueues an element to the queue. If the configured batch size is reached, the batch will be emitted immediately.

type CachingEmbedFS

type CachingEmbedFS struct {
	ModTime time.Time
	FS      embed.FS
}

CachingEmbedFS is a wrapper around embed.FS that allows setting a ModTime, so that the default static file server can send 304s back. It can be used like this:

  var (
     //go:embed docs
     docsStaticFs     embed.FS
     docsStaticCached = &util.CachingEmbedFS{ModTime: time.Now(), FS: docsStaticFs}
  )

	 http.FileServer(http.FS(docsStaticCached)).ServeHTTP(w, r)

func (CachingEmbedFS) Open

func (f CachingEmbedFS) Open(name string) (fs.File, error)

Open opens a file in the embedded filesystem and returns a fs.File with the static ModTime

type ContentTypeWriter

type ContentTypeWriter struct {
	// contains filtered or unexported fields
}

ContentTypeWriter is an implementation of http.ResponseWriter that will detect the content type and set the Content-Type and (optionally) Content-Disposition headers accordingly.

It will always set a Content-Type based on http.DetectContentType, but will never send the "text/html" content type.

func NewContentTypeWriter

func NewContentTypeWriter(w http.ResponseWriter, filename string) *ContentTypeWriter

NewContentTypeWriter creates a new ContentTypeWriter

func (*ContentTypeWriter) Write

func (w *ContentTypeWriter) Write(p []byte) (n int, err error)

type FixedLimiter

type FixedLimiter struct {
	// contains filtered or unexported fields
}

FixedLimiter is a helper that allows adding values up to a well-defined limit. Once the limit is reached ErrLimitReached will be returned. FixedLimiter may be used by multiple goroutines.

func NewFixedLimiter

func NewFixedLimiter(limit int64) *FixedLimiter

NewFixedLimiter creates a new Limiter

func NewFixedLimiterWithValue

func NewFixedLimiterWithValue(limit, value int64) *FixedLimiter

NewFixedLimiterWithValue creates a new Limiter and sets the initial value

func (*FixedLimiter) Allow

func (l *FixedLimiter) Allow() bool

Allow adds one to the limiters internal value, but only if the limit has not been reached. If the limit was exceeded, false is returned.

func (*FixedLimiter) AllowN

func (l *FixedLimiter) AllowN(n int64) bool

AllowN adds n to the limiters internal value, but only if the limit has not been reached. If the limit was exceeded after adding n, false is returned.

func (*FixedLimiter) Reset

func (l *FixedLimiter) Reset()

Reset sets the limiter's value back to zero

func (*FixedLimiter) Value

func (l *FixedLimiter) Value() int64

Value returns the current limiter value

type LimitWriter

type LimitWriter struct {
	// contains filtered or unexported fields
}

LimitWriter implements an io.Writer that will pass through all Write calls to the underlying writer w until any of the limiter's limit is reached, at which point a Write will return ErrLimitReached. Each limiter's value is increased with every write.

func NewLimitWriter

func NewLimitWriter(w io.Writer, limiters ...Limiter) *LimitWriter

NewLimitWriter creates a new LimitWriter

func (*LimitWriter) Write

func (w *LimitWriter) Write(p []byte) (n int, err error)

Write passes through all writes to the underlying writer until any of the given limiter's limit is reached

type Limiter

type Limiter interface {
	// Allow adds one to the limiters value, or returns false if the limit has been reached
	Allow() bool

	// AllowN adds n to the limiters value, or returns false if the limit has been reached
	AllowN(n int64) bool

	// Value returns the current internal limiter value
	Value() int64

	// Reset resets the state of the limiter
	Reset()
}

Limiter is an interface that implements a rate limiting mechanism, e.g. based on time or a fixed value

type LookupCache

type LookupCache[T any] struct {
	// contains filtered or unexported fields
}

LookupCache is a single-value cache with a time-to-live (TTL). The cache has a lookup function to retrieve the value and stores it until TTL is reached.

Example:

lookup := func() (string, error) {
   r, _ := http.Get("...")
   s, _ := io.ReadAll(r.Body)
   return string(s), nil
}
c := NewLookupCache[string](lookup, time.Hour)
fmt.Println(c.Get()) // Fetches the string via HTTP
fmt.Println(c.Get()) // Uses cached value

func NewLookupCache

func NewLookupCache[T any](lookup LookupFunc[T], ttl time.Duration) *LookupCache[T]

NewLookupCache creates a new LookupCache with a given time-to-live (TTL)

func (*LookupCache[T]) Value

func (c *LookupCache[T]) Value() (T, error)

Value returns the cached value, or retrieves it via the lookup function

type LookupFunc

type LookupFunc[T any] func() (T, error)

LookupFunc is a function that is called by the LookupCache if the underlying value is out-of-date. It returns the new value, or an error.

type PeekedReadCloser

type PeekedReadCloser struct {
	PeekedBytes  []byte
	LimitReached bool
	// contains filtered or unexported fields
}

PeekedReadCloser is a ReadCloser that allows peeking into a stream and buffering it in memory. It can be instantiated using the Peek function. After a stream has been peeked, it can still be fully read by reading the PeekedReadCloser. It first drained from the memory buffer, and then from the remaining underlying reader.

func Peek

func Peek(underlying io.ReadCloser, limit int) (*PeekedReadCloser, error)

Peek reads the underlying ReadCloser into memory up until the limit and returns a PeekedReadCloser. It does not return an error if limit is reached. Instead, LimitReached will be set to true.

func (*PeekedReadCloser) Close

func (r *PeekedReadCloser) Close() error

Close closes the underlying stream

func (*PeekedReadCloser) Read

func (r *PeekedReadCloser) Read(p []byte) (n int, err error)

Read reads from the peeked bytes and then from the underlying stream

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter is a Limiter that wraps a rate.Limiter, allowing a floating time-based limit.

func NewBytesLimiter

func NewBytesLimiter(bytes int, interval time.Duration) *RateLimiter

NewBytesLimiter creates a RateLimiter that is meant to be used for a bytes-per-interval limit, e.g. 250 MB per day. And example of the underlying idea can be found here: https://go.dev/play/p/0ljgzIZQ6dJ

func NewRateLimiter

func NewRateLimiter(r rate.Limit, b int) *RateLimiter

NewRateLimiter creates a new RateLimiter

func NewRateLimiterWithValue

func NewRateLimiterWithValue(r rate.Limit, b int, value int64) *RateLimiter

NewRateLimiterWithValue creates a new RateLimiter with the given starting value.

Note that the starting value only has informational value. It does not impact the underlying value of the rate.Limiter.

func (*RateLimiter) Allow

func (l *RateLimiter) Allow() bool

Allow adds one to the limiters internal value, but only if the limit has not been reached. If the limit was exceeded, false is returned.

func (*RateLimiter) AllowN

func (l *RateLimiter) AllowN(n int64) bool

AllowN adds n to the limiters internal value, but only if the limit has not been reached. If the limit was exceeded after adding n, false is returned.

func (*RateLimiter) Reset

func (l *RateLimiter) Reset()

Reset sets the limiter's value back to zero, and resets the underlying rate.Limiter

func (*RateLimiter) Value

func (l *RateLimiter) Value() int64

Value returns the current limiter value

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL