PIN (Piece Identifier Notation) implementation for Go.
This library implements the PIN Specification v1.0.0.
go get github.com/sashite/pin.go/v3Convert a PIN string into an Identifier struct.
package main
import (
"fmt"
"github.com/sashite/pin.go/v3"
)
func main() {
// Standard parsing (returns error)
id, err := pin.Parse("K")
if err != nil {
panic(err)
}
fmt.Println(id.Abbr()) // K
fmt.Println(id.Side()) // First
fmt.Println(id.State()) // Normal
fmt.Println(id.IsTerminal()) // false
// With state modifier
id, _ = pin.Parse("+R")
fmt.Println(id.State()) // Enhanced
// With terminal marker
id, _ = pin.Parse("K^")
fmt.Println(id.IsTerminal()) // true
// Panic on error (for constants or trusted input)
k := pin.MustParse("+K^")
fmt.Println(k.String()) // +K^
}Convert an Identifier back to a PIN string.
// From Identifier
id := pin.NewIdentifier('K', pin.First)
fmt.Println(id.String()) // "K"
// With attributes
id = pin.NewIdentifierWithOptions('R', pin.Second, pin.Enhanced, false)
fmt.Println(id.String()) // "+r"
id = pin.NewIdentifierWithOptions('K', pin.First, pin.Normal, true)
fmt.Println(id.String()) // "K^"// Boolean check
if pin.IsValid("K") {
// valid identifier
}
// Detailed error
if err := pin.Validate("+K^"); err != nil {
fmt.Println(err)
}All transformations return new immutable values.
id := pin.MustParse("K")
// State transformations
fmt.Println(id.Enhance().String()) // "+K"
fmt.Println(id.Diminish().String()) // "-K"
fmt.Println(id.Normalize().String()) // "K"
// Side transformation
fmt.Println(id.Flip().String()) // "k"
// Terminal transformations
fmt.Println(id.Terminal().String()) // "K^"
fmt.Println(id.NonTerminal().String()) // "K"
// Attribute changes
fmt.Println(id.WithAbbr('Q').String()) // "Q"
fmt.Println(id.WithSide(pin.Second).String()) // "k"
fmt.Println(id.WithState(pin.Enhanced).String()) // "+K"
fmt.Println(id.WithTerminal(true).String()) // "K^"id := pin.MustParse("+K^")
// State queries
fmt.Println(id.IsNormal()) // false
fmt.Println(id.IsEnhanced()) // true
fmt.Println(id.IsDiminished()) // false
// Side queries
fmt.Println(id.IsFirstPlayer()) // true
fmt.Println(id.IsSecondPlayer()) // false
// Terminal query
fmt.Println(id.IsTerminal()) // true
// Comparison queries
other := pin.MustParse("k")
fmt.Println(id.SameAbbr(other)) // true
fmt.Println(id.SameSide(other)) // false
fmt.Println(id.SameState(other)) // false
fmt.Println(id.SameTerminal(other)) // falseFor high-performance scenarios, use AppendTo to avoid allocations.
buf := make([]byte, 0, 32)
id := pin.MustParse("+K^")
buf = id.AppendTo(buf)
fmt.Printf("%s\n", buf) // "+K^"// Identifier represents a parsed PIN identifier with all attributes.
// Zero value is not valid; use NewIdentifier or Parse to create.
type Identifier struct {
// contains unexported fields
}
// Side represents the piece side.
type Side uint8
// State represents the piece state.
type State uint8
// NewIdentifier creates an Identifier with default state (Normal) and terminal (false).
func NewIdentifier(abbr rune, side Side) Identifier
// NewIdentifierWithOptions creates an Identifier with all attributes specified.
func NewIdentifierWithOptions(abbr rune, side Side, state State, terminal bool) Identifier
// Abbr returns the piece name abbreviation as uppercase rune (A-Z).
func (id Identifier) Abbr() rune
// Side returns the piece side.
func (id Identifier) Side() Side
// State returns the piece state.
func (id Identifier) State() State
// IsTerminal returns the terminal status.
func (id Identifier) IsTerminal() bool
// String returns the PIN string representation.
func (id Identifier) String() string
// AppendTo appends the PIN string to dst without allocation.
func (id Identifier) AppendTo(dst []byte) []byteconst (
First Side = iota // Uppercase letter
Second // Lowercase letter
)
const (
Normal State = iota // No prefix
Enhanced // Prefix '+'
Diminished // Prefix '-'
)
const MaxStringLength = 3// Parse converts a PIN string to an Identifier.
// Returns an error if the string is not valid.
func Parse(s string) (Identifier, error)
// MustParse is like Parse but panics on error.
// Use for constants or trusted input.
func MustParse(s string) Identifier// Validate checks if s is a valid PIN identifier.
// Returns nil if valid, or a descriptive error.
func Validate(s string) error
// IsValid reports whether s is a valid PIN identifier.
func IsValid(s string) bool// State transformations
func (id Identifier) Enhance() Identifier
func (id Identifier) Diminish() Identifier
func (id Identifier) Normalize() Identifier
// Side transformation
func (id Identifier) Flip() Identifier
// Terminal transformations
func (id Identifier) Terminal() Identifier
func (id Identifier) NonTerminal() Identifier
// Attribute changes
func (id Identifier) WithAbbr(abbr rune) Identifier
func (id Identifier) WithSide(side Side) Identifier
func (id Identifier) WithState(state State) Identifier
func (id Identifier) WithTerminal(terminal bool) Identifier// State queries
func (id Identifier) IsNormal() bool
func (id Identifier) IsEnhanced() bool
func (id Identifier) IsDiminished() bool
// Side queries
func (id Identifier) IsFirstPlayer() bool
func (id Identifier) IsSecondPlayer() bool
// Comparison queries
func (id Identifier) SameAbbr(other Identifier) bool
func (id Identifier) SameSide(other Identifier) bool
func (id Identifier) SameState(other Identifier) bool
func (id Identifier) SameTerminal(other Identifier) boolvar (
ErrEmptyInput = errors.New("pin: empty input")
ErrInputTooLong = errors.New("pin: input exceeds 3 characters")
ErrMustContainOneLetter = errors.New("pin: must contain exactly one letter")
ErrInvalidStateModifier = errors.New("pin: invalid state modifier")
ErrInvalidTerminalMarker = errors.New("pin: invalid terminal marker")
)- Bounded types: Fixed-size struct, no heap allocation in hot path
- Value semantics:
Identifieris a value type, safe to copy - Sentinel errors: Standard Go error handling with
errors.Is() - strconv-style API: Familiar
Parse,MustParse,String()patterns - Zero-allocation option:
AppendTofor high-performance serialization - Security-hardened: Byte-level parsing, rejects Unicode lookalikes
- No dependencies: Pure Go standard library only
- Game Protocol — Conceptual foundation
- PIN Specification — Official specification
- PIN Examples — Usage examples
Available as open source under the Apache License 2.0.