Reject unversioned party documents
This commit is contained in:
@@ -83,17 +83,12 @@ type PartyClass struct {
|
||||
Level *int
|
||||
}
|
||||
|
||||
// ParseParty classifies and, when selected by schema_version, strictly parses
|
||||
// a party source. An unversioned source takes the deliberately opaque legacy
|
||||
// compatibility path; see party_legacy.go.
|
||||
// ParseParty strictly parses one supported party document.
|
||||
func ParseParty(data []byte) (*PartyDocument, error) {
|
||||
root, decoder, err := parsePartyFirstDocument(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !partyDocumentSelectsCanonical(root) {
|
||||
return classifyLegacyPartyDocument(), nil
|
||||
}
|
||||
if err := requireNoTrailingPartyDocuments(decoder); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -119,25 +114,12 @@ func parsePartyFirstDocument(data []byte) (*yaml.Node, *yaml.Decoder, error) {
|
||||
return document.Content[0], decoder, nil
|
||||
}
|
||||
|
||||
func partyDocumentSelectsCanonical(root *yaml.Node) bool {
|
||||
if root == nil || root.Kind != yaml.MappingNode {
|
||||
return false
|
||||
}
|
||||
for index := 0; index+1 < len(root.Content); index += 2 {
|
||||
key := root.Content[index]
|
||||
if key.Kind == yaml.ScalarNode && key.Tag == "!!str" && key.Value == "schema_version" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func requireNoTrailingPartyDocuments(decoder *yaml.Decoder) error {
|
||||
var trailing yaml.Node
|
||||
if err := decoder.Decode(&trailing); err == nil {
|
||||
return fmt.Errorf("canonical party must contain exactly one YAML document")
|
||||
return fmt.Errorf("party must contain exactly one YAML document")
|
||||
} else if err != io.EOF {
|
||||
return fmt.Errorf("decode trailing canonical party YAML: %w", err)
|
||||
return fmt.Errorf("decode trailing party YAML: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -147,17 +129,21 @@ func parseCanonicalParty(root *yaml.Node, raw []byte) (*CanonicalParty, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
version, ok := fields["schema_version"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("party.schema_version is required; supported schema_version is %q", PartySchemaVersion)
|
||||
}
|
||||
schemaVersion, err := partyRequiredString(map[string]*yaml.Node{"schema_version": version}, "schema_version", "party")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("party.schema_version must be a non-empty string; supported schema_version is %q", PartySchemaVersion)
|
||||
}
|
||||
if schemaVersion != PartySchemaVersion {
|
||||
return nil, fmt.Errorf("party.schema_version %q is unsupported; supported schema_version is %q", schemaVersion, PartySchemaVersion)
|
||||
}
|
||||
if err := partyKnownFields(fields, "party", "schema_version", "characters"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
version, err := partyRequiredString(fields, "schema_version", "party")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if version != PartySchemaVersion {
|
||||
return nil, fmt.Errorf("party.schema_version %q is unsupported", version)
|
||||
}
|
||||
charactersNode, ok := fields["characters"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("party.characters is required")
|
||||
|
||||
Reference in New Issue
Block a user