Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decode: allow integers to be unmarshaled into floats #841

Merged
merged 2 commits into from
Feb 9, 2023

Conversation

PotatoesFall
Copy link
Contributor

@PotatoesFall PotatoesFall commented Feb 7, 2023

This issue was raised and is described in #835

Float values do not require a floating point according to toml documentation: https://toml.io/en/v1.0.0#float

This PR allows integer toml values to be decoded into float64 and float32 fields.

There is no conversion check but as far as I can tell any int64 value can always be converted to a float32 or float64, albeit with potential loss of precision.

I am not sure I got the style right when it comes to tests - I was looking for test(s) where all possible types of values for a field are unmarshaled but found no such test.


stdout of ./ci.sh coverage -d v2 :

/tmp/tmp.MGcFIXUKIi ~/github.com/pelletier/go-toml
total:	(statements)	0.0%
~/github.com/pelletier/go-toml
/tmp/tmp.aycJKpzKVa ~/github.com/pelletier/go-toml
ok  	github.com/pelletier/go-toml/v2	0.026s	coverage: 86.3% of statements in ./...
ok  	github.com/pelletier/go-toml/v2/benchmark	0.467s	coverage: 41.5% of statements in ./...
?   	github.com/pelletier/go-toml/v2/cmd/gotoml-test-decoder	[no test files]
ok  	github.com/pelletier/go-toml/v2/cmd/jsontoml	0.007s	coverage: 5.1% of statements in ./...
ok  	github.com/pelletier/go-toml/v2/cmd/tomljson	0.007s	coverage: 17.6% of statements in ./...
ok  	github.com/pelletier/go-toml/v2/cmd/tomll	0.005s	coverage: 19.2% of statements in ./...
?   	github.com/pelletier/go-toml/v2/cmd/tomltestgen	[no test files]
?   	github.com/pelletier/go-toml/v2/internal/characters	[no test files]
ok  	github.com/pelletier/go-toml/v2/internal/cli	0.005s	coverage: 13.7% of statements in ./...
ok  	github.com/pelletier/go-toml/v2/internal/danger	0.005s	coverage: 1.0% of statements in ./...
ok  	github.com/pelletier/go-toml/v2/internal/imported_tests	0.007s	coverage: 55.2% of statements in ./...
?   	github.com/pelletier/go-toml/v2/internal/testsuite	[no test files]
ok  	github.com/pelletier/go-toml/v2/internal/tracker	0.005s	coverage: 0.1% of statements in ./...
ok  	github.com/pelletier/go-toml/v2/unstable	0.004s	coverage: 12.2% of statements in ./...
github.com/pelletier/go-toml/v2/cmd/jsontoml/main.go:36:		main						0.0%
github.com/pelletier/go-toml/v2/cmd/jsontoml/main.go:44:		convert						100.0%
github.com/pelletier/go-toml/v2/cmd/tomljson/main.go:38:		main						0.0%
github.com/pelletier/go-toml/v2/cmd/tomljson/main.go:46:		convert						100.0%
github.com/pelletier/go-toml/v2/cmd/tomll/main.go:38:			main						0.0%
github.com/pelletier/go-toml/v2/cmd/tomll/main.go:47:			convert						100.0%
github.com/pelletier/go-toml/v2/decode.go:12:				parseInteger					85.7%
github.com/pelletier/go-toml/v2/decode.go:29:				parseLocalDate					93.8%
github.com/pelletier/go-toml/v2/decode.go:64:				parseDecimalDigits				100.0%
github.com/pelletier/go-toml/v2/decode.go:78:				parseDateTime					97.4%
github.com/pelletier/go-toml/v2/decode.go:160:				parseLocalDateTime				100.0%
github.com/pelletier/go-toml/v2/decode.go:191:				parseLocalTime					97.9%
github.com/pelletier/go-toml/v2/decode.go:283:				parseFloat					100.0%
github.com/pelletier/go-toml/v2/decode.go:333:				parseIntHex					100.0%
github.com/pelletier/go-toml/v2/decode.go:347:				parseIntOct					100.0%
github.com/pelletier/go-toml/v2/decode.go:361:				parseIntBin					100.0%
github.com/pelletier/go-toml/v2/decode.go:375:				isSign						100.0%
github.com/pelletier/go-toml/v2/decode.go:379:				parseIntDec					100.0%
github.com/pelletier/go-toml/v2/decode.go:403:				checkAndRemoveUnderscoresIntegers		100.0%
github.com/pelletier/go-toml/v2/decode.go:452:				checkAndRemoveUnderscoresFloats			100.0%
github.com/pelletier/go-toml/v2/decode.go:514:				isValidDate					100.0%
github.com/pelletier/go-toml/v2/decode.go:537:				daysIn						100.0%
github.com/pelletier/go-toml/v2/decode.go:544:				isLeap						100.0%
github.com/pelletier/go-toml/v2/decode.go:548:				isDigit						100.0%
github.com/pelletier/go-toml/v2/errors.go:38:				Error						100.0%
github.com/pelletier/go-toml/v2/errors.go:43:				String						100.0%
github.com/pelletier/go-toml/v2/errors.go:60:				Error						100.0%
github.com/pelletier/go-toml/v2/errors.go:65:				String						100.0%
github.com/pelletier/go-toml/v2/errors.go:71:				Position					100.0%
github.com/pelletier/go-toml/v2/errors.go:77:				Key						100.0%
github.com/pelletier/go-toml/v2/errors.go:90:				wrapDecodeError					100.0%
github.com/pelletier/go-toml/v2/errors.go:173:				formatLineNumber				100.0%
github.com/pelletier/go-toml/v2/errors.go:179:				linesOfContext					100.0%
github.com/pelletier/go-toml/v2/errors.go:183:				beforeLines					100.0%
github.com/pelletier/go-toml/v2/errors.go:210:				afterLines					100.0%
github.com/pelletier/go-toml/v2/errors.go:238:				positionAtEnd					100.0%
github.com/pelletier/go-toml/v2/internal/characters/ascii.go:40:	InvalidAscii					100.0%
github.com/pelletier/go-toml/v2/internal/characters/utf8.go:12:		Zero						100.0%
github.com/pelletier/go-toml/v2/internal/characters/utf8.go:35:		Utf8TomlValidAlreadyEscaped			100.0%
github.com/pelletier/go-toml/v2/internal/characters/utf8.go:109:	Utf8ValidNext					100.0%
github.com/pelletier/go-toml/v2/internal/cli/cli.go:25:			Execute						0.0%
github.com/pelletier/go-toml/v2/internal/cli/cli.go:31:			main						100.0%
github.com/pelletier/go-toml/v2/internal/cli/cli.go:49:			run						100.0%
github.com/pelletier/go-toml/v2/internal/cli/cli.go:64:			runAllFilesInPlace				100.0%
github.com/pelletier/go-toml/v2/internal/cli/cli.go:74:			runFileInPlace					100.0%
github.com/pelletier/go-toml/v2/internal/danger/danger.go:11:		SubsliceOffset					92.3%
github.com/pelletier/go-toml/v2/internal/danger/danger.go:37:		BytesRange					100.0%
github.com/pelletier/go-toml/v2/internal/danger/danger.go:61:		Stride						100.0%
github.com/pelletier/go-toml/v2/internal/danger/typeid.go:18:		MakeTypeID					100.0%
github.com/pelletier/go-toml/v2/internal/tracker/key.go:12:		UpdateTable					100.0%
github.com/pelletier/go-toml/v2/internal/tracker/key.go:18:		UpdateArrayTable				100.0%
github.com/pelletier/go-toml/v2/internal/tracker/key.go:24:		Push						100.0%
github.com/pelletier/go-toml/v2/internal/tracker/key.go:32:		Pop						100.0%
github.com/pelletier/go-toml/v2/internal/tracker/key.go:40:		Key						100.0%
github.com/pelletier/go-toml/v2/internal/tracker/key.go:46:		reset						100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:20:		String						66.7%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:62:		reset						100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:87:		find						100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:97:		clear						90.9%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:115:		create						100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:140:		setExplicitFlag					100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:153:		CheckExpression					85.7%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:169:		checkTable					100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:222:		checkArrayTable					100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:270:		checkKeyValue					100.0%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:309:		checkArray					90.9%
github.com/pelletier/go-toml/v2/internal/tracker/seen.go:329:		checkInlineTable				100.0%
github.com/pelletier/go-toml/v2/localtime.go:19:			AsTime						100.0%
github.com/pelletier/go-toml/v2/localtime.go:24:			String						100.0%
github.com/pelletier/go-toml/v2/localtime.go:29:			MarshalText					100.0%
github.com/pelletier/go-toml/v2/localtime.go:34:			UnmarshalText					100.0%
github.com/pelletier/go-toml/v2/localtime.go:57:			String						100.0%
github.com/pelletier/go-toml/v2/localtime.go:72:			MarshalText					100.0%
github.com/pelletier/go-toml/v2/localtime.go:77:			UnmarshalText					100.0%
github.com/pelletier/go-toml/v2/localtime.go:96:			AsTime						100.0%
github.com/pelletier/go-toml/v2/localtime.go:101:			String						100.0%
github.com/pelletier/go-toml/v2/localtime.go:106:			MarshalText					100.0%
github.com/pelletier/go-toml/v2/localtime.go:111:			UnmarshalText					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:22:			Marshal						100.0%
github.com/pelletier/go-toml/v2/marshaler.go:47:			NewEncoder					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:60:			SetTablesInline					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:71:			SetArraysMultiline				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:79:			SetIndentSymbol					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:85:			SetIndentTables					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:155:			Encode						100.0%
github.com/pelletier/go-toml/v2/marshaler.go:212:			shiftKey					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:219:			setKey						100.0%
github.com/pelletier/go-toml/v2/marshaler.go:224:			clearKey					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:229:			isRoot						100.0%
github.com/pelletier/go-toml/v2/marshaler.go:233:			encode						100.0%
github.com/pelletier/go-toml/v2/marshaler.go:342:			isNil						100.0%
github.com/pelletier/go-toml/v2/marshaler.go:351:			shouldOmitEmpty					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:355:			encodeKv					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:381:			isEmptyValue					77.8%
github.com/pelletier/go-toml/v2/marshaler.go:401:			isEmptyStruct					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:431:			encodeString					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:439:			needsQuoting					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:450:			encodeLiteralString				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:458:			encodeQuotedString				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:518:			encodeUnquotedKey				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:522:			encodeTableHeader				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:546:			encodeKey					93.8%
github.com/pelletier/go-toml/v2/marshaler.go:580:			encodeMap					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:612:			sortEntriesByKey				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:629:			pushKV						100.0%
github.com/pelletier/go-toml/v2/marshaler.go:639:			pushTable					75.0%
github.com/pelletier/go-toml/v2/marshaler.go:648:			walkStruct					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:702:			encodeStruct					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:710:			encodeComment					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:729:			isValidName					83.3%
github.com/pelletier/go-toml/v2/marshaler.go:752:			parseTag					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:783:			encodeTable					97.2%
github.com/pelletier/go-toml/v2/marshaler.go:848:			encodeTableInline				88.2%
github.com/pelletier/go-toml/v2/marshaler.go:882:			willConvertToTable				91.7%
github.com/pelletier/go-toml/v2/marshaler.go:907:			willConvertToTableOrArrayTable			100.0%
github.com/pelletier/go-toml/v2/marshaler.go:937:			encodeSlice					100.0%
github.com/pelletier/go-toml/v2/marshaler.go:953:			encodeSliceAsArrayTable				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:989:			encodeSliceAsArray				100.0%
github.com/pelletier/go-toml/v2/marshaler.go:1036:			indent						100.0%
github.com/pelletier/go-toml/v2/strict.go:18:				EnterTable					100.0%
github.com/pelletier/go-toml/v2/strict.go:26:				EnterArrayTable					100.0%
github.com/pelletier/go-toml/v2/strict.go:34:				EnterKeyValue					100.0%
github.com/pelletier/go-toml/v2/strict.go:42:				ExitKeyValue					100.0%
github.com/pelletier/go-toml/v2/strict.go:50:				MissingTable					100.0%
github.com/pelletier/go-toml/v2/strict.go:62:				MissingField					100.0%
github.com/pelletier/go-toml/v2/strict.go:74:				Error						100.0%
github.com/pelletier/go-toml/v2/strict.go:91:				keyLocation					88.9%
github.com/pelletier/go-toml/v2/unmarshaler.go:23:			Unmarshal					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:41:			NewDecoder					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:52:			DisallowUnknownFields				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:98:			Decode						100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:151:			typeMismatchError				80.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:160:			expr						100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:164:			nextExpr					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:172:			stashExpr					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:176:			arrayIndex					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:193:			FromParser					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:222:			fromParser					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:242:			handleRootExpression				95.7%
github.com/pelletier/go-toml/v2/unmarshaler.go:282:			handleArrayTable				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:289:			handleArrayTableCollectionLast			97.7%
github.com/pelletier/go-toml/v2/unmarshaler.go:356:			handleArrayTableCollection			89.3%
github.com/pelletier/go-toml/v2/unmarshaler.go:403:			handleKeyPart					92.8%
github.com/pelletier/go-toml/v2/unmarshaler.go:521:			handleArrayTablePart				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:533:			handleTable					92.3%
github.com/pelletier/go-toml/v2/unmarshaler.go:559:			handleKeyValues					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:594:			makeMapStringInterface				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:598:			makeSliceInterface				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:602:			handleTablePart					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:606:			tryTextUnmarshaler				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:625:			handleValue					94.1%
github.com/pelletier/go-toml/v2/unmarshaler.go:661:			unmarshalArray					97.6%
github.com/pelletier/go-toml/v2/unmarshaler.go:732:			unmarshalInlineTable				88.9%
github.com/pelletier/go-toml/v2/unmarshaler.go:768:			unmarshalDateTime				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:778:			unmarshalLocalDate				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:795:			unmarshalLocalTime				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:809:			unmarshalLocalDateTime				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:831:			unmarshalBool					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:846:			unmarshalFloat					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:882:			init						66.7%
github.com/pelletier/go-toml/v2/unmarshaler.go:889:			unmarshalInteger				95.2%
github.com/pelletier/go-toml/v2/unmarshaler.go:974:			unmarshalString					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:987:			handleKeyValue					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:1001:			handleKeyValueInner				100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:1011:			handleKeyValuePart				98.6%
github.com/pelletier/go-toml/v2/unmarshaler.go:1132:			initAndDereferencePointer			100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:1143:			fieldByIndex					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:1161:			structFieldPath					100.0%
github.com/pelletier/go-toml/v2/unmarshaler.go:1191:			forEachField					100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:28:			Next						100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:39:			IsLast						100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:44:			Node						100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:82:			Next						100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:94:			Child						100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:104:			Valid						100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:111:			Key						71.4%
github.com/pelletier/go-toml/v2/unstable/ast.go:129:			Value						100.0%
github.com/pelletier/go-toml/v2/unstable/ast.go:134:			Children					100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:11:			Iterator					0.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:19:			at						100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:27:			Valid						100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:36:			Tree						0.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:40:			NodeAt						100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:44:			Reset						100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:49:			Push						100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:55:			PushAndChain					100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:65:			AttachChild					100.0%
github.com/pelletier/go-toml/v2/unstable/builder.go:69:			Chain						100.0%
github.com/pelletier/go-toml/v2/unstable/kind.go:35:			String						22.2%
github.com/pelletier/go-toml/v2/unstable/parser.go:23:			Error						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:31:			NewParserError					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:64:			Data						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:71:			Range						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:79:			Raw						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:85:			Reset						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:99:			NextExpression					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:136:			Expression					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:141:			Error						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:145:			parseNewline					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:158:			parseExpression					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:200:			parseTable					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:209:			parseArrayTable					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:238:			parseStdTable					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:263:			parseKeyval					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:301:			parseVal					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:380:			atmost						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:388:			parseLiteralString				100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:397:			parseInlineTable				100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:458:			parseValArray					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:536:			parseOptionalWhitespaceCommentNewline		100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:565:			parseMultilineLiteralString			100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:584:			parseMultilineBasicString			98.5%
github.com/pelletier/go-toml/v2/unstable/parser.go:715:			parseKey					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:758:			parseSimpleKey					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:780:			parseBasicString				100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:875:			hexToRune					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:904:			parseWhitespace					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:914:			parseIntOrFloatOrDateTime			100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:962:			scanDateTime					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:1028:		scanIntOrFloat					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:1116:		isDigit						100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:1122:		isValidHexRune					100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:1129:		isValidOctalRune				100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:1133:		isValidBinaryRune				100.0%
github.com/pelletier/go-toml/v2/unstable/parser.go:1137:		expect						100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:5:			scanFollows					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:11:			scanFollowsMultilineBasicStringDelimiter	100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:15:			scanFollowsMultilineLiteralStringDelimiter	100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:19:			scanFollowsTrue					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:23:			scanFollowsFalse				100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:27:			scanFollowsInf					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:31:			scanFollowsNan					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:35:			scanUnquotedKey					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:46:			isUnquotedKeyChar				100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:50:			scanLiteralString				100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:71:			scanMultilineLiteralString			100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:128:		scanWindowsNewline				100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:141:		scanWhitespace					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:155:		scanComment					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:183:		scanBasicString					100.0%
github.com/pelletier/go-toml/v2/unstable/scanner.go:210:		scanMultilineBasicString			100.0%
total:									(statements)					97.0%
~/github.com/pelletier/go-toml

Results: v2 0.0% HEAD 97.0%
Delta: 97.0

@pelletier
Copy link
Owner

Thank you for the pull request! I was actually looking into this the other day. It's something that go-toml v1 used to allow, but I removed in go-toml v2. My reasoning was to avoid the loss of precision, and it's kind of a slippery slope to allow automatic conversions.

Can you point out in the specification where floats can be expressed like integers? I'm seeing this:

A float consists of an integer part (which follows the same rules as decimal integer values) followed by a fractional part and/or an exponent part.

Anyway, I think I'm coming around to it, given that encoding/json also permits it.

@PotatoesFall
Copy link
Contributor Author

PotatoesFall commented Feb 7, 2023

For me it's this one:

The decimal point, if used, must be surrounded by at least one digit on each side.

Specifically, the "if used" seems to imply that this is allowed.

On closer inspection, I do now see the "and/or" wording for decimal points and exponents, so this could refer to the case where we have an exponent, so I think I misread the docs, oops.

I don't think the comparison with encoding/json should have an influence here, since integers and floats are all the same number data type in JSON, unlike TOML.

That being said, I think it does make sense to allow this. There is no exact mapping of data types from TOML to go, so when unmarshalling I think the question should really be if the value can be assigned in a sensible way. In the case of integers, it generally is assignable to a float right?

The argument that we lose precision also seems inconsistent, since we also lose precision with floats:

  • most decimals cannot be expressed in binary
  • strconv.ParseFloat allows values with much higher precision than a float64 can hold, with 100 decimal digits for example.

@pelletier
Copy link
Owner

the question should really be if the value can be assigned in a sensible way. In the case of integers, it generally is assignable to a float right?

The thing that worries me is the precision loss for larger integers into floats (16777217 for float32 and 9007199254740993 for float64), since they start being less precise.

On the one hand, we could implement a bound check for those values and error out, or we could still do it and put it on the user to know what they are doing. One of the guidelines for this project is "no surprises", but I think both behaviors could be surprising. What do you think?

@PotatoesFall
Copy link
Contributor Author

PotatoesFall commented Feb 9, 2023

One of the guidelines for this project is "no surprises", but I think both behaviors could be surprising. What do you think?

I definitely agree with "no surprises" ! This does need some discussion. I'll invent some cases for illustration.

Surprise from current state

  • I take number values from JSON, expecting them to fit into a float. some of them do, some of them don't.
  • I have a value that I run through strconv.ParseFloat and it works fine. I put it in my toml and it says it's not a float.
  • I know that the value 1 fits into a float - I change a setting in a TOML config file from 1.5 to 1 and suddenly my service crashes.

Surprise from accepting all ints even with precision loss

  • I parse a TOML file and then export it. One of the values seems to have randomly changed.

Surprise from accepting ints but only without precision loss

  • I check to see if I can unmarshal an int into a float, it works and I build my program around this. One day the output of my toml config generator becomes too large and my program unexpectedly crashes.
  • I have a value that I run through strconv.ParseFloat and it works fine. I put it in my toml and it says it doesn't fit into a float64.
  • I can put all these values into a float:
    • ✔️ 12341234123412341234.12341234123412341234
    • ✔️ 12341234123412341234.0
    • ❌ 12341234123412341234

My personal and totally biased conclusion is that allowing ints and accepting precision loss has much less confusing surprises, and stays consistent with the behavior of the standard library. The latter is also the reason I think this is the best toml package out there.

EDIT upon writing this I realized that parsing values like 12341234123412341234 would fail since they don't fit into an int64, I pushed a fix for that.

@pelletier pelletier added the bug Issues describing a bug in go-toml. label Feb 9, 2023
@pelletier
Copy link
Owner

I think you're right, this seems like the right tradeoff for this lib. Thank you for the patch and the discussion!

@pelletier pelletier changed the title Allow ints to be unmarshaled into Floats Allow integers to be unmarshaled into floats Feb 9, 2023
@pelletier pelletier merged commit 9f57260 into pelletier:v2 Feb 9, 2023
@pelletier pelletier changed the title Allow integers to be unmarshaled into floats Decode: allow integers to be unmarshaled into floats Feb 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issues describing a bug in go-toml.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants