typia 15.0.0 → 15.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/http.d.ts +49 -24
- package/lib/http.js.map +1 -1
- package/lib/http.mjs.map +1 -1
- package/lib/internal/_httpFormDataReadBigint.js +7 -5
- package/lib/internal/_httpFormDataReadBigint.js.map +1 -1
- package/lib/internal/_httpFormDataReadBigint.mjs +1 -1
- package/lib/internal/_httpFormDataReadBigint.mjs.map +1 -1
- package/lib/internal/_httpFormDataReadBoolean.js +12 -10
- package/lib/internal/_httpFormDataReadBoolean.js.map +1 -1
- package/lib/internal/_httpFormDataReadBoolean.mjs +1 -1
- package/lib/internal/_httpFormDataReadBoolean.mjs.map +1 -1
- package/lib/internal/_httpFormDataReadNumber.js +7 -5
- package/lib/internal/_httpFormDataReadNumber.js.map +1 -1
- package/lib/internal/_httpFormDataReadNumber.mjs +1 -1
- package/lib/internal/_httpFormDataReadNumber.mjs.map +1 -1
- package/lib/internal/_httpFormDataReadString.d.ts +9 -1
- package/lib/internal/_httpFormDataReadString.js +10 -2
- package/lib/internal/_httpFormDataReadString.js.map +1 -1
- package/lib/internal/_httpFormDataReadString.mjs +9 -1
- package/lib/internal/_httpFormDataReadString.mjs.map +1 -1
- package/lib/internal/_httpHeaderReadBigint.js +5 -1
- package/lib/internal/_httpHeaderReadBigint.js.map +1 -1
- package/lib/internal/_httpHeaderReadBigint.mjs +2 -1
- package/lib/internal/_httpHeaderReadBigint.mjs.map +1 -1
- package/lib/internal/_httpHeaderReadNumber.js +5 -1
- package/lib/internal/_httpHeaderReadNumber.js.map +1 -1
- package/lib/internal/_httpHeaderReadNumber.mjs +2 -1
- package/lib/internal/_httpHeaderReadNumber.mjs.map +1 -1
- package/lib/internal/_httpParameterReadBigint.js +4 -0
- package/lib/internal/_httpParameterReadBigint.js.map +1 -1
- package/lib/internal/_httpParameterReadBigint.mjs +1 -0
- package/lib/internal/_httpParameterReadBigint.mjs.map +1 -1
- package/lib/internal/_httpParameterReadNumber.js +4 -0
- package/lib/internal/_httpParameterReadNumber.js.map +1 -1
- package/lib/internal/_httpParameterReadNumber.mjs +1 -0
- package/lib/internal/_httpParameterReadNumber.mjs.map +1 -1
- package/lib/internal/_httpParameterReadString.d.ts +9 -1
- package/lib/internal/_httpParameterReadString.js +9 -1
- package/lib/internal/_httpParameterReadString.js.map +1 -1
- package/lib/internal/_httpParameterReadString.mjs +9 -1
- package/lib/internal/_httpParameterReadString.mjs.map +1 -1
- package/lib/internal/_httpQueryReadBigint.js +8 -1
- package/lib/internal/_httpQueryReadBigint.js.map +1 -1
- package/lib/internal/_httpQueryReadBigint.mjs +1 -1
- package/lib/internal/_httpQueryReadBigint.mjs.map +1 -1
- package/lib/internal/_httpQueryReadBoolean.js +4 -1
- package/lib/internal/_httpQueryReadBoolean.js.map +1 -1
- package/lib/internal/_httpQueryReadBoolean.mjs +1 -1
- package/lib/internal/_httpQueryReadBoolean.mjs.map +1 -1
- package/lib/internal/_httpQueryReadNumber.js +8 -1
- package/lib/internal/_httpQueryReadNumber.js.map +1 -1
- package/lib/internal/_httpQueryReadNumber.mjs +1 -1
- package/lib/internal/_httpQueryReadNumber.mjs.map +1 -1
- package/lib/internal/_httpQueryReadString.d.ts +9 -1
- package/lib/internal/_httpQueryReadString.js +9 -1
- package/lib/internal/_httpQueryReadString.js.map +1 -1
- package/lib/internal/_httpQueryReadString.mjs +9 -1
- package/lib/internal/_httpQueryReadString.mjs.map +1 -1
- package/lib/internal/_randomBigint.d.ts +12 -1
- package/lib/internal/_randomBigint.js +90 -2
- package/lib/internal/_randomBigint.js.map +1 -1
- package/lib/internal/_randomBigint.mjs +70 -2
- package/lib/internal/_randomBigint.mjs.map +1 -1
- package/lib/internal/_randomInteger.js +21 -12
- package/lib/internal/_randomInteger.js.map +1 -1
- package/lib/internal/_randomInteger.mjs +21 -16
- package/lib/internal/_randomInteger.mjs.map +1 -1
- package/lib/internal/_randomNumber.js +19 -10
- package/lib/internal/_randomNumber.js.map +1 -1
- package/lib/internal/_randomNumber.mjs +19 -14
- package/lib/internal/_randomNumber.mjs.map +1 -1
- package/native/cmd/ttsc-typia/llm_evaluation_rejects_invalid_probability_test.go +9 -0
- package/native/cmd/ttsc-typia/random_recursive_min_items_diagnostic_test.go +18 -1
- package/native/core/factories/ExpressionFactory.go +16 -1
- package/native/core/factories/MetadataCommentTagFactory.go +177 -29
- package/native/core/factories/expression_factory_number_spells_non_finite_values_test.go +69 -0
- package/native/core/factories/metadata_comment_tag_factory_holds_bigint_tags_exact_test.go +168 -0
- package/native/core/factories/metadata_comment_tag_factory_reads_javascript_numbers_test.go +158 -0
- package/native/core/programmers/functional/FunctionalAssertParametersProgrammer.go +1 -3
- package/native/core/programmers/functional/FunctionalIsParametersProgrammer.go +107 -9
- package/native/core/programmers/functional/FunctionalValidateParametersProgrammer.go +1 -3
- package/native/core/programmers/http/HttpFormDataProgrammer.go +41 -2
- package/native/core/programmers/http/HttpHeadersProgrammer.go +56 -4
- package/native/core/programmers/http/HttpParameterProgrammer.go +1 -3
- package/native/core/programmers/http/HttpQueryProgrammer.go +26 -43
- package/native/core/programmers/iterate/json_schema_jsDocTags.go +10 -3
- package/native/core/programmers/iterate/json_schema_jsdoc_tags_cast_reads_javascript_numbers_test.go +64 -0
- package/native/core/programmers/llm/LlmEvaluationProgrammer.go +6 -2
- package/native/core/programmers/llm/LlmSchemaProgrammer.go +34 -4
- package/native/core/utils/NumberUtil.go +195 -0
- package/native/core/utils/number_util_rational_keeps_written_value_test.go +62 -0
- package/native/core/utils/number_util_reads_javascript_number_grammar_test.go +147 -0
- package/package.json +3 -3
- package/src/http.ts +61 -34
- package/src/internal/_httpFormDataReadBigint.ts +3 -1
- package/src/internal/_httpFormDataReadBoolean.ts +3 -1
- package/src/internal/_httpFormDataReadNumber.ts +3 -1
- package/src/internal/_httpFormDataReadString.ts +10 -1
- package/src/internal/_httpHeaderReadBigint.ts +6 -1
- package/src/internal/_httpHeaderReadNumber.ts +6 -1
- package/src/internal/_httpParameterReadBigint.ts +3 -0
- package/src/internal/_httpParameterReadNumber.ts +3 -0
- package/src/internal/_httpParameterReadString.ts +12 -2
- package/src/internal/_httpQueryReadBigint.ts +7 -1
- package/src/internal/_httpQueryReadBoolean.ts +3 -1
- package/src/internal/_httpQueryReadNumber.ts +7 -1
- package/src/internal/_httpQueryReadString.ts +10 -1
- package/src/internal/_randomBigint.ts +111 -3
- package/src/internal/_randomInteger.ts +31 -16
- package/src/internal/_randomNumber.ts +23 -12
|
@@ -2,10 +2,12 @@ package factories
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"math"
|
|
5
|
+
"math/big"
|
|
5
6
|
"strconv"
|
|
6
7
|
"strings"
|
|
7
8
|
|
|
8
9
|
schemametadata "github.com/samchon/typia/packages/typia/native/core/schemas/metadata"
|
|
10
|
+
nativeutils "github.com/samchon/typia/packages/typia/native/core/utils"
|
|
9
11
|
)
|
|
10
12
|
|
|
11
13
|
type metadataCommentTagFactoryNamespace struct{}
|
|
@@ -51,6 +53,22 @@ func (metadataCommentTagFactoryNamespace) Analyze(props struct {
|
|
|
51
53
|
continue
|
|
52
54
|
}
|
|
53
55
|
for key, value := range tagger {
|
|
56
|
+
// An empty arm names a target the tag's value cannot be stated for; see
|
|
57
|
+
// metadataCommentTagFactory_bigint. It is an error only where that target
|
|
58
|
+
// occurs, and the other arms still apply to theirs.
|
|
59
|
+
if value != nil && len(value) == 0 {
|
|
60
|
+
for _, atomic := range props.Metadata.Atomics {
|
|
61
|
+
if atomic.Type == key {
|
|
62
|
+
text := ""
|
|
63
|
+
if len(tag.Text) != 0 {
|
|
64
|
+
text = tag.Text[0].Text
|
|
65
|
+
}
|
|
66
|
+
report(key + " value " + strings.TrimSpace(text) + " is not an int64 integer that a number represents exactly")
|
|
67
|
+
break
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
continue
|
|
71
|
+
}
|
|
54
72
|
filtered := []schemametadata.IMetadataTypeTag{}
|
|
55
73
|
for _, elem := range value {
|
|
56
74
|
filtered = append(filtered, elem)
|
|
@@ -230,37 +248,37 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
|
|
|
230
248
|
Report func(msg string) any
|
|
231
249
|
Value string
|
|
232
250
|
}) metadataCommentTagFactory_TagRecord {
|
|
233
|
-
value := metadataCommentTagFactory_parse_integer(struct {
|
|
251
|
+
value := metadataCommentTagFactory_value(metadataCommentTagFactory_parse_integer(struct {
|
|
234
252
|
Report func(msg string) any
|
|
235
253
|
Unsigned bool
|
|
236
254
|
Value string
|
|
237
|
-
}{Report: props.Report, Value: props.Value, Unsigned: true})
|
|
255
|
+
}{Report: props.Report, Value: props.Value, Unsigned: true}))
|
|
238
256
|
return metadataCommentTagFactory_TagRecord{"array": {
|
|
239
|
-
{Name: "MinItems<" + props.Value + ">", Target: "array", Kind: "minItems", Value: value, Validate: props.Value + " <= $input.length", Exclusive: metadataCommentTagFactory_exclusive("minItems"), Schema: map[string]any{"minItems": value}},
|
|
240
|
-
{Name: "MaxItems<" + props.Value + ">", Target: "array", Kind: "maxItems", Value: value, Validate: "$input.length <= " + props.Value, Exclusive: metadataCommentTagFactory_exclusive("maxItems"), Schema: map[string]any{"maxItems": value}},
|
|
257
|
+
{Name: "MinItems<" + props.Value + ">", Target: "array", Kind: "minItems", Value: value, Validate: metadataCommentTagFactory_splice(props.Value) + " <= $input.length", Exclusive: metadataCommentTagFactory_exclusive("minItems"), Schema: map[string]any{"minItems": value}},
|
|
258
|
+
{Name: "MaxItems<" + props.Value + ">", Target: "array", Kind: "maxItems", Value: value, Validate: "$input.length <= " + metadataCommentTagFactory_splice(props.Value), Exclusive: metadataCommentTagFactory_exclusive("maxItems"), Schema: map[string]any{"maxItems": value}},
|
|
241
259
|
}}
|
|
242
260
|
},
|
|
243
261
|
"minItems": func(props struct {
|
|
244
262
|
Report func(msg string) any
|
|
245
263
|
Value string
|
|
246
264
|
}) metadataCommentTagFactory_TagRecord {
|
|
247
|
-
value := metadataCommentTagFactory_parse_integer(struct {
|
|
265
|
+
value := metadataCommentTagFactory_value(metadataCommentTagFactory_parse_integer(struct {
|
|
248
266
|
Report func(msg string) any
|
|
249
267
|
Unsigned bool
|
|
250
268
|
Value string
|
|
251
|
-
}{Report: props.Report, Value: props.Value, Unsigned: true})
|
|
252
|
-
return metadataCommentTagFactory_TagRecord{"array": {{Name: "MinItems<" + props.Value + ">", Target: "array", Kind: "minItems", Value: value, Validate: props.Value + " <= $input.length", Exclusive: metadataCommentTagFactory_exclusive("minItems"), Schema: map[string]any{"minItems": value}}}}
|
|
269
|
+
}{Report: props.Report, Value: props.Value, Unsigned: true}))
|
|
270
|
+
return metadataCommentTagFactory_TagRecord{"array": {{Name: "MinItems<" + props.Value + ">", Target: "array", Kind: "minItems", Value: value, Validate: metadataCommentTagFactory_splice(props.Value) + " <= $input.length", Exclusive: metadataCommentTagFactory_exclusive("minItems"), Schema: map[string]any{"minItems": value}}}}
|
|
253
271
|
},
|
|
254
272
|
"maxItems": func(props struct {
|
|
255
273
|
Report func(msg string) any
|
|
256
274
|
Value string
|
|
257
275
|
}) metadataCommentTagFactory_TagRecord {
|
|
258
|
-
value := metadataCommentTagFactory_parse_integer(struct {
|
|
276
|
+
value := metadataCommentTagFactory_value(metadataCommentTagFactory_parse_integer(struct {
|
|
259
277
|
Report func(msg string) any
|
|
260
278
|
Unsigned bool
|
|
261
279
|
Value string
|
|
262
|
-
}{Report: props.Report, Value: props.Value, Unsigned: true})
|
|
263
|
-
return metadataCommentTagFactory_TagRecord{"array": {{Name: "MaxItems<" + props.Value + ">", Target: "array", Kind: "maxItems", Value: value, Validate: "$input.length <= " + props.Value, Exclusive: metadataCommentTagFactory_exclusive("maxItems"), Schema: map[string]any{"maxItems": value}}}}
|
|
280
|
+
}{Report: props.Report, Value: props.Value, Unsigned: true}))
|
|
281
|
+
return metadataCommentTagFactory_TagRecord{"array": {{Name: "MaxItems<" + props.Value + ">", Target: "array", Kind: "maxItems", Value: value, Validate: "$input.length <= " + metadataCommentTagFactory_splice(props.Value), Exclusive: metadataCommentTagFactory_exclusive("maxItems"), Schema: map[string]any{"maxItems": value}}}}
|
|
264
282
|
},
|
|
265
283
|
"uniqueItems": func(props struct {
|
|
266
284
|
Report func(msg string) any
|
|
@@ -273,25 +291,25 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
|
|
|
273
291
|
Report func(msg string) any
|
|
274
292
|
Value string
|
|
275
293
|
}) metadataCommentTagFactory_TagRecord {
|
|
276
|
-
return metadataCommentTagFactory_numeric(props, "Minimum", "minimum", props.Value+" <= $input", props.Value+" <= $input")
|
|
294
|
+
return metadataCommentTagFactory_numeric(props, "Minimum", "minimum", metadataCommentTagFactory_splice(props.Value)+" <= $input", metadataCommentTagFactory_splice_integer(props.Value)+" <= $input")
|
|
277
295
|
},
|
|
278
296
|
"maximum": func(props struct {
|
|
279
297
|
Report func(msg string) any
|
|
280
298
|
Value string
|
|
281
299
|
}) metadataCommentTagFactory_TagRecord {
|
|
282
|
-
return metadataCommentTagFactory_numeric(props, "Maximum", "maximum", "$input <= "+props.Value, "$input <= "+props.Value)
|
|
300
|
+
return metadataCommentTagFactory_numeric(props, "Maximum", "maximum", "$input <= "+metadataCommentTagFactory_splice(props.Value), "$input <= "+metadataCommentTagFactory_splice_integer(props.Value))
|
|
283
301
|
},
|
|
284
302
|
"exclusiveMinimum": func(props struct {
|
|
285
303
|
Report func(msg string) any
|
|
286
304
|
Value string
|
|
287
305
|
}) metadataCommentTagFactory_TagRecord {
|
|
288
|
-
return metadataCommentTagFactory_numeric(props, "ExclusiveMinimum", "exclusiveMinimum", props.Value+" < $input", props.Value+" < $input")
|
|
306
|
+
return metadataCommentTagFactory_numeric(props, "ExclusiveMinimum", "exclusiveMinimum", metadataCommentTagFactory_splice(props.Value)+" < $input", metadataCommentTagFactory_splice_integer(props.Value)+" < $input")
|
|
289
307
|
},
|
|
290
308
|
"exclusiveMaximum": func(props struct {
|
|
291
309
|
Report func(msg string) any
|
|
292
310
|
Value string
|
|
293
311
|
}) metadataCommentTagFactory_TagRecord {
|
|
294
|
-
return metadataCommentTagFactory_numeric(props, "ExclusiveMaximum", "exclusiveMaximum", "$input < "+props.Value, "$input < "+props.Value)
|
|
312
|
+
return metadataCommentTagFactory_numeric(props, "ExclusiveMaximum", "exclusiveMaximum", "$input < "+metadataCommentTagFactory_splice(props.Value), "$input < "+metadataCommentTagFactory_splice_integer(props.Value))
|
|
295
313
|
},
|
|
296
314
|
"multipleOf": func(props struct {
|
|
297
315
|
Report func(msg string) any
|
|
@@ -303,7 +321,7 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
|
|
|
303
321
|
// answers a different question than the `multipleOf` keyword this tag emits.
|
|
304
322
|
// The bigint arm needs no helper: a bigint remainder is already exact.
|
|
305
323
|
// `_isMultipleOf` first shipped in 13.1.19; see the doc comment above.
|
|
306
|
-
return metadataCommentTagFactory_numeric(props, "MultipleOf", "multipleOf", "$importInternal(\"_isMultipleOf\")($input, "+props.Value+")", "$input % "+props.Value+"n === 0n")
|
|
324
|
+
return metadataCommentTagFactory_numeric(props, "MultipleOf", "multipleOf", "$importInternal(\"_isMultipleOf\")($input, "+metadataCommentTagFactory_splice(props.Value)+")", "$input % "+metadataCommentTagFactory_splice_integer(props.Value)+"n === 0n")
|
|
307
325
|
},
|
|
308
326
|
"format": func(props struct {
|
|
309
327
|
Report func(msg string) any
|
|
@@ -335,8 +353,8 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
|
|
|
335
353
|
// The comparison helpers keep that code-point walk but stop when the
|
|
336
354
|
// declared boundary already determines the answer.
|
|
337
355
|
return metadataCommentTagFactory_TagRecord{"string": {
|
|
338
|
-
{Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: "$importInternal(\"_stringLengthGte\")($input, " + props.Value + ")", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}},
|
|
339
|
-
{Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$importInternal(\"_stringLengthLte\")($input, " + props.Value + ")", Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}},
|
|
356
|
+
{Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: "$importInternal(\"_stringLengthGte\")($input, " + metadataCommentTagFactory_splice(props.Value) + ")", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}},
|
|
357
|
+
{Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$importInternal(\"_stringLengthLte\")($input, " + metadataCommentTagFactory_splice(props.Value) + ")", Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}},
|
|
340
358
|
}}
|
|
341
359
|
},
|
|
342
360
|
"minLength": func(props struct {
|
|
@@ -344,14 +362,14 @@ var metadataCommentTagFactory_PARSER = map[string]metadataCommentTagFactory_pars
|
|
|
344
362
|
Value string
|
|
345
363
|
}) metadataCommentTagFactory_TagRecord {
|
|
346
364
|
value := metadataCommentTagFactory_parse_number(props)
|
|
347
|
-
return metadataCommentTagFactory_TagRecord{"string": {{Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: "$importInternal(\"_stringLengthGte\")($input, " + props.Value + ")", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}}}}
|
|
365
|
+
return metadataCommentTagFactory_TagRecord{"string": {{Name: "MinLength<" + props.Value + ">", Target: "string", Kind: "minLength", Value: value, Validate: "$importInternal(\"_stringLengthGte\")($input, " + metadataCommentTagFactory_splice(props.Value) + ")", Exclusive: metadataCommentTagFactory_exclusive("minLength"), Schema: map[string]any{"minLength": value}}}}
|
|
348
366
|
},
|
|
349
367
|
"maxLength": func(props struct {
|
|
350
368
|
Report func(msg string) any
|
|
351
369
|
Value string
|
|
352
370
|
}) metadataCommentTagFactory_TagRecord {
|
|
353
371
|
value := metadataCommentTagFactory_parse_number(props)
|
|
354
|
-
return metadataCommentTagFactory_TagRecord{"string": {{Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$importInternal(\"_stringLengthLte\")($input, " + props.Value + ")", Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}}}}
|
|
372
|
+
return metadataCommentTagFactory_TagRecord{"string": {{Name: "MaxLength<" + props.Value + ">", Target: "string", Kind: "maxLength", Value: value, Validate: "$importInternal(\"_stringLengthLte\")($input, " + metadataCommentTagFactory_splice(props.Value) + ")", Exclusive: metadataCommentTagFactory_exclusive("maxLength"), Schema: map[string]any{"maxLength": value}}}}
|
|
355
373
|
},
|
|
356
374
|
}
|
|
357
375
|
|
|
@@ -480,31 +498,161 @@ func metadataCommentTagFactory_numeric(props struct {
|
|
|
480
498
|
Value string
|
|
481
499
|
}, name string, kind string, numberValidate string, bigintValidate string) metadataCommentTagFactory_TagRecord {
|
|
482
500
|
number := metadataCommentTagFactory_parse_number(props)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
501
|
+
if number == nil {
|
|
502
|
+
// Reported as an invalid or non-finite number already; a record would only
|
|
503
|
+
// add "requires number type" on a bigint property, which is not the fault.
|
|
504
|
+
return metadataCommentTagFactory_TagRecord{}
|
|
505
|
+
}
|
|
488
506
|
exclusive := metadataCommentTagFactory_exclusive(kind)
|
|
489
507
|
record := metadataCommentTagFactory_TagRecord{
|
|
490
508
|
"number": {{Name: name + "<" + props.Value + ">", Target: "number", Kind: kind, Value: number, Validate: numberValidate, Exclusive: exclusive, Schema: map[string]any{kind: number}}},
|
|
491
509
|
}
|
|
492
|
-
|
|
493
|
-
|
|
510
|
+
integer, numeric, ok := metadataCommentTagFactory_bigint(props.Value)
|
|
511
|
+
if ok {
|
|
512
|
+
record["bigint"] = []schemametadata.IMetadataTypeTag{{Name: name + "<" + props.Value + "n>", Target: "bigint", Kind: kind, Value: integer, Validate: bigintValidate, Exclusive: exclusive, Schema: map[string]any{kind: number}}}
|
|
513
|
+
} else if numeric {
|
|
514
|
+
// An empty arm: the value bounds a bigint, but not with any value this tag
|
|
515
|
+
// can state. `Analyze` reports it where a bigint occurs, so the bigint part
|
|
516
|
+
// of a `number | bigint` property is never left unconstrained silently.
|
|
517
|
+
record["bigint"] = []schemametadata.IMetadataTypeTag{}
|
|
494
518
|
}
|
|
495
519
|
return record
|
|
496
520
|
}
|
|
497
521
|
|
|
522
|
+
// metadataCommentTagFactory_bigint reads a numeric tag's value for its bigint
|
|
523
|
+
// arm.
|
|
524
|
+
//
|
|
525
|
+
// Consumers of that arm hold the value as a double: the bound validators splice
|
|
526
|
+
// a number literal, and the schema `random` draws from is numeric. The written
|
|
527
|
+
// integer survives them only when a double represents it exactly, so that is
|
|
528
|
+
// what the arm admits, within the int64 range its value is carried in
|
|
529
|
+
// (samchon/typia#2352). Reading any integer through a double instead enforced
|
|
530
|
+
// `@minimum 9007199254740993` as 9007199254740992, and let `random` generate
|
|
531
|
+
// values the exact `@multipleOf` check rejects (samchon/typia#2457).
|
|
532
|
+
//
|
|
533
|
+
// numeric reports whether the text writes a finite number at all. One that is
|
|
534
|
+
// no such integer -- `1.5`, `5.0000000000000001`, `9007199254740993`, or
|
|
535
|
+
// `1e-1000001` -- is a bigint bound the tag cannot state, while text that is no
|
|
536
|
+
// finite number has already been reported by the number arm.
|
|
537
|
+
func metadataCommentTagFactory_bigint(text string) (value int64, numeric bool, ok bool) {
|
|
538
|
+
if reading := nativeutils.NumberUtil.Read(text); reading.Numeric == false || reading.Finite == false {
|
|
539
|
+
return 0, false, false
|
|
540
|
+
}
|
|
541
|
+
integer, exact := metadataCommentTagFactory_integer(text)
|
|
542
|
+
if exact == false || integer.IsInt64() == false {
|
|
543
|
+
return 0, true, false
|
|
544
|
+
}
|
|
545
|
+
if _, accuracy := new(big.Float).SetInt(integer).Float64(); accuracy != big.Exact {
|
|
546
|
+
return 0, true, false
|
|
547
|
+
}
|
|
548
|
+
return integer.Int64(), true, true
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// metadataCommentTagFactory_integer is the integer a finite numeric text
|
|
552
|
+
// writes exactly, if it writes one whose double lies within the int64 range. A
|
|
553
|
+
// few integers just below -2^63 round to it and pass; the bigint record checks
|
|
554
|
+
// the integer itself.
|
|
555
|
+
//
|
|
556
|
+
// Its double, which `NumberUtil.Read` rounds correctly, settles most texts
|
|
557
|
+
// without expanding them. A non-integer double comes only from a non-integer
|
|
558
|
+
// text, and a zero from a text with a non-zero digit is the underflow of a
|
|
559
|
+
// non-integer. A double at 2^63 or above, or below -2^63, is refused too: the
|
|
560
|
+
// int64 texts that round up to 2^63 (from 9223372036854775296) are no doubles,
|
|
561
|
+
// so no bigint record could hold them anyway. `big.Rat` expands only what
|
|
562
|
+
// remains, so a short text such as `@minimum 1e-1000000` costs nothing, on any
|
|
563
|
+
// target.
|
|
564
|
+
func metadataCommentTagFactory_integer(text string) (*big.Int, bool) {
|
|
565
|
+
reading := nativeutils.NumberUtil.Read(text)
|
|
566
|
+
if reading.Numeric == false ||
|
|
567
|
+
reading.Finite == false ||
|
|
568
|
+
reading.Value != math.Trunc(reading.Value) ||
|
|
569
|
+
reading.Value < metadataCommentTagFactory_INT64_MINIMUM ||
|
|
570
|
+
reading.Value >= metadataCommentTagFactory_INT64_EXCLUSIVE_MAXIMUM {
|
|
571
|
+
return nil, false
|
|
572
|
+
}
|
|
573
|
+
if reading.Value == 0 {
|
|
574
|
+
// A zero writes zero only when no digit before its exponent is non-zero;
|
|
575
|
+
// otherwise it underflowed. A radix zero has no `e`, being all zeros.
|
|
576
|
+
mantissa := text
|
|
577
|
+
if index := strings.IndexAny(text, "eE"); index != -1 {
|
|
578
|
+
mantissa = text[:index]
|
|
579
|
+
}
|
|
580
|
+
if strings.ContainsAny(mantissa, "123456789") {
|
|
581
|
+
return nil, false
|
|
582
|
+
}
|
|
583
|
+
return big.NewInt(0), true
|
|
584
|
+
}
|
|
585
|
+
rational, ok := nativeutils.NumberUtil.Rational(text)
|
|
586
|
+
if ok == false || rational.IsInt() == false {
|
|
587
|
+
return nil, false
|
|
588
|
+
}
|
|
589
|
+
return rational.Num(), true
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// metadataCommentTagFactory_value unwraps a parsed count into the record's
|
|
593
|
+
// value and schema. Storing the pointer itself let every consumer that formats
|
|
594
|
+
// a value print an address: strict LLM schemas described `@minItems 2` as
|
|
595
|
+
// `@minItems 0xc000012345`.
|
|
596
|
+
func metadataCommentTagFactory_value(value *int64) any {
|
|
597
|
+
if value == nil {
|
|
598
|
+
return nil
|
|
599
|
+
}
|
|
600
|
+
return *value
|
|
601
|
+
}
|
|
602
|
+
|
|
498
603
|
func metadataCommentTagFactory_parse_number(props struct {
|
|
499
604
|
Report func(msg string) any
|
|
500
605
|
Value string
|
|
501
606
|
}) any {
|
|
502
|
-
|
|
503
|
-
if
|
|
607
|
+
reading := nativeutils.NumberUtil.Read(props.Value)
|
|
608
|
+
if reading.Numeric == false {
|
|
504
609
|
props.Report("invalid number")
|
|
505
610
|
return nil
|
|
506
611
|
}
|
|
507
|
-
|
|
612
|
+
// A JSON Schema keyword such as `minimum` must be a JSON number, and JSON has
|
|
613
|
+
// no spelling for an infinity (samchon/typia#2452).
|
|
614
|
+
if reading.Finite == false {
|
|
615
|
+
props.Report("non-finite number")
|
|
616
|
+
return nil
|
|
617
|
+
}
|
|
618
|
+
return reading.Value
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// metadataCommentTagFactory_splice respells a numeric tag value for the
|
|
622
|
+
// validator the record splices it into (`16 <= $input`, `$input % 1000n`).
|
|
623
|
+
//
|
|
624
|
+
// The spliced text has to be JavaScript for the value the tag was read as, in
|
|
625
|
+
// both the number and the bigint target. The source spelling need not be:
|
|
626
|
+
// `0x10` happens to be, but `1e3`, `1.0`, `+5`, and `007` are integers whose
|
|
627
|
+
// bigint splice (`1e3n`, `1.0n`, `+5n`, `007n`) is no valid BigInt expression
|
|
628
|
+
// (samchon/typia#2442). An integer spelling keeps its digits as written, so the
|
|
629
|
+
// splice never rounds where the source did not: `Number()` would read
|
|
630
|
+
// `9007199254740993` as ...992, while the bigint `@multipleOf` check appends
|
|
631
|
+
// `n` to the digits and compares exactly.
|
|
632
|
+
// Text that does not read as a finite number is passed through; the parser
|
|
633
|
+
// reports it and nothing is emitted.
|
|
634
|
+
func metadataCommentTagFactory_splice(value string) string {
|
|
635
|
+
if integer, ok := nativeutils.NumberUtil.Integer(value); ok {
|
|
636
|
+
return integer.String()
|
|
637
|
+
}
|
|
638
|
+
if reading := nativeutils.NumberUtil.Read(value); reading.Numeric && reading.Finite {
|
|
639
|
+
return nativeutils.NumberUtil.String(reading.Value)
|
|
640
|
+
}
|
|
641
|
+
return value
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// metadataCommentTagFactory_splice_integer respells a tag value for a bigint
|
|
645
|
+
// validator: the exact digits of the integer the text writes, whatever its
|
|
646
|
+
// spelling, for every value a bigint record holds. `1.152921504606846976e18`
|
|
647
|
+
// writes 2^60, while its double spells 1152921504606847000, which spliced
|
|
648
|
+
// before an `n` would check a different integer (samchon/typia#2457). Text
|
|
649
|
+
// that writes no integer has no bigint record, and falls back to the number
|
|
650
|
+
// splice.
|
|
651
|
+
func metadataCommentTagFactory_splice_integer(value string) string {
|
|
652
|
+
if integer, ok := metadataCommentTagFactory_integer(value); ok {
|
|
653
|
+
return integer.String()
|
|
654
|
+
}
|
|
655
|
+
return metadataCommentTagFactory_splice(value)
|
|
508
656
|
}
|
|
509
657
|
|
|
510
658
|
func metadataCommentTagFactory_parse_integer(props struct {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
package factories
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"math"
|
|
5
|
+
"testing"
|
|
6
|
+
|
|
7
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestExpressionFactoryNumberSpellsNonFiniteValues verifies number literals for
|
|
11
|
+
// NaN and the infinities.
|
|
12
|
+
//
|
|
13
|
+
// ExpressionFactory.Number built the literal text with `fmt.Sprint`, which
|
|
14
|
+
// spells positive infinity `+Inf` and prints the magnitude of negative infinity
|
|
15
|
+
// as `Inf`. Both reached the emit as identifiers JavaScript does not declare, so
|
|
16
|
+
// every emitted schema, validator, or random bound carrying one threw
|
|
17
|
+
// `ReferenceError: Inf is not defined` on its first run (samchon/typia#2452).
|
|
18
|
+
// The expected shapes are the JavaScript globals TypeScript's own factory
|
|
19
|
+
// prints. Finite values are the negative twin and must keep their literal.
|
|
20
|
+
//
|
|
21
|
+
// 1. Build numbers for NaN, positive and negative infinity.
|
|
22
|
+
// 2. Assert they are the `NaN` / `Infinity` identifiers, negated for -Infinity.
|
|
23
|
+
// 3. Assert finite values, negative ones, and zero keep numeric literals, with
|
|
24
|
+
// negative zero negated like any negative value rather than spelled `-0`
|
|
25
|
+
// inside one literal.
|
|
26
|
+
func TestExpressionFactoryNumberSpellsNonFiniteValues(t *testing.T) {
|
|
27
|
+
identifier := func(node *shimast.Node, name string) bool {
|
|
28
|
+
return node != nil && node.Kind == shimast.KindIdentifier && node.Text() == name
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if node := ExpressionFactory.Number(math.NaN()); identifier(node, "NaN") == false {
|
|
32
|
+
t.Fatalf("NaN should be the NaN identifier, got kind %v", node.Kind)
|
|
33
|
+
}
|
|
34
|
+
if node := ExpressionFactory.Number(math.Inf(1)); identifier(node, "Infinity") == false {
|
|
35
|
+
t.Fatalf("+Inf should be the Infinity identifier, got kind %v", node.Kind)
|
|
36
|
+
}
|
|
37
|
+
negative := ExpressionFactory.Number(math.Inf(-1))
|
|
38
|
+
if negative.Kind != shimast.KindPrefixUnaryExpression {
|
|
39
|
+
t.Fatalf("-Inf should be a negation, got kind %v", negative.Kind)
|
|
40
|
+
}
|
|
41
|
+
unary := negative.AsPrefixUnaryExpression()
|
|
42
|
+
if unary.Operator != shimast.KindMinusToken || identifier(unary.Operand, "Infinity") == false {
|
|
43
|
+
t.Fatal("-Inf should negate the Infinity identifier")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for _, item := range []struct {
|
|
47
|
+
value any
|
|
48
|
+
negative bool
|
|
49
|
+
text string
|
|
50
|
+
}{
|
|
51
|
+
{3, false, "3"},
|
|
52
|
+
{1.5, false, "1.5"},
|
|
53
|
+
{int64(0), false, "0"},
|
|
54
|
+
{-12, true, "12"},
|
|
55
|
+
{-2.5, true, "2.5"},
|
|
56
|
+
{math.Copysign(0, -1), true, "0"},
|
|
57
|
+
} {
|
|
58
|
+
node := ExpressionFactory.Number(item.value)
|
|
59
|
+
if item.negative {
|
|
60
|
+
if node.Kind != shimast.KindPrefixUnaryExpression {
|
|
61
|
+
t.Fatalf("%v should be a negation, got kind %v", item.value, node.Kind)
|
|
62
|
+
}
|
|
63
|
+
node = node.AsPrefixUnaryExpression().Operand
|
|
64
|
+
}
|
|
65
|
+
if node.Kind != shimast.KindNumericLiteral || node.Text() != item.text {
|
|
66
|
+
t.Fatalf("%v should be the numeric literal %q, got kind %v", item.value, item.text, node.Kind)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
package factories
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"testing"
|
|
6
|
+
|
|
7
|
+
schemametadata "github.com/samchon/typia/packages/typia/native/core/schemas/metadata"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestMetadataCommentTagFactoryHoldsBigintTagsExact verifies a numeric comment
|
|
11
|
+
// tag states a bigint bound only when it can state it exactly.
|
|
12
|
+
//
|
|
13
|
+
// The bigint arm of `@minimum`, `@maximum`, `@exclusiveMinimum`,
|
|
14
|
+
// `@exclusiveMaximum`, and `@multipleOf` read its value through a double, so
|
|
15
|
+
// `@minimum 9007199254740993` was enforced as 9007199254740992: the bound
|
|
16
|
+
// validators splice a number literal JavaScript rounds, and `random` drew from
|
|
17
|
+
// the rounded schema while the `@multipleOf` check stayed exact
|
|
18
|
+
// (samchon/typia#2457). Every consumer of the bigint record holds its value as
|
|
19
|
+
// a double, so the record now admits an integer only when a double represents
|
|
20
|
+
// it exactly, within the int64 range of samchon/typia#2352, and splices its
|
|
21
|
+
// exact digits into the bigint check. A number target keeps reading the text
|
|
22
|
+
// as `Number()` does.
|
|
23
|
+
//
|
|
24
|
+
// 1. Admit integers a double represents exactly, whatever their spelling, and
|
|
25
|
+
// splice their exact digits into the bigint check.
|
|
26
|
+
// 2. Refuse every other finite value as a bigint bound: integers a double
|
|
27
|
+
// cannot represent, integers beyond int64, and non-integers, including
|
|
28
|
+
// ones `Number()` rounds to an integer.
|
|
29
|
+
// 3. Report a refused value on a bigint property, and on the bigint part of a
|
|
30
|
+
// `number | bigint` one, while a number property and the number part
|
|
31
|
+
// still take the tag, and report text that is no finite number once.
|
|
32
|
+
func TestMetadataCommentTagFactoryHoldsBigintTagsExact(t *testing.T) {
|
|
33
|
+
//----
|
|
34
|
+
// 1. exact integers
|
|
35
|
+
//----
|
|
36
|
+
for _, item := range []struct {
|
|
37
|
+
text string
|
|
38
|
+
value int64
|
|
39
|
+
}{
|
|
40
|
+
{"9007199254740991", 9007199254740991},
|
|
41
|
+
{"9007199254740992", 9007199254740992},
|
|
42
|
+
{"18014398509481984", 18014398509481984}, // 2^54
|
|
43
|
+
{"54043195528445952", 54043195528445952}, // 3 * 2^54, although `String()` spells it ...950
|
|
44
|
+
{"1152921504606846976", 1152921504606846976}, // 2^60
|
|
45
|
+
{"1.152921504606846976e18", 1152921504606846976},
|
|
46
|
+
{"-9007199254740992", -9007199254740992},
|
|
47
|
+
{"1e3", 1000},
|
|
48
|
+
{"0x10", 16},
|
|
49
|
+
{"-0", 0},
|
|
50
|
+
{"0e999999999", 0},
|
|
51
|
+
{"0E5", 0},
|
|
52
|
+
{"0e99999999999999999999", 0}, // an exponent `big.Rat` cannot parse
|
|
53
|
+
{"0x0", 0},
|
|
54
|
+
{"10000000000000000", 10000000000000000},
|
|
55
|
+
} {
|
|
56
|
+
value, numeric, ok := metadataCommentTagFactory_bigint(item.text)
|
|
57
|
+
if ok == false || numeric == false || value != item.value {
|
|
58
|
+
t.Fatalf("%s must be the bigint %d, got %d (numeric=%v ok=%v)", item.text, item.value, value, numeric, ok)
|
|
59
|
+
}
|
|
60
|
+
if spliced := metadataCommentTagFactory_splice_integer(item.text); spliced != fmt.Sprint(item.value) {
|
|
61
|
+
t.Fatalf("%s must splice into a bigint check as %d, got %s", item.text, item.value, spliced)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//----
|
|
66
|
+
// 2. finite values no bigint tag states, and text that is no number
|
|
67
|
+
//----
|
|
68
|
+
for _, text := range []string{
|
|
69
|
+
"9007199254740993", // rounds to ...992
|
|
70
|
+
"9007199254740993.0", // the same integer, spelled with a point
|
|
71
|
+
"9.007199254740993e15", // and with an exponent
|
|
72
|
+
"-9007199254740993",
|
|
73
|
+
"0x20000000000001", // 2^53 + 1 in hexadecimal
|
|
74
|
+
"1152921504606847000", // `String(2 ** 60)`, which is not 2^60
|
|
75
|
+
"10000000000000000000", // beyond int64
|
|
76
|
+
"1.5",
|
|
77
|
+
"1e-3",
|
|
78
|
+
"5.0000000000000001", // `Number()` reads 5
|
|
79
|
+
"1e-400", // `Number()` reads 0
|
|
80
|
+
"1e-1000001", // underflows to 0, but writes no zero
|
|
81
|
+
} {
|
|
82
|
+
if _, numeric, ok := metadataCommentTagFactory_bigint(text); ok || numeric == false {
|
|
83
|
+
t.Fatalf("%s must be a finite value no bigint tag states (numeric=%v ok=%v)", text, numeric, ok)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for _, text := range []string{"Infinity", "abc", "1_000"} {
|
|
87
|
+
if _, numeric, ok := metadataCommentTagFactory_bigint(text); ok || numeric {
|
|
88
|
+
t.Fatalf("%s is no finite number (numeric=%v ok=%v)", text, numeric, ok)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//----
|
|
93
|
+
// 3. where the refusal is reported
|
|
94
|
+
//----
|
|
95
|
+
analyze := func(types []string, name string, text string) (*schemametadata.MetadataSchema, []string) {
|
|
96
|
+
atomics := []*schemametadata.MetadataAtomic{}
|
|
97
|
+
for _, typ := range types {
|
|
98
|
+
atomics = append(atomics, schemametadata.MetadataAtomic_create(schemametadata.MetadataAtomic{Type: typ}))
|
|
99
|
+
}
|
|
100
|
+
meta := schemametadata.MetadataSchema_create(schemametadata.MetadataSchema{Atomics: atomics})
|
|
101
|
+
errors := []MetadataFactory_IError{}
|
|
102
|
+
MetadataCommentTagFactory.Analyze(struct {
|
|
103
|
+
Errors *[]MetadataFactory_IError
|
|
104
|
+
Metadata *schemametadata.MetadataSchema
|
|
105
|
+
Tags []schemametadata.IJsDocTagInfo
|
|
106
|
+
Explore MetadataFactory_IExplore
|
|
107
|
+
}{
|
|
108
|
+
Errors: &errors,
|
|
109
|
+
Metadata: meta,
|
|
110
|
+
Tags: []schemametadata.IJsDocTagInfo{{Name: name, Text: []schemametadata.IJsDocTagInfo_IText{{Text: text}}}},
|
|
111
|
+
})
|
|
112
|
+
messages := []string{}
|
|
113
|
+
for _, err := range errors {
|
|
114
|
+
messages = append(messages, err.Messages...)
|
|
115
|
+
}
|
|
116
|
+
return meta, messages
|
|
117
|
+
}
|
|
118
|
+
refusal := "bigint value 9007199254740993 is not an int64 integer that a number represents exactly"
|
|
119
|
+
for _, name := range []string{"minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum", "multipleOf"} {
|
|
120
|
+
if _, messages := analyze([]string{"bigint"}, name, "9007199254740993"); len(messages) != 1 || messages[0] != refusal {
|
|
121
|
+
t.Fatalf("@%s on a bigint must report the refusal alone, got %#v", name, messages)
|
|
122
|
+
}
|
|
123
|
+
meta, messages := analyze([]string{"number"}, name, "9007199254740993")
|
|
124
|
+
if len(messages) != 0 || len(meta.Atomics[0].Tags) != 1 {
|
|
125
|
+
t.Fatalf("@%s on a number must apply, got %#v", name, messages)
|
|
126
|
+
}
|
|
127
|
+
meta, messages = analyze([]string{"number", "bigint"}, name, "9007199254740993")
|
|
128
|
+
if len(messages) != 1 || messages[0] != refusal {
|
|
129
|
+
t.Fatalf("@%s on number | bigint must report the bigint part, got %#v", name, messages)
|
|
130
|
+
}
|
|
131
|
+
if len(meta.Atomics[0].Tags) != 1 || len(meta.Atomics[1].Tags) != 0 {
|
|
132
|
+
t.Fatalf("@%s on number | bigint must constrain the number part only", name)
|
|
133
|
+
}
|
|
134
|
+
if meta, messages := analyze([]string{"bigint"}, name, "9007199254740992"); len(messages) != 0 || len(meta.Atomics[0].Tags) != 1 {
|
|
135
|
+
t.Fatalf("@%s 9007199254740992 on a bigint must apply, got %#v", name, messages)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// A value `Number()` rounds to an integer still names no bigint bound: the
|
|
139
|
+
// number part takes it as 5, and the bigint part is reported, not dropped.
|
|
140
|
+
meta, messages := analyze([]string{"number", "bigint"}, "minimum", "5.0000000000000001")
|
|
141
|
+
if len(messages) != 1 || messages[0] != "bigint value 5.0000000000000001 is not an int64 integer that a number represents exactly" {
|
|
142
|
+
t.Fatalf("@minimum 5.0000000000000001 on number | bigint must report the bigint part, got %#v", messages)
|
|
143
|
+
}
|
|
144
|
+
if len(meta.Atomics[0].Tags) != 1 || meta.Atomics[0].Tags[0][0].Validate != "5 <= $input" || len(meta.Atomics[1].Tags) != 0 {
|
|
145
|
+
t.Fatal("@minimum 5.0000000000000001 on number | bigint must constrain the number part only")
|
|
146
|
+
}
|
|
147
|
+
if _, messages := analyze([]string{"bigint"}, "minimum", "1.5"); len(messages) != 1 || messages[0] != "bigint value 1.5 is not an int64 integer that a number represents exactly" {
|
|
148
|
+
t.Fatalf("@minimum 1.5 on a bigint must be refused, got %#v", messages)
|
|
149
|
+
}
|
|
150
|
+
if _, messages := analyze([]string{"number", "bigint"}, "minimum", "1e-1000001"); len(messages) != 1 || messages[0] != "bigint value 1e-1000001 is not an int64 integer that a number represents exactly" {
|
|
151
|
+
t.Fatalf("@minimum 1e-1000001 on number | bigint must report the bigint part, got %#v", messages)
|
|
152
|
+
}
|
|
153
|
+
// Text that is no finite number is reported once, as such, on any target.
|
|
154
|
+
for _, item := range []struct {
|
|
155
|
+
text string
|
|
156
|
+
message string
|
|
157
|
+
}{
|
|
158
|
+
{"abc", "invalid number"},
|
|
159
|
+
{"Infinity", "non-finite number"},
|
|
160
|
+
{"1e400", "non-finite number"},
|
|
161
|
+
} {
|
|
162
|
+
for _, types := range [][]string{{"bigint"}, {"number", "bigint"}} {
|
|
163
|
+
if _, messages := analyze(types, "minimum", item.text); len(messages) != 1 || messages[0] != item.message {
|
|
164
|
+
t.Fatalf("@minimum %s on %v must report %q alone, got %#v", item.text, types, item.message, messages)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|