//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import SwiftShims extension _UnmanagedString where CodeUnit == UInt8 { internal func hashASCII(into core: inout Hasher.Core) { core.combine(bytes: rawBuffer) } } extension BidirectionalCollection where Element == UInt16, SubSequence == Self { internal func hashUTF16(into core: inout Hasher.Core) { for i in self.indices { let cu = self[i] let cuIsASCII = cu <= 0x7F let isSingleSegmentScalar = self.hasNormalizationBoundary(after: i) if cuIsASCII && isSingleSegmentScalar { core.combine(UInt8(truncatingIfNeeded: cu)) } else { for encodedScalar in Unicode._ParsingIterator( codeUnits: _NormalizedCodeUnitIterator(self[i.. Int { return Hasher._hash(seed: seed, bytes: rawBuffer) } } extension _UnmanagedString where CodeUnit == UInt16 { internal func hash(into hasher: inout Hasher) { self.hashUTF16(into: &hasher._core) hasher._core.combine(0xFF as UInt8) // terminator } internal func _rawHashValue(seed: (UInt64, UInt64)) -> Int { var core = Hasher.Core(seed: seed) self.hashUTF16(into: &core) return Int(truncatingIfNeeded: core.finalize()) } } extension _UnmanagedOpaqueString { internal func hash(into hasher: inout Hasher) { self.hashUTF16(into: &hasher._core) hasher._core.combine(0xFF as UInt8) // terminator } internal func _rawHashValue(seed: (UInt64, UInt64)) -> Int { var core = Hasher.Core(seed: seed) self.hashUTF16(into: &core) return Int(truncatingIfNeeded: core.finalize()) } } extension _SmallUTF8String { internal func hash(into hasher: inout Hasher) { #if arch(i386) || arch(arm) unsupportedOn32bit() #else if isASCII { self.withUnmanagedASCII { $0.hash(into: &hasher) } return } self.withUnmanagedUTF16 { $0.hash(into: &hasher) } #endif // 64-bit } internal func _rawHashValue(seed: (UInt64, UInt64)) -> Int { #if arch(i386) || arch(arm) unsupportedOn32bit() #else if isASCII { return self.withUnmanagedASCII { $0._rawHashValue(seed: seed) } } return self.withUnmanagedUTF16 { $0._rawHashValue(seed: seed) } #endif // 64-bit } } extension _StringGuts { @_effects(releasenone) // FIXME: Is this valid in the opaque case? @usableFromInline internal func hash(into hasher: inout Hasher) { if _isSmall { _smallUTF8String.hash(into: &hasher) return } defer { _fixLifetime(self) } if _slowPath(_isOpaque) { _asOpaque().hash(into: &hasher) return } if isASCII { _unmanagedASCIIView.hash(into: &hasher) return } _unmanagedUTF16View.hash(into: &hasher) } @_effects(releasenone) // FIXME: Is this valid in the opaque case? @usableFromInline internal func hash(_ range: Range, into hasher: inout Hasher) { if _isSmall { _smallUTF8String[range].hash(into: &hasher) return } defer { _fixLifetime(self) } if _slowPath(_isOpaque) { _asOpaque()[range].hash(into: &hasher) return } if isASCII { _unmanagedASCIIView[range].hash(into: &hasher) return } _unmanagedUTF16View[range].hash(into: &hasher) } @_effects(releasenone) // FIXME: Is this valid in the opaque case? @usableFromInline internal func _rawHashValue(seed: (UInt64, UInt64)) -> Int { if _isSmall { return _smallUTF8String._rawHashValue(seed: seed) } defer { _fixLifetime(self) } if _slowPath(_isOpaque) { return _asOpaque()._rawHashValue(seed: seed) } if isASCII { return _unmanagedASCIIView._rawHashValue(seed: seed) } return _unmanagedUTF16View._rawHashValue(seed: seed) } @_effects(releasenone) // FIXME: Is this valid in the opaque case? @usableFromInline internal func _rawHashValue( _ range: Range, seed: (UInt64, UInt64) ) -> Int { if _isSmall { return _smallUTF8String[range]._rawHashValue(seed: seed) } defer { _fixLifetime(self) } if _slowPath(_isOpaque) { return _asOpaque()[range]._rawHashValue(seed: seed) } if isASCII { return _unmanagedASCIIView[range]._rawHashValue(seed: seed) } return _unmanagedUTF16View[range]._rawHashValue(seed: seed) } } extension String : Hashable { /// Hashes the essential components of this value by feeding them into the /// given hasher. /// /// - Parameter hasher: The hasher to use when combining the components /// of this instance. @inlinable public func hash(into hasher: inout Hasher) { _guts.hash(into: &hasher) } @inlinable public func _rawHashValue(seed: (UInt64, UInt64)) -> Int { return _guts._rawHashValue(seed: seed) } } extension StringProtocol { /// Hashes the essential components of this value by feeding them into the /// given hasher. /// /// - Parameter hasher: The hasher to use when combining the components /// of this instance. @inlinable public func hash(into hasher: inout Hasher) { _wholeString._guts.hash(_encodedOffsetRange, into: &hasher) } @inlinable public func _rawHashValue(seed: (UInt64, UInt64)) -> Int { return _wholeString._guts._rawHashValue(_encodedOffsetRange, seed: seed) } }