strict.go raw

   1  package toml
   2  
   3  import (
   4  	"github.com/pelletier/go-toml/v2/internal/danger"
   5  	"github.com/pelletier/go-toml/v2/internal/tracker"
   6  	"github.com/pelletier/go-toml/v2/unstable"
   7  )
   8  
   9  type strict struct {
  10  	Enabled bool
  11  
  12  	// Tracks the current key being processed.
  13  	key tracker.KeyTracker
  14  
  15  	missing []unstable.ParserError
  16  }
  17  
  18  func (s *strict) EnterTable(node *unstable.Node) {
  19  	if !s.Enabled {
  20  		return
  21  	}
  22  
  23  	s.key.UpdateTable(node)
  24  }
  25  
  26  func (s *strict) EnterArrayTable(node *unstable.Node) {
  27  	if !s.Enabled {
  28  		return
  29  	}
  30  
  31  	s.key.UpdateArrayTable(node)
  32  }
  33  
  34  func (s *strict) EnterKeyValue(node *unstable.Node) {
  35  	if !s.Enabled {
  36  		return
  37  	}
  38  
  39  	s.key.Push(node)
  40  }
  41  
  42  func (s *strict) ExitKeyValue(node *unstable.Node) {
  43  	if !s.Enabled {
  44  		return
  45  	}
  46  
  47  	s.key.Pop(node)
  48  }
  49  
  50  func (s *strict) MissingTable(node *unstable.Node) {
  51  	if !s.Enabled {
  52  		return
  53  	}
  54  
  55  	s.missing = append(s.missing, unstable.ParserError{
  56  		Highlight: keyLocation(node),
  57  		Message:   "missing table",
  58  		Key:       s.key.Key(),
  59  	})
  60  }
  61  
  62  func (s *strict) MissingField(node *unstable.Node) {
  63  	if !s.Enabled {
  64  		return
  65  	}
  66  
  67  	s.missing = append(s.missing, unstable.ParserError{
  68  		Highlight: keyLocation(node),
  69  		Message:   "missing field",
  70  		Key:       s.key.Key(),
  71  	})
  72  }
  73  
  74  func (s *strict) Error(doc []byte) error {
  75  	if !s.Enabled || len(s.missing) == 0 {
  76  		return nil
  77  	}
  78  
  79  	err := &StrictMissingError{
  80  		Errors: make([]DecodeError, 0, len(s.missing)),
  81  	}
  82  
  83  	for _, derr := range s.missing {
  84  		derr := derr
  85  		err.Errors = append(err.Errors, *wrapDecodeError(doc, &derr))
  86  	}
  87  
  88  	return err
  89  }
  90  
  91  func keyLocation(node *unstable.Node) []byte {
  92  	k := node.Key()
  93  
  94  	hasOne := k.Next()
  95  	if !hasOne {
  96  		panic("should not be called with empty key")
  97  	}
  98  
  99  	start := k.Node().Data
 100  	end := k.Node().Data
 101  
 102  	for k.Next() {
 103  		end = k.Node().Data
 104  	}
 105  
 106  	return danger.BytesRange(start, end)
 107  }
 108