feat: documentation
This commit is contained in:
235
.golangci.yml
Normal file
235
.golangci.yml
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
---
|
||||||
|
# golangci-lint configuration file made by @ccoVeille
|
||||||
|
# Source: https://github.com/ccoVeille/golangci-lint-config-examples/
|
||||||
|
# Author: @ccoVeille
|
||||||
|
# License: MIT
|
||||||
|
# Variant: 03-safe
|
||||||
|
# Version: v2.0.0
|
||||||
|
#
|
||||||
|
version: "2"
|
||||||
|
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
# format the code
|
||||||
|
- gofmt
|
||||||
|
# format the block of imports
|
||||||
|
- gci
|
||||||
|
|
||||||
|
settings:
|
||||||
|
# format the code with Go standard library
|
||||||
|
gofmt:
|
||||||
|
# simplify the code
|
||||||
|
# https://pkg.go.dev/cmd/gofmt#hdr-The_simplify_command
|
||||||
|
simplify: true
|
||||||
|
rewrite-rules:
|
||||||
|
# replace `interface{}` with `any` in the code on format
|
||||||
|
- pattern: 'interface{}'
|
||||||
|
replacement: 'any'
|
||||||
|
|
||||||
|
# make sure imports are always in a deterministic order
|
||||||
|
# https://github.com/daixiang0/gci/
|
||||||
|
gci: # define the section orders for imports
|
||||||
|
sections:
|
||||||
|
# Standard section: captures all standard packages.
|
||||||
|
- standard
|
||||||
|
# Default section: catchall that is not standard or custom
|
||||||
|
- default
|
||||||
|
# linters that related to local tool, so they should be separated
|
||||||
|
- localmodule
|
||||||
|
|
||||||
|
linters:
|
||||||
|
exclusions:
|
||||||
|
# these presets where present in the v1 version of golangci-lint
|
||||||
|
# it's interesting to keep them when migrating, but removing them should be the goal
|
||||||
|
presets:
|
||||||
|
# exclude check on comments format in godoc
|
||||||
|
# These are common false positives in poor code
|
||||||
|
# you should not use this on recent code you write from scratch
|
||||||
|
# More information: https://golangci-lint.run/usage/false-positives/#comments
|
||||||
|
#
|
||||||
|
# Please uncomment the following line if your code is not using the godoc format
|
||||||
|
# - comments
|
||||||
|
|
||||||
|
# Common false positives
|
||||||
|
# feel free to remove this if you don't have any false positives
|
||||||
|
# More information: https://golangci-lint.run/usage/false-positives/#common-false-positives
|
||||||
|
- common-false-positives
|
||||||
|
|
||||||
|
# Legacy preset is not recommended anymore
|
||||||
|
# More information: https://golangci-lint.run/usage/false-positives/#legacy
|
||||||
|
- legacy
|
||||||
|
|
||||||
|
# std-error-handling is a set of rules that avoid reporting unhandled errors on common functions/methods
|
||||||
|
# More information: https://golangci-lint.run/usage/false-positives/#std-error-handling
|
||||||
|
- std-error-handling
|
||||||
|
|
||||||
|
# some linters are enabled by default
|
||||||
|
# https://golangci-lint.run/usage/linters/
|
||||||
|
#
|
||||||
|
# enable some extra linters
|
||||||
|
enable:
|
||||||
|
# Errcheck is a program for checking for unchecked errors in Go code.
|
||||||
|
- errcheck
|
||||||
|
|
||||||
|
# Vet examines Go source code and reports suspicious constructs.
|
||||||
|
- govet
|
||||||
|
|
||||||
|
# Detects when assignments to existing variables are not used.
|
||||||
|
- ineffassign
|
||||||
|
|
||||||
|
# It's a set of rules from staticcheck. See https://staticcheck.io/
|
||||||
|
- staticcheck
|
||||||
|
|
||||||
|
# Checks Go code for unused constants, variables, functions and types.
|
||||||
|
- unused
|
||||||
|
|
||||||
|
# Fast, configurable, extensible, flexible, and beautiful linter for Go.
|
||||||
|
# Drop-in replacement of golint.
|
||||||
|
- revive
|
||||||
|
|
||||||
|
# make sure to use t.Helper() when needed
|
||||||
|
- thelper
|
||||||
|
|
||||||
|
# mirror suggests rewrites to avoid unnecessary []byte/string conversion
|
||||||
|
- mirror
|
||||||
|
|
||||||
|
# detect the possibility to use variables/constants from the Go standard library.
|
||||||
|
- usestdlibvars
|
||||||
|
|
||||||
|
# Finds commonly misspelled English words.
|
||||||
|
- misspell
|
||||||
|
|
||||||
|
# Checks for duplicate words in the source code.
|
||||||
|
- dupword
|
||||||
|
|
||||||
|
# linter to detect errors invalid key values count
|
||||||
|
- loggercheck
|
||||||
|
|
||||||
|
# detect when a package or method could be replaced by one from the standard library
|
||||||
|
- exptostd
|
||||||
|
|
||||||
|
# detects nested contexts in loops or function literals
|
||||||
|
- fatcontext
|
||||||
|
|
||||||
|
# Reports uses of functions with replacement inside the testing package.
|
||||||
|
- usetesting
|
||||||
|
|
||||||
|
settings:
|
||||||
|
revive:
|
||||||
|
rules:
|
||||||
|
# these are the default revive rules
|
||||||
|
# you can remove the whole "rules" node if you want
|
||||||
|
# BUT
|
||||||
|
# ! /!\ they all need to be present when you want to add more rules than the default ones
|
||||||
|
# otherwise, you won't have the default rules, but only the ones you define in the "rules" node
|
||||||
|
|
||||||
|
# Blank import should be only in a main or test package, or have a comment justifying it.
|
||||||
|
- name: blank-imports
|
||||||
|
|
||||||
|
# Packages should have comments of the form "Package x ...".
|
||||||
|
- name: package-comments
|
||||||
|
|
||||||
|
# context.Context() should be the first parameter of a function when provided as argument.
|
||||||
|
- name: context-as-argument
|
||||||
|
arguments:
|
||||||
|
- allowTypesBefore: "*testing.T"
|
||||||
|
|
||||||
|
# Basic types should not be used as a key in `context.WithValue`
|
||||||
|
- name: context-keys-type
|
||||||
|
|
||||||
|
# Importing with `.` makes the programs much harder to understand
|
||||||
|
- name: dot-imports
|
||||||
|
|
||||||
|
# Empty blocks make code less readable and could be a symptom of a bug or unfinished refactoring.
|
||||||
|
- name: empty-block
|
||||||
|
|
||||||
|
# for better readability, variables of type `error` must be named with the prefix `err`.
|
||||||
|
- name: error-naming
|
||||||
|
|
||||||
|
# for better readability, the errors should be last in the list of returned values by a function.
|
||||||
|
- name: error-return
|
||||||
|
|
||||||
|
# for better readability, error messages should not be capitalized or end with punctuation or a newline.
|
||||||
|
- name: error-strings
|
||||||
|
|
||||||
|
# report when replacing `errors.New(fmt.Sprintf())` with `fmt.Errorf()` is possible
|
||||||
|
- name: errorf
|
||||||
|
|
||||||
|
# check naming and commenting conventions on exported symbols.
|
||||||
|
- name: exported
|
||||||
|
arguments:
|
||||||
|
# make error messages clearer
|
||||||
|
- "sayRepetitiveInsteadOfStutters"
|
||||||
|
# require comments on public interface methods
|
||||||
|
- "checkPublicInterface"
|
||||||
|
|
||||||
|
# incrementing an integer variable by 1 is recommended to be done using the `++` operator
|
||||||
|
- name: increment-decrement
|
||||||
|
|
||||||
|
# highlights redundant else-blocks that can be eliminated from the code
|
||||||
|
# - name: indent-error-flow
|
||||||
|
|
||||||
|
# This rule suggests a shorter way of writing ranges that do not use the second value.
|
||||||
|
- name: range
|
||||||
|
|
||||||
|
# receiver names in a method should reflect the struct name (p for Person, for example)
|
||||||
|
- name: receiver-naming
|
||||||
|
|
||||||
|
# redefining built in names (true, false, append, make) can lead to bugs very difficult to detect.
|
||||||
|
- name: redefines-builtin-id
|
||||||
|
|
||||||
|
# redundant else-blocks that can be eliminated from the code.
|
||||||
|
# - name: superfluous-else
|
||||||
|
|
||||||
|
# prevent confusing name for variables when using `time` package
|
||||||
|
- name: time-naming
|
||||||
|
|
||||||
|
# warns when an exported function or method returns a value of an un-exported type.
|
||||||
|
- name: unexported-return
|
||||||
|
|
||||||
|
# spots and proposes to remove unreachable code. also helps to spot errors
|
||||||
|
- name: unreachable-code
|
||||||
|
|
||||||
|
# Functions or methods with unused parameters can be a symptom of an unfinished refactoring or a bug.
|
||||||
|
- name: unused-parameter
|
||||||
|
|
||||||
|
# report when a variable declaration can be simplified
|
||||||
|
- name: var-declaration
|
||||||
|
|
||||||
|
# warns when initialism, variable or package naming conventions are not followed.
|
||||||
|
- name: var-naming
|
||||||
|
|
||||||
|
misspell:
|
||||||
|
# Correct spellings using locale preferences for US or UK.
|
||||||
|
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||||
|
# Default ("") is to use a neutral variety of English.
|
||||||
|
locale: US
|
||||||
|
|
||||||
|
# List of words to ignore
|
||||||
|
# among the one defined in https://github.com/golangci/misspell/blob/master/words.go
|
||||||
|
ignore-rules: []
|
||||||
|
# - valor
|
||||||
|
# - and
|
||||||
|
|
||||||
|
# Extra word corrections.
|
||||||
|
extra-words: []
|
||||||
|
# - typo: "whattever"
|
||||||
|
# correction: "whatever"
|
||||||
|
|
||||||
|
output:
|
||||||
|
# Order to use when sorting results.
|
||||||
|
# Possible values: `file`, `linter`, and `severity`.
|
||||||
|
#
|
||||||
|
# If the severity values are inside the following list, they are ordered in this order:
|
||||||
|
# 1. error
|
||||||
|
# 2. warning
|
||||||
|
# 3. high
|
||||||
|
# 4. medium
|
||||||
|
# 5. low
|
||||||
|
# Either they are sorted alphabetically.
|
||||||
|
#
|
||||||
|
# Default: ["file"]
|
||||||
|
sort-order:
|
||||||
|
- linter
|
||||||
|
- severity
|
||||||
|
- file # filepath, line, and column.
|
||||||
2
doc.go
Normal file
2
doc.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package ring implements a generic deque using a circular buffer.
|
||||||
|
package ring
|
||||||
11
options.go
11
options.go
@@ -2,17 +2,26 @@ package ring
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
// DefaultGrowthFactor is the default multiplier a [Ring] uses to increase its
|
||||||
|
// capacity. Most implementations use 2.
|
||||||
const DefaultGrowthFactor = 2
|
const DefaultGrowthFactor = 2
|
||||||
|
|
||||||
|
// DefaultCapacity is the default starting capacity of a new [Ring]. Sixteen was
|
||||||
|
// chosen as a reasonable default.
|
||||||
const DefaultCapacity = 16
|
const DefaultCapacity = 16
|
||||||
|
|
||||||
|
// A config holds all values that modify the behavior of a [Ring].
|
||||||
type config struct {
|
type config struct {
|
||||||
capacity uint64
|
capacity uint64
|
||||||
growthFactor uint64
|
growthFactor uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An Option can be used with [New] to modify the behavior of a [Ring].
|
||||||
type Option func(*config)
|
type Option func(*config)
|
||||||
|
|
||||||
|
// GrowthFactor modifies the multiplier used to increase (and decrease) the
|
||||||
|
// capacity of a [Ring].
|
||||||
|
// Its value must be greater than 1.
|
||||||
func GrowthFactor(value int) Option {
|
func GrowthFactor(value int) Option {
|
||||||
if value <= 1 {
|
if value <= 1 {
|
||||||
panic(fmt.Errorf("go-ring: growth factor must be greater than 1, got %d", value))
|
panic(fmt.Errorf("go-ring: growth factor must be greater than 1, got %d", value))
|
||||||
@@ -23,6 +32,8 @@ func GrowthFactor(value int) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capacity modifies the starting capacity of a [Ring].
|
||||||
|
// Its value must be non-negative.
|
||||||
func Capacity(value int) Option {
|
func Capacity(value int) Option {
|
||||||
if value < 0 {
|
if value < 0 {
|
||||||
panic(fmt.Errorf("go-ring: starting capacity must be non-negative, got %d", value))
|
panic(fmt.Errorf("go-ring: starting capacity must be non-negative, got %d", value))
|
||||||
|
|||||||
27
ring.go
27
ring.go
@@ -12,16 +12,18 @@ type Ring[T any] struct {
|
|||||||
offset uint64 // Is not greater than 'size'.
|
offset uint64 // Is not greater than 'size'.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cap returns the capacity of 'r'.
|
||||||
func (r Ring[T]) Cap() int {
|
func (r Ring[T]) Cap() int {
|
||||||
return len(r.data)
|
return len(r.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Len returns the number of values in 'r'.
|
||||||
func (r Ring[T]) Len() int {
|
func (r Ring[T]) Len() int {
|
||||||
return int(r.size)
|
return int(r.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch returns the value of a certain index. The index MUST NOT be out of
|
// fetch returns the value of a certain index.
|
||||||
// range.
|
// The index MUST NOT be out of range.
|
||||||
func (r Ring[T]) fetch(index uint64) T {
|
func (r Ring[T]) fetch(index uint64) T {
|
||||||
if index >= r.size {
|
if index >= r.size {
|
||||||
panic("Out of range!")
|
panic("Out of range!")
|
||||||
@@ -30,20 +32,26 @@ func (r Ring[T]) fetch(index uint64) T {
|
|||||||
return r.data[(r.offset+index)%r.size]
|
return r.data[(r.offset+index)%r.size]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns the value at a certain 'index' in 'r'.
|
||||||
|
// The index must be within the range of the ring.
|
||||||
func (r Ring[T]) Get(index int) T {
|
func (r Ring[T]) Get(index int) T {
|
||||||
return r.fetch(uint64(index))
|
return r.fetch(uint64(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Front returns the first value in 'r'.
|
||||||
|
// The ring must not be empty.
|
||||||
func (r Ring[T]) Front() T {
|
func (r Ring[T]) Front() T {
|
||||||
return r.fetch(0)
|
return r.fetch(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Back returns the last value in 'r'.
|
||||||
|
// The ring must not be empty.
|
||||||
func (r Ring[T]) Back() T {
|
func (r Ring[T]) Back() T {
|
||||||
return r.fetch(r.size - 1)
|
return r.fetch(r.size - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resize replaces the current data table with a new table a new 'capacity'. The
|
// resize replaces the current data table with a new table a new 'capacity'.
|
||||||
// new capacity MUST NOT be less than [Ring.Len].
|
// The new capacity must not be less than [Ring.Len].
|
||||||
func (r *Ring[T]) resize(capacity uint64) {
|
func (r *Ring[T]) resize(capacity uint64) {
|
||||||
if capacity < r.size {
|
if capacity < r.size {
|
||||||
panic("Resize too small!")
|
panic("Resize too small!")
|
||||||
@@ -58,8 +66,8 @@ func (r *Ring[T]) resize(capacity uint64) {
|
|||||||
r.data = newData
|
r.data = newData
|
||||||
}
|
}
|
||||||
|
|
||||||
// grow increases the size of the array by its growth factor. It is guaranteed
|
// grow increases the size of the array by its growth factor.
|
||||||
// to not be [Ring.full].
|
// It is guaranteed to not be [Ring.full].
|
||||||
func (r *Ring[T]) grow() {
|
func (r *Ring[T]) grow() {
|
||||||
if r.size == 0 {
|
if r.size == 0 {
|
||||||
r.resize(1)
|
r.resize(1)
|
||||||
@@ -73,8 +81,8 @@ func (r Ring[T]) full() bool {
|
|||||||
return r.size == uint64(len(r.data))
|
return r.size == uint64(len(r.data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// shrink decreases the size of the data table by its growth factor. Do not call
|
// shrink decreases the capacity of 'r' by its growth factor.
|
||||||
// this when the data table is not [Ring.sparse].
|
// The ring must be [Ring.sparse].
|
||||||
func (r *Ring[T]) shrink() {
|
func (r *Ring[T]) shrink() {
|
||||||
r.resize(r.size / r.growthFactor)
|
r.resize(r.size / r.growthFactor)
|
||||||
}
|
}
|
||||||
@@ -84,7 +92,8 @@ func (r *Ring[T]) sparse() bool {
|
|||||||
return r.size*r.growthFactor < uint64(len(r.data))
|
return r.size*r.growthFactor < uint64(len(r.data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// set updates the value of a certain index. The index MUST be in range.
|
// set updates the value of a certain index.
|
||||||
|
// The index must be in range.
|
||||||
func (r Ring[T]) set(index uint64, value T) {
|
func (r Ring[T]) set(index uint64, value T) {
|
||||||
if index >= r.size {
|
if index >= r.size {
|
||||||
panic("Out of range!")
|
panic("Out of range!")
|
||||||
|
|||||||
Reference in New Issue
Block a user