Long story short
Scrolling through Apple Advanced Swift Operators documentation I encountered something 'interesting’. The case is that I have never used it, and neither see in the production code of the project to which I participated so far. I thought, let's play with this ‘just in case’.
My attention was caught by following operators:
-
&+
- Overflow addition -
&-
- Overflow subtraction -
&*
- Overflow multiplication
All of them has been created to deal with Integer overflow scenarios in our codebase.
What is Integer Overflow you may ask... is situation where: "an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of digits – either higher than the maximum or lower than the minimum representable value.", we are going to explain it using example later on 😎.
I know that is not a common case, but it is good to have at least an idea that some API for handling mentioned computation in Swift is waiting for us. In this article we are going to focus only on &+
, since rest of them works in the simmilar manner.
YouTube already failed with Integer overflow
Researching quickly about the topic of Integer overflow, I found one funny story related to the YouTube website, and how they failed with assumption, that 'Int32' is going to be enough to store ‘view count’ for each video. Yep, they took the following assumption, and it was working for them for a long time, but suddenly crazy viral Psy’s “Gangnam Style” video came, and destroyed they ‘view count’ layout, because mentioned video exceeded value, which is able to be stored by 'Int32' variable, mean that music video surpassed over 2,147,483,647 views. After admitting that they made a mistake, the view counter type has been switched to 'Int64' which can store enormous 9,223,372,036,854,775,807 (gosh… that’s over 9 quintillion) views.
Scenarios in which simple +
operator is not enough
As an example we can use 'Int8' (signed 8-bit integer) type, which can store values from -128 to 127.
Normally if we do simple calculation like:
let a: Int8 = 127
let b: Int8 = 1
let sum = a + b // Compilation error 💥
We get a smart compilation error which says that: “Arithmetic operation ‘127 + 1’ (on type ‘Int8’) results in an overflow”, that is great! Seems that we are covered… unfortunately, compilator is going to help us only in that kind of static/obvious scenario, let's consider other scenarios where he won't be that helpful:
func makeValue() -> Int8 { 1 }
let a: Int8 = 127
let b: Int8 = makeValue()
let sum = a + b // Runtime error 💥
That scenario is giving us "Thread 1: Swift runtime failure: arithmetic overflow” runtime error, plus beautiful app crash. 😪
Overflow addition to the rescue!
We can consider once again the first example but with &+
operator in action.
let a: Int8 = 127
let b: Int8 = 1
let sum = a &+ b // Compilator is OK with this 🤓
As we can see, compilation went smoothly, but the result of the calculation is quite unexpected at the first glance, because after checking 'sum' constant value, we see -128, what the heck!
To understand better this operator, we can do manual 'Int8' addition with the deliberate overflow, bit by bit.
Taking our 127 number, which is the maximum positive value of 'Int8' type, where binary representation is: 0111 1111 , most significant bit (MSB) has 0 value (0 for positive, and 1 for negative numbers). And 'Int8(1)' binary representation is: 0000 0001. Knowing this let`s do Overflow addition:
Ok! Everything is now clear, &+
operator in this calculation flipped to 1 our MSB bit, and in result we get a binary value of 1000 0000 which in context of 'Int8' type has -128 value.
Is there any easy way to react in Unit Tests on type Overflow cases?
For creating Unit Tests which can check Type Overflows, we could use the 'addingReportingOverflow' method, which as a result returns a tuple of operation value, and 'Bool' value which indicates whether operation has been finished with overflow or not.
let result = Int8.max.addingReportingOverflow(1)
'result' is an tuple, which has following values for presented scenario: (partialValue -128, overflow true)
Original article source: LINK
Top comments (0)