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

Limitation for Long type finally removed: support for integer types #171

Merged
merged 7 commits into from
Dec 28, 2022

Conversation

orchestr7
Copy link
Owner

@orchestr7 orchestr7 commented Dec 27, 2022

What's done:

  • removed limitation for integers to be long
  • TOML spec: Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be accepted and handled losslessly. If an integer cannot be represented losslessly, an error must be thrown
  • so right now we support Byte, Short and Int. But if there is an overflow, we throw an exception
  • BREAKING CHANGE: CastException removed and now unified with IllegalTypeException

### What's done:
- removed limitation for integers to be long
- TOML spec: Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be accepted and handled losslessly. If an integer cannot be represented losslessly, an error must be thrown
- so right now we support Byte, Short and Int. But if there is an overflow, we throw an exception
@orchestr7 orchestr7 requested a review from NightEule5 December 27, 2022 14:14
@orchestr7 orchestr7 marked this pull request as draft December 27, 2022 14:15
Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ktlint found more than 10 potential problems in the proposed changes. Check the Files changed tab for more details.

### What's done:
- removed limitation for integers to be long
- TOML spec: Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be accepted and handled losslessly. If an integer cannot be represented losslessly, an error must be thrown
- so right now we support Byte, Short and Int. But if there is an overflow, we throw an exception
### What's done:
- removed limitation for integers to be long
- TOML spec: Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be accepted and handled losslessly. If an integer cannot be represented losslessly, an error must be thrown
- so right now we support Byte, Short and Int. But if there is an overflow, we throw an exception
@orchestr7 orchestr7 added the enhancement New feature or request label Dec 28, 2022
@orchestr7 orchestr7 linked an issue Dec 28, 2022 that may be closed by this pull request
@orchestr7 orchestr7 marked this pull request as ready for review December 28, 2022 09:32
@orchestr7
Copy link
Owner Author

@aSemy @NightEule5 @BOOMeranGG @nulls could you please have a look?

### What's done:
- removed limitation for integers to be long
- TOML spec: Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be accepted and handled losslessly. If an integer cannot be represented losslessly, an error must be thrown
- so right now we support Byte, Short and Int. But if there is an overflow, we throw an exception
Comment on lines +17 to +19
// Unsigned values are not supported now, and I think
// that will not be supported, because TOML spec says the following:
// Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be accepted and handled losslessly.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind elaborating on why unsigneds can't be supported?

I'd recommend making a new GitHub issue 'support unsigned ints' (I could make the issue if you like) and adding the link in the source code, then it's easier to track and follow progress.

Copy link
Owner Author

@orchestr7 orchestr7 Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind, but the main problem is related to the kotlinx.serialization. I cannot find decodeUInt in their library...
I will write it to the comments

Copy link
Collaborator

@aSemy aSemy Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's a little bit odd how KxS handles unsigneds.

KxS JSON handles them natively though https://github.com/Kotlin/kotlinx.serialization/blob/v1.4.1/docs/value-classes.md#unsigned-types-support-json-only

I suspect that they should 'just work' though, since they have serializers https://github.com/Kotlin/kotlinx.serialization/blob/v1.4.1/core/commonMain/src/kotlinx/serialization/internal/ValueClasses.kt

How KxS JSON handles them is

  1. unsigned numbers are value classes, so their SerialDescriptors are 'inline'
  2. it keeps a list of the 'SerialDescriptors' for all unsigned numbers
    https://github.com/Kotlin/kotlinx.serialization/blob/dc950f5098162a3f8dd742d04b95f9a0405470e1/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonEncoder.kt#L15-L24
  3. there's a specific function AbstractDecoder.decodeInline(...), that will handle the unsigned numbers
  4. then there's a specific decoder for the unsigned types https://github.com/Kotlin/kotlinx.serialization/blob/d7e58c2eeb02e1da87ad36d41ef25523fafb6935/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt#L367-L379

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need to add it then also... Yes, let's support it then :)
Looks like a workaround in KxS, looks like they forgot about unsigned in the very beginning

Comment on lines +96 to +98
): T = if (content in limits.min..limits.max) {
conversion(content)
} else {
Copy link
Collaborator

@aSemy aSemy Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code is based on my PR which used the MIN/MAX boundaries, but I checked the Kotlinx Serialization JSON decoder and I think it has a better way.

https://github.com/Kotlin/kotlinx.serialization/blob/d7e58c2eeb02e1da87ad36d41ef25523fafb6935/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt#L299-L304

  1. decode to Long
  2. convert to value.toInt()
  3. if the result is different, then throw an exception

It's less code, and I think easier to understand because it's inline, the logic isn't split up or abstracted

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only problem I see here is that comparing operation with limits can be easier than making a toInt() and than comparing... But anyway probably your variant is good enough.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

speaking about the idea - I actually asked a question on stack overflow about that and as well as I and you thought - everyone suggests to check boundaries: https://stackoverflow.com/questions/74510016/how-to-understand-if-there-was-an-integer-overflow-during-parsing-of-string-with :D

So probably, it is a good idea to have the most obvious solution

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I prefer the KxS JSON way with .toInt(), but the result is the same pick whatever you prefer :)

Copy link
Owner Author

@orchestr7 orchestr7 Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also funny thing that @NightEule5 suggested same solution as you initially here: #153 (comment) :D

### What's done:
- removed limitation for integers to be long
- TOML spec: Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be accepted and handled losslessly. If an integer cannot be represented losslessly, an error must be thrown
- so right now we support Byte, Short and Int. But if there is an overflow, we throw an exception
@orchestr7 orchestr7 merged commit d92f2d3 into main Dec 28, 2022
@orchestr7 orchestr7 deleted the feature/integer-values branch December 28, 2022 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support encoding/decoding non-Long numbers
4 participants