diff --git a/Sources/Core/CMakeLists.txt b/Sources/Core/CMakeLists.txt index f7d6e64..0eee81a 100644 --- a/Sources/Core/CMakeLists.txt +++ b/Sources/Core/CMakeLists.txt @@ -23,6 +23,7 @@ add_library(swiftCore Pointer.swift Policy.swift Sequence.swift + StaticString.swift Swift.swift UInt.swift UInt8.swift diff --git a/Sources/Core/CompilerProtocols.swift b/Sources/Core/CompilerProtocols.swift index 9f04ca2..2fa88f6 100644 --- a/Sources/Core/CompilerProtocols.swift +++ b/Sources/Core/CompilerProtocols.swift @@ -38,3 +38,13 @@ public protocol RawRepresentable { var rawValue: RawValue { get } init?(rawValue: RawValue) } + +public protocol _ExpressibleByBuiltinStringLiteral { + init(_builtinStringLiteral start: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) +} + +public protocol ExpressibleByStringLiteral { + associatedtype StringLiteralType: _ExpressibleByBuiltinStringLiteral + + init(stringLiteral value: StringLiteralType) +} diff --git a/Sources/Core/Policy.swift b/Sources/Core/Policy.swift index 791befb..991fa16 100644 --- a/Sources/Core/Policy.swift +++ b/Sources/Core/Policy.swift @@ -50,6 +50,10 @@ precedencegroup NilCoalescingPrecedence { higherThan: ComparisonPrecedence } +precedencegroup CastingPrecedence { + higherThan: NilCoalescingPrecedence +} + precedencegroup AdditionPrecedence { associativity: left higherThan: NilCoalescingPrecedence diff --git a/Sources/Core/StaticString.swift b/Sources/Core/StaticString.swift new file mode 100644 index 0000000..3e22f3b --- /dev/null +++ b/Sources/Core/StaticString.swift @@ -0,0 +1,79 @@ +// Copyright © 2022 Max Desiatov . +// All Rights Reserved. +// SPDX-License-Identifier: BSD-3 + +@frozen +public struct StaticString { + /// `StaticString` stores either a pointer to null-terminated string data, or a single unicode scalar if possible. + @usableFromInline + internal var _startPtrOrData: Builtin.Word + + @usableFromInline + internal var _utf8CodeUnitCount: Builtin.Word + + /// Flags indicating how `StaticString` storage is used. + /// Only two bits are used. + /// Bit 1 is set to 1 if `_startPtrOrData` contains a Unicode scalar, 0 otherwise. + /// Bit 2 is set to 1 if `_startPtrOrData` is a pointer to an ASCII string, or stores an ASCII scalar value. + @usableFromInline + internal var _flags: Builtin.Int8 + + @_transparent + public init() { + self = "" + } + + @usableFromInline + @_transparent + internal init( + _start: Builtin.RawPointer, + utf8CodeUnitCount: Builtin.Word, + isASCII: Builtin.Int1 + ) { + _startPtrOrData = Builtin.ptrtoint_Word(_start) + _utf8CodeUnitCount = utf8CodeUnitCount + + // First bit indicates whether `StaticString` stores a pointer to the null-terminated string. + let pointerRepresentationFlag = (0x0 as UInt8)._value + + // Second bit tells if this string is ASCII. + let asciiFlag = (0x2 as UInt8)._value + _flags = Bool(isASCII) ? asciiFlag : pointerRepresentationFlag + } + + @_alwaysEmitIntoClient + @_transparent + internal var unsafeRawPointer: Builtin.RawPointer { + Builtin.inttoptr_Word(_startPtrOrData) + } + + @_transparent + public var hasPointerRepresentation: Bool { + return (UInt8(_flags) & 0x1) == 0 + } + + @_transparent + public var isASCII: Bool { + return (UInt8(_flags) & 0x2) != 0 + } +} + +extension StaticString: _ExpressibleByBuiltinStringLiteral { + @_effects(readonly) + @_transparent + public init(_builtinStringLiteral start: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) { + self = StaticString( + _start: start, + utf8CodeUnitCount: utf8CodeUnitCount, + isASCII: isASCII + ) + } +} + +extension StaticString: ExpressibleByStringLiteral { + @_effects(readonly) + @_transparent + public init(stringLiteral value: StaticString) { + self = value + } +}