package DataStructs import ( "encoding/json" "errors" ) type Stack[T any] struct { top *ChainElem[T] bottom *ChainElem[T] } // isValid checks if the stack is valid. func (s *Stack[T]) isValid() bool { return s.top != nil && s.bottom != nil && reachable(s.top, s.bottom) } // IsEmpty checks if the stack is currently empty. func (s *Stack[T]) IsEmpty() bool { return s.top == s.bottom } // Push adds a new element to the top of the stack. // It errors out if the stack is invalid. func (s *Stack[T]) Push(e *T) error { if !s.isValid() { return errors.New("stack invalid") } n := emptyElem[T]() n.Elem = e n.Next = s.top s.top = n return nil } // Pop removes the first element at the top of the stack and returns it. // It errors out if the stack is invalid or empty. func (s *Stack[T]) Pop() (*T, error) { if !s.isValid() { return nil, errors.New("stack invalid") } if s.IsEmpty() { return nil, errors.New("stack empty") } e := s.top.Elem s.top = s.top.Next return e, nil } // Top returns the first element at the top of the stack without removing it. // It errors out if the stack is empty or invalid. func (s *Stack[T]) Top() (*T, error) { if !s.isValid() { return nil, errors.New("stack invalid") } if s.IsEmpty() { return nil, errors.New("stack empty") } return s.top.Elem, nil } // MarshalJSON is used by json.Marshal to create a json representation. func (s *Stack[T]) MarshalJSON() ([]byte, error) { if !s.isValid() { return nil, errors.New("queue invalid") } if s.IsEmpty() { return nil, errors.New("queue empty") } return json.Marshal(s.top) } func BuildStack[T any]() *Stack[T] { empty := emptyElem[T]() return &Stack[T]{ top: empty, bottom: empty, } }