Switch completely to the new validation "ErrorType"
Stay backward-compatible with previous error messages.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/errors.go Sun Oct 16 11:52:01 2016 +0200
@@ -0,0 +1,63 @@
+package takuzu
+
+import "fmt"
+
+// This file contains the takuzu validation error type.
+
+const (
+ ErrorNil = iota
+ ErrorDuplicate
+ ErrorTooManyValues
+ ErrorTooManyAdjacentValues
+)
+
+type validationError struct {
+ ErrorType int
+ LineNumber *int
+ ColumnNumber *int
+ CellValue *int
+}
+
+func (e validationError) Error() string {
+ var axis string
+ var n int
+
+ // Currently we don't have validation errors with both
+ // line and column so we can get the axis:
+ if e.LineNumber != nil {
+ axis = "line"
+ n = *e.LineNumber
+ } else if e.ColumnNumber != nil {
+ axis = "column"
+ n = *e.ColumnNumber
+ }
+
+ switch e.ErrorType {
+ case ErrorNil:
+ return ""
+ case ErrorDuplicate:
+ if axis == "" {
+ return "internal validation error"
+ }
+ return fmt.Sprintf("duplicate %ss (%d)", axis, n)
+ case ErrorTooManyValues:
+ if axis == "" || e.CellValue == nil {
+ return "internal validation error"
+ }
+ var numberStr string
+ if *e.CellValue == 0 {
+ numberStr = "zeroes"
+ } else if *e.CellValue == 1 {
+ numberStr = "ones"
+ } else {
+ return "internal validation error"
+ }
+ return fmt.Sprintf("%s %d: too many %s", axis, n, numberStr)
+ case ErrorTooManyAdjacentValues:
+ if axis == "" || e.CellValue == nil {
+ return "internal validation error"
+ }
+ return fmt.Sprintf("%s %d: 3+ same values %d", axis, n, *e.CellValue)
+ }
+ return "internal validation error"
+}
--- a/validate.go Sun Oct 16 10:08:11 2016 +0200
+++ b/validate.go Sun Oct 16 11:52:01 2016 +0200
@@ -1,10 +1,6 @@
package takuzu
-import (
- "fmt"
-
- "github.com/pkg/errors"
-)
+// This file contains the takuzu validation functions and methods.
// checkRange returns true if the range is completely defined, and an error
// if it doesn't follow the rules for a takuzu line or column
@@ -31,7 +27,11 @@
if c.Value == prevCell.Value {
prevCellCount++
if prevCellCount > 2 {
- return full, errors.Errorf("3+ same values %d", c.Value)
+ v := c.Value
+ return full, validationError{
+ ErrorType: ErrorTooManyAdjacentValues,
+ CellValue: &v,
+ }
}
} else {
prevCellCount = 1
@@ -41,10 +41,18 @@
prevCell = c
}
if counters[0] > size/2 {
- return full, errors.Errorf("too many zeroes")
+ v := 0
+ return full, validationError{
+ ErrorType: ErrorTooManyValues,
+ CellValue: &v,
+ }
}
if counters[1] > size/2 {
- return full, errors.Errorf("too many ones")
+ v := 1
+ return full, validationError{
+ ErrorType: ErrorTooManyValues,
+ CellValue: &v,
+ }
}
return full, nil
}
@@ -101,12 +109,18 @@
d = b.GetLine(i)
full, err = checkRange(d)
if err != nil {
- return false, errors.Wrapf(err, "line %d", i)
+ err := err.(validationError)
+ err.LineNumber = &i
+ return false, err
}
if full {
hv := computeVal(d)
if lineVals[hv] {
- return false, fmt.Errorf("duplicate lines (%d)", i)
+ err := validationError{
+ ErrorType: ErrorDuplicate,
+ LineNumber: &i,
+ }
+ return false, err
}
lineVals[hv] = true
} else {
@@ -117,12 +131,18 @@
d = b.GetColumn(i)
full, err = checkRange(d)
if err != nil {
- return false, errors.Wrapf(err, "column %d", i)
+ err := err.(validationError)
+ err.ColumnNumber = &i
+ return false, err
}
if full {
hv := computeVal(d)
if colVals[hv] {
- return false, fmt.Errorf("duplicate columns (%d)", i)
+ err := validationError{
+ ErrorType: ErrorDuplicate,
+ ColumnNumber: &i,
+ }
+ return false, err
}
colVals[hv] = true
} else {