Files
notarius/internal/core/source/validation.go

105 lines
2.8 KiB
Go

package source
import (
"fmt"
"strings"
)
func ValidateDocument(doc *SourceDocument) error {
if doc == nil {
return fmt.Errorf("source document must not be nil")
}
if isBlank(doc.ID) {
return fmt.Errorf("source document id must not be empty")
}
if hasSurroundingWhitespace(doc.ID) {
return fmt.Errorf("source document id %q must not contain leading or trailing whitespace", doc.ID)
}
if isBlank(doc.Kind) {
return fmt.Errorf("source document kind must not be empty")
}
if isBlank(doc.Format) {
return fmt.Errorf("source document format must not be empty")
}
if isBlank(doc.Digest) {
return fmt.Errorf("source document digest must not be empty")
}
if len(doc.Units) == 0 {
return fmt.Errorf("source document units must not be empty")
}
seenUnitIDs := make(map[int]struct{}, len(doc.Units))
for i, unit := range doc.Units {
if unit.ID <= 0 {
return fmt.Errorf("source unit[%d].id must be positive", i)
}
if isBlank(unit.Kind) {
return fmt.Errorf("source unit[%d].kind must not be empty", i)
}
if isBlank(unit.Text) {
return fmt.Errorf("source unit[%d].text must not be empty", i)
}
if _, ok := seenUnitIDs[unit.ID]; ok {
return fmt.Errorf("source unit id %d is duplicated", unit.ID)
}
seenUnitIDs[unit.ID] = struct{}{}
}
return nil
}
func ValidateRef(doc *SourceDocument, ref SourceRef) error {
if doc == nil {
return fmt.Errorf("source document must not be nil")
}
if isBlank(ref.SourceID) {
return fmt.Errorf("source ref source_id must not be empty")
}
if hasSurroundingWhitespace(ref.SourceID) {
return fmt.Errorf("source ref source_id %q must not contain leading or trailing whitespace", ref.SourceID)
}
if ref.StartUnitID <= 0 {
return fmt.Errorf("source ref start_unit_id must be positive")
}
if ref.EndUnitID <= 0 {
return fmt.Errorf("source ref end_unit_id must be positive")
}
if ref.SourceID != doc.ID {
return fmt.Errorf("source ref source_id %q does not match document id %q", ref.SourceID, doc.ID)
}
startIndex, ok := UnitIndex(doc, ref.StartUnitID)
if !ok {
return fmt.Errorf("source ref start_unit_id %d was not found", ref.StartUnitID)
}
endIndex, ok := UnitIndex(doc, ref.EndUnitID)
if !ok {
return fmt.Errorf("source ref end_unit_id %d was not found", ref.EndUnitID)
}
if startIndex > endIndex {
return fmt.Errorf("source ref start_unit_id %d appears after end_unit_id %d", ref.StartUnitID, ref.EndUnitID)
}
return nil
}
func UnitIndex(doc *SourceDocument, unitID int) (int, bool) {
if doc == nil {
return 0, false
}
for i, unit := range doc.Units {
if unit.ID == unitID {
return i, true
}
}
return 0, false
}
func isBlank(value string) bool {
return strings.TrimSpace(value) == ""
}
func hasSurroundingWhitespace(value string) bool {
return strings.TrimSpace(value) != value
}