Allow sentence parsing customization (SentenceParser struct) ...#97
Allow sentence parsing customization (SentenceParser struct) ...#97aldas merged 5 commits intoadrianmo:masterfrom
Conversation
|
Looks like it's time for a v2. |
|
Just a note Github flow uses |
|
Yep, I agree. |
…MTK sentence to PMTK001, Add Query sentence, Expose all supported type and their parsers (SupportedParsers map), Add 1.18 into CI flow
|
This is how I imagine the API: p := nmea.SentenceParser{
ParsePrefix: func(prefix string) (string, string, err) {
if prefix == "GSENSORD" {
return "", prefix, nil
}
return nmea.ParsePrefix(prefix)
},
CheckCRC: func(s nmea.BaseSentence, fields string) error {
if s.Type == "GSENSORD" {
return nil
}
return nmea.CheckCRC(s, fields)
},
}
p.Register("GSENSORD", func(s nmea.BaseSentence) (nmea.Sentence, error) {
// ...
})The zero value var p nmea.SentenceParser
_, _ = p.Parse("...") |
|
At the moment I would suggest p := nmea.NewSentenceParserWithConfig(nmea.SentenceParserConfig{
CustomParsers: map[string]nmea.ParserFunc{
"XYZ": func(s nmea.BaseSentence) (nmea.Sentence, error) {
// This example uses the package builtin parsing helpers
// you can implement your own parsing logic also
p := nmea.NewParser(s)
return XYZType{
BaseSentence: s,
Time: p.Time(0, "time"),
Label: p.String(1, "label"),
Counter: p.Int64(2, "counter"),
Value: p.Float64(3, "value"),
}, p.Err()
},
},
})
s, err := p.Parse(`$00XYZ,220516,A,23,5133.82,W*42`)
// SentenceParser provides configurable functionality to parse raw input into Sentence
type SentenceParser struct {
// parserLock exists because we want to preserve defaultSentenceParser backwards compatibility so global
// RegisterParser and MustRegisterParser functions can mutate customParsers map. SentenceParser instance itself
// does not need locks
parserLock *sync.RWMutex
config SentenceParserConfig
}
// NewSentenceParser creates new default instance of SentenceParser
func NewSentenceParser() *SentenceParser {
return NewSentenceParserWithConfig(SentenceParserConfig{})
}
// NewSentenceParserWithConfig creates new instance of SentenceParser with given config
func NewSentenceParserWithConfig(c SentenceParserConfig) *SentenceParser {
if c.ParseAddress == nil {
c.ParseAddress = DefaultParseAddress
}
if c.CheckCRC == nil {
c.CheckCRC = DefaultCheckCRC
}
cp := map[string]ParserFunc{}
for sType, pFunc := range c.CustomParsers {
cp[sType] = pFunc
}
return &SentenceParser{
parserLock: &sync.RWMutex{},
config: SentenceParserConfig{
CustomParsers: cp,
ParseAddress: c.ParseAddress,
CheckCRC: c.CheckCRC,
OnTagBlock: c.OnTagBlock,
},
}
} |
The top level functions are thread safe because it's likely that code in different packages/modules use them without being aware of each-other. If a package is creating its own
How would the suggested lock prevent races in the user-provider functions?
Then let them shoot themselves in the foot. Maybe they'll learn to read the docs. |
f6ad0f0 to
f0f8cb3
Compare
|
alright, this should be better now. Changed mutex parts + |
|
If it comes to merging some day - please use Squash or allow me to squash commits |
icholy
left a comment
There was a problem hiding this comment.
gofmt the code and it's good to go.
SentenceParserstruct) - See possibility to make CRC check optional for certain sentences #96SupportedParsers),BREAKING CHANGE:
I have added MTK change here as it is deeply tied to sentence parsing internals and has "hacks" to override BaseSentence.TalkerID meaning.