package traverse // DefaultMaxDepth is the maximum traversal depth used when no explicit depth is configured. const DefaultMaxDepth = 20 // Stack is a depth-limited LIFO queue of Referrals used to drive iterative // DNS traversal. Pushing a Referral whose Depth exceeds maxDepth fails // silently and returns false, preventing unbounded traversal. type Stack struct { items []*Referral maxDepth int } // NewStack creates a Stack with the given maximum depth. // When maxDepth is ≤ 0, DefaultMaxDepth is used. func NewStack(maxDepth int) *Stack { if maxDepth <= 0 { maxDepth = DefaultMaxDepth } return &Stack{ items: make([]*Referral, 0), maxDepth: maxDepth, } } // Push adds r to the stack. Returns false (and does not add) when r is nil // or r.Depth >= maxDepth. func (s *Stack) Push(r *Referral) bool { if r == nil { return false } if r.Depth >= s.maxDepth { return false } s.items = append(s.items, r) return true } // Pop removes and returns the top Referral, or nil when the stack is empty. func (s *Stack) Pop() *Referral { if len(s.items) == 0 { return nil } idx := len(s.items) - 1 item := s.items[idx] s.items = s.items[:idx] return item } // Peek returns the top Referral without removing it, or nil when empty. func (s *Stack) Peek() *Referral { if len(s.items) == 0 { return nil } return s.items[len(s.items)-1] } // Len returns the current number of items in the stack. func (s *Stack) Len() int { return len(s.items) } // MaxDepth returns the configured maximum depth for this stack. func (s *Stack) MaxDepth() int { return s.maxDepth } // IsEmpty reports whether the stack has no items. func (s *Stack) IsEmpty() bool { return len(s.items) == 0 }