Skip to content

Commit b05c768

Browse files
committed
pkg/math: added MultipleOf
Also: - add support for Decimal type (internal) - add correspondng support in openapi package Change-Id: Idc4b829423bba63380a8edfc1109c345f4248355 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2640 Reviewed-by: Marcel van Lohuizen <[email protected]>
1 parent ce195d2 commit b05c768

File tree

10 files changed

+98
-3
lines changed

10 files changed

+98
-3
lines changed

cue/builtin.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"cuelang.org/go/cue/errors"
2929
"cuelang.org/go/cue/parser"
3030
"cuelang.org/go/internal"
31+
"github.com/cockroachdb/apd/v2"
3132
)
3233

3334
// A builtin is a builtin function or constant.
@@ -393,6 +394,15 @@ func (c *callCtxt) uintValue(i, bits int, typ string) uint64 {
393394
return res
394395
}
395396

397+
func (c *callCtxt) decimal(i int) *apd.Decimal {
398+
x := newValueRoot(c.ctx, c.args[i])
399+
if _, err := x.MantExp(nil); err != nil {
400+
c.invalidArgType(c.args[i], i, "Decimal", err)
401+
return nil
402+
}
403+
return &c.args[i].(*numLit).v
404+
}
405+
396406
func (c *callCtxt) float64(i int) float64 {
397407
x := newValueRoot(c.ctx, c.args[i])
398408
res, err := x.Float64()

cue/builtin_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@ func TestBuiltins(t *testing.T) {
8989
}, {
9090
test("math", `math.Asin(2.0e400)`),
9191
`_|_(cannot use 2.0e+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up)`,
92+
}, {
93+
test("math", `math.MultipleOf(4, 2)`), `true`,
94+
}, {
95+
test("math", `math.MultipleOf(5, 2)`), `false`,
96+
}, {
97+
test("math", `math.MultipleOf(5, 0)`),
98+
`_|_(error in call to math.MultipleOf: division by zero)`,
99+
}, {
100+
test("math", `math.MultipleOf(100, 1.00001)`), `false`,
101+
}, {
102+
test("math", `math.MultipleOf(1, 1)`), `true`,
103+
}, {
104+
test("math", `math.MultipleOf(5, 2.5)`), `true`,
105+
}, {
106+
test("math", `math.MultipleOf(100e100, 10)`), `true`,
92107
}, {
93108
test("encoding/csv", `csv.Decode("1,2,3\n4,5,6")`),
94109
`[["1","2","3"],["4","5","6"]]`,

cue/builtins.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cue/gen.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ func (g *generator) goKind(expr ast.Expr) string {
388388
return "bigFloat"
389389
case "big.Rat":
390390
return "bigRat"
391+
case "internal.Decimal":
392+
return "decimal"
391393
case "cue.Value":
392394
return "value"
393395
case "cue.List":
@@ -419,7 +421,7 @@ func (g *generator) goToCUE(expr ast.Expr) (cueKind string, omitCheck bool) {
419421
"uint", "byte", "uint8", "uint16", "uint32", "uint64",
420422
"bigInt":
421423
cueKind += "intKind"
422-
case "float64", "bigRat", "bigFloat":
424+
case "float64", "bigRat", "bigFloat", "decimal":
423425
cueKind += "numKind"
424426
case "list":
425427
cueKind += "listKind"

encoding/openapi/build.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ func (b *builder) dispatch(f typeFunc, v cue.Value) {
435435

436436
// object supports the following
437437
// - maxProperties: maximum allowed fields in this struct.
438-
// - minProperties: minimum required fields in this struct.a
438+
// - minProperties: minimum required fields in this struct.
439439
// - patternProperties: [regexp]: schema
440440
// TODO: we can support this once .kv(key, value) allow
441441
// foo [=~"pattern"]: type
@@ -599,6 +599,18 @@ func (b *builder) number(v cue.Value) {
599599
b.kv("maxItems", i),
600600
})
601601

602+
case cue.CallOp:
603+
name := fmt.Sprint(a[0])
604+
switch name {
605+
case "math.MultipleOf":
606+
if len(a) != 2 {
607+
b.failf(v, "builtin %v may only be used with single argument", name)
608+
}
609+
b.setFilter("Schema", "multipleOf", b.int(a[1]))
610+
default:
611+
b.failf(v, "builtin %v not supported in OpenAPI", name)
612+
}
613+
602614
case cue.NoOp:
603615
// TODO: extract format from specific type.
604616

encoding/openapi/openapi_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ func TestParseDefinitions(t *testing.T) {
5454
"strings.cue",
5555
"strings.json",
5656
defaultConfig,
57+
}, {
58+
"nums.cue",
59+
"nums.json",
60+
defaultConfig,
5761
}, {
5862
"oneof.cue",
5963
"oneof.json",

encoding/openapi/testdata/nums.cue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import "math"
2+
3+
mul: math.MultipleOf(5)

encoding/openapi/testdata/nums.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"openapi": "3.0.0",
3+
"info": {},
4+
"components": {
5+
"schemas": {
6+
"mul": {
7+
"type": "number",
8+
"multipleOf": 5
9+
}
10+
}
11+
}
12+
}

internal/internal.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ package internal // import "cuelang.org/go/internal"
1616

1717
// TODO: refactor packages as to make this package unnecessary.
1818

19+
import "github.com/cockroachdb/apd/v2"
20+
21+
// A Decimal is an arbitrary-precision binary-coded decimal number.
22+
//
23+
// Right now Decimal is aliased to apd.Decimal. This may change in the future.
24+
type Decimal = apd.Decimal
25+
1926
// DebugStr prints a syntax node.
2027
var DebugStr func(x interface{}) string
2128

pkg/math/manual.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414

1515
package math
1616

17-
import "math"
17+
import (
18+
"math"
19+
20+
"cuelang.org/go/internal"
21+
"github.com/cockroachdb/apd/v2"
22+
)
1823

1924
// TODO: use apd
2025

@@ -67,3 +72,12 @@ func Round(x float64) float64 {
6772
func RoundToEven(x float64) float64 {
6873
return math.RoundToEven(x)
6974
}
75+
76+
var mulContext = apd.BaseContext.WithPrecision(1)
77+
78+
// MultipleOf reports whether x is a multiple of y.
79+
func MultipleOf(x, y *internal.Decimal) (bool, error) {
80+
var d apd.Decimal
81+
cond, err := mulContext.Quo(&d, x, y)
82+
return !cond.Inexact(), err
83+
}

0 commit comments

Comments
 (0)