// Copyright 2017-2022 The MathJax Consortium
// SPDX-License-Identifier: Apache-2.0
// This file is a Go translation and modification of MathJax 3.2.2 behavior.

// Package ordered provides deterministic insertion-ordered string maps. They // model the object-key and DOM-attribute ordering observable in MathJax 3.2.2.
package ordered import ( ) // Map is an insertion-ordered map with string keys. Updating a key preserves // its original position; deleting and reinserting it appends it at the end. // The zero value is ready for use. type Map[ any] struct { keys []string values map[string] } // New returns an initialized empty map. func [ any]() *Map[] { return &Map[]{values: make(map[string])} } func ( *Map[]) () { if .values == nil { .values = make(map[string]) } } // Len returns the number of entries. func ( *Map[]) () int { if == nil { return 0 } return len(.values) } // Has reports whether key is present. func ( *Map[]) ( string) bool { if == nil { return false } , := .values[] return } // Get returns the value and whether key is present. func ( *Map[]) ( string) (, bool) { var if == nil { return , false } , := .values[] return , } // Set inserts or updates key. func ( *Map[]) ( string, ) { .initialize() if , := .values[]; ! { .keys = append(.keys, ) } .values[] = } // Delete removes key and reports whether it was present. func ( *Map[]) ( string) bool { if == nil { return false } if , := .values[]; ! { return false } delete(.values, ) for , := range .keys { if == { copy(.keys[:], .keys[+1:]) .keys = .keys[:len(.keys)-1] break } } return true } // Keys returns a copy of the keys in insertion order. func ( *Map[]) () []string { if == nil { return nil } return append([]string(nil), .keys...) } // JavaScriptKeys returns keys in Object.keys order: canonical array indices // first in numeric order, then the remaining keys in insertion order. // Keys and Range retain insertion order for DOM attributes and other callers. func ( *Map[]) () []string { if == nil { return nil } := make([]string, 0, len(.keys)) := make([]string, 0, len(.keys)) for , := range .keys { , := strconv.ParseUint(, 10, 32) if == nil && < 1<<32-1 && strconv.FormatUint(, 10) == { = append(, ) } else { = append(, ) } } sort.Slice(, func(, int) bool { , := strconv.ParseUint([], 10, 32) , := strconv.ParseUint([], 10, 32) return < }) return append(, ...) } // Range calls yield in insertion order until it returns false. func ( *Map[]) ( func( string, ) bool) { if == nil { return } for , := range .keys { if !(, .values[]) { return } } } // Clone returns an independent shallow copy. func ( *Map[]) () *Map[] { := New[]() if == nil { return } .keys = append(.keys, .keys...) for , := range .values { .values[] = } return }