Dmitry
Dmitry

Reputation: 14622

Why is startIndex not equal to endIndex shifted to startIndex position in String in Swift?

Look at the program:

let s = "1"
print(s.startIndex)
print(s.index(before: s.endIndex))
print(s.index(before: s.endIndex) == s.startIndex)

It returns:

Index(_rawBits: 0)
Index(_rawBits: 256)
true

So, the same position in the string is represented with rawBits 0 and 256. Why?

Upvotes: 1

Views: 266

Answers (2)

ielyamani
ielyamani

Reputation: 18581

Equality between two String.Indexes is defined on the upper 50 bits of the _rawBits, aka orderingValue, as follows:

extension String.Index: Equatable {
  @inlinable @inline(__always)
  public static func == (lhs: String.Index, rhs: String.Index) -> Bool {
    return lhs.orderingValue == rhs.orderingValue
  }
}

And since 0 &>> 14 and 256 &>> 14 both equal 0, the positions are equal, and thus the indices are considered equal.


&>> is the infix operator to shift bits to the right, masking the shift amount to 64 bits.

Upvotes: 3

Rob Napier
Rob Napier

Reputation: 299345

The raw bits of the index are an implementation detail. As you see in your example, the two values are equal (they return true for ==).

As to the current implementation, bit 8 is set, which is not part of the position. That's a cached value for the offset to the next grapheme cluster, which is 1 byte away. It's telling you that there's one byte to the next grapheme (which it didn't know until you calculated the endIndex).

Upvotes: 3

Related Questions