package validation import ( "fmt" "strings" ) // Check identifies one shared validation check. type Check string const ( // GoTest identifies the base Go test suite. GoTest Check = "go-test" ) // Finding describes a validation observation at an optional source location. type Finding struct { Path string Line int Column int Message string Target string Directive string } // FileSizeMeasurement describes a measured file size and its selected limit. type FileSizeMeasurement struct { Bytes int64 LimitBytes int64 } // Failure describes a failed shared validation check and preserves its cause. type Failure struct { Check Check Findings []Finding Measurement *FileSizeMeasurement Cause error } // Error returns a useful summary of the failed check. func (failure *Failure) Error() string { return formatFailure(failure) } // Unwrap returns the underlying validation error. func (failure *Failure) Unwrap() error { if failure == nil { return nil } return failure.Cause } func formatFailure(failure *Failure) string { if failure == nil { return "" } var summary strings.Builder if failure.Check == "" { summary.WriteString("validation failed") } else { fmt.Fprintf(&summary, "%s validation failed", failure.Check) } for _, finding := range failure.Findings { summary.WriteString(": ") if finding.Path != "" { summary.WriteString(finding.Path) if finding.Line > 0 { fmt.Fprintf(&summary, ":%d", finding.Line) if finding.Column > 0 { fmt.Fprintf(&summary, ":%d", finding.Column) } } summary.WriteString(": ") } summary.WriteString(finding.Message) } if failure.Measurement != nil { fmt.Fprintf(&summary, ": measured %d bytes against a %d byte limit", failure.Measurement.Bytes, failure.Measurement.LimitBytes) } if failure.Cause != nil { if len(failure.Findings) == 0 && failure.Measurement == nil { summary.WriteString(": ") } else { summary.WriteString("; ") } summary.WriteString(failure.Cause.Error()) } return summary.String() } var _ error = (*Failure)(nil) var _ interface{ Unwrap() error } = (*Failure)(nil)