@@ -4,11 +4,11 @@ import (
4
4
"bytes"
5
5
"errors"
6
6
"fmt"
7
+ "math"
7
8
"strings"
8
9
"text/template"
9
10
10
11
"github.com/goadesign/goa/design"
11
- "github.com/goadesign/goa/dslengine"
12
12
)
13
13
14
14
var (
@@ -328,6 +328,9 @@ func (v *Validator) recurseAttribute(att, catt *design.AttributeDefinition, n, t
328
328
// error. It initializes that variable in case a validation fails.
329
329
// Note: we do not want to recurse here, recursion is done by the marshaler/unmarshaler code.
330
330
func ValidationChecker (att * design.AttributeDefinition , nonzero , required , hasDefault bool , target , context string , depth int , private bool ) string {
331
+ if att .Validation == nil {
332
+ return ""
333
+ }
331
334
t := target
332
335
isPointer := private || (! required && ! hasDefault && ! nonzero )
333
336
if isPointer && att .Type .IsPrimitive () {
@@ -346,14 +349,12 @@ func ValidationChecker(att *design.AttributeDefinition, nonzero, required, hasDe
346
349
"depth" : depth ,
347
350
"private" : private ,
348
351
}
349
- res := validationsCode (att . Validation , data )
352
+ res := validationsCode (att , data )
350
353
return strings .Join (res , "\n " )
351
354
}
352
355
353
- func validationsCode (validation * dslengine.ValidationDefinition , data map [string ]interface {}) (res []string ) {
354
- if validation == nil {
355
- return nil
356
- }
356
+ func validationsCode (att * design.AttributeDefinition , data map [string ]interface {}) (res []string ) {
357
+ validation := att .Validation
357
358
if values := validation .Values ; values != nil {
358
359
data ["values" ] = values
359
360
if val := RunTemplate (enumValT , data ); val != "" {
@@ -373,15 +374,23 @@ func validationsCode(validation *dslengine.ValidationDefinition, data map[string
373
374
}
374
375
}
375
376
if min := validation .Minimum ; min != nil {
376
- data ["min" ] = * min
377
+ if att .Type == design .Integer {
378
+ data ["min" ] = renderInteger (* min )
379
+ } else {
380
+ data ["min" ] = fmt .Sprintf ("%f" , * min )
381
+ }
377
382
data ["isMin" ] = true
378
383
delete (data , "max" )
379
384
if val := RunTemplate (minMaxValT , data ); val != "" {
380
385
res = append (res , val )
381
386
}
382
387
}
383
388
if max := validation .Maximum ; max != nil {
384
- data ["max" ] = * max
389
+ if att .Type == design .Integer {
390
+ data ["max" ] = renderInteger (* max )
391
+ } else {
392
+ data ["max" ] = fmt .Sprintf ("%f" , * max )
393
+ }
385
394
data ["isMin" ] = false
386
395
delete (data , "min" )
387
396
if val := RunTemplate (minMaxValT , data ); val != "" {
@@ -418,6 +427,18 @@ func validationsCode(validation *dslengine.ValidationDefinition, data map[string
418
427
return
419
428
}
420
429
430
+ // renderInteger renders a max or min value properly, taking into account
431
+ // overflows due to casting from a float value.
432
+ func renderInteger (f float64 ) string {
433
+ if f > math .Nextafter (float64 (math .MaxInt64 ), 0 ) {
434
+ return fmt .Sprintf ("%d" , int64 (math .MaxInt64 ))
435
+ }
436
+ if f < math .Nextafter (float64 (math .MinInt64 ), 0 ) {
437
+ return fmt .Sprintf ("%d" , int64 (math .MinInt64 ))
438
+ }
439
+ return fmt .Sprintf ("%d" , int64 (f ))
440
+ }
441
+
421
442
// oneof produces code that compares target with each element of vals and ORs
422
443
// the result, e.g. "target == 1 || target == 2".
423
444
func oneof (target string , vals []interface {}) string {
0 commit comments