package middleware
import
type RelativePosition int
const (
After RelativePosition = iota
Before
)
type ider interface {
ID() string
}
type orderedIDs struct {
order *relativeOrder
items map[string]ider
}
const baseOrderedItems = 5
func () *orderedIDs {
return &orderedIDs{
order: newRelativeOrder(),
items: make(map[string]ider, baseOrderedItems),
}
}
func ( *orderedIDs) ( ider, RelativePosition) error {
:= .ID()
if len() == 0 {
return fmt.Errorf("empty ID, ID must not be empty")
}
if := .order.Add(, ); != nil {
return
}
.items[] =
return nil
}
func ( *orderedIDs) ( ider, string, RelativePosition) error {
if len(.ID()) == 0 {
return fmt.Errorf("insert ID must not be empty")
}
if len() == 0 {
return fmt.Errorf("relative to ID must not be empty")
}
if := .order.Insert(, , .ID()); != nil {
return
}
.items[.ID()] =
return nil
}
func ( *orderedIDs) ( string) (ider, bool) {
, := .items[]
return ,
}
func ( *orderedIDs) ( string, ider) (ider, error) {
if len() == 0 {
return nil, fmt.Errorf("swap from ID must not be empty")
}
:= .ID()
if len() == 0 {
return nil, fmt.Errorf("swap to ID must not be empty")
}
if := .order.Swap(, ); != nil {
return nil,
}
:= .items[]
delete(.items, )
.items[] =
return , nil
}
func ( *orderedIDs) ( string) (ider, error) {
if len() == 0 {
return nil, fmt.Errorf("remove ID must not be empty")
}
if := .order.Remove(); != nil {
return nil,
}
:= .items[]
delete(.items, )
return , nil
}
func ( *orderedIDs) () []string {
:= .order.List()
:= make([]string, len())
copy(, )
return
}
func ( *orderedIDs) () {
.order.Clear()
.items = map[string]ider{}
}
func ( *orderedIDs) () []interface{} {
:= .order.List()
:= make([]interface{}, len())
for := 0; < len(); ++ {
[] = .items[[]]
}
return
}
type relativeOrder struct {
order []string
}
func () *relativeOrder {
return &relativeOrder{
order: make([]string, 0, baseOrderedItems),
}
}
func ( *relativeOrder) ( RelativePosition, ...string) error {
if len() == 0 {
return nil
}
for , := range {
if , := .has(); {
return fmt.Errorf("already exists, %v", )
}
}
switch {
case Before:
return .insert(0, Before, ...)
case After:
.order = append(.order, ...)
default:
return fmt.Errorf("invalid position, %v", int())
}
return nil
}
func ( *relativeOrder) ( string, RelativePosition, ...string) error {
if len() == 0 {
return nil
}
for , := range {
if , := .has(); {
return fmt.Errorf("already exists, %v", )
}
}
, := .has()
if ! {
return fmt.Errorf("not found, %v", )
}
return .insert(, , ...)
}
func ( *relativeOrder) (, string) error {
, := .has()
if ! {
return fmt.Errorf("not found, %v", )
}
if _, = .has(); && != {
return fmt.Errorf("already exists, %v", )
}
.order[] =
return nil
}
func ( *relativeOrder) ( string) error {
, := .has()
if ! {
return fmt.Errorf("not found, %v", )
}
.order = append(.order[:], .order[+1:]...)
return nil
}
func ( *relativeOrder) () []string {
return .order
}
func ( *relativeOrder) () {
.order = .order[0:0]
}
func ( *relativeOrder) ( int, RelativePosition, ...string) error {
switch {
case Before:
:= len()
var []string
if <= cap(.order)-len(.order) {
.order = .order[:len(.order)+]
= .order
} else {
= .order
.order = make([]string, len(.order)+)
copy(.order[:], [:])
}
copy(.order[+:], [:])
copy(.order[:], )
case After:
if == len(.order)-1 || len(.order) == 0 {
.order = append(.order, ...)
} else {
.order = append(.order[:+1], append(, .order[+1:]...)...)
}
default:
return fmt.Errorf("invalid position, %v", int())
}
return nil
}
func ( *relativeOrder) ( string) ( int, bool) {
for := 0; < len(.order); ++ {
if .order[] == {
return , true
}
}
return 0, false
}