Skip to content

Commit

Permalink
Make internal cast safer: rename from unsafeCast to cast and ma…
Browse files Browse the repository at this point in the history
…ke it throwable (instead of `fatalError`) (#47)
  • Loading branch information
kirilltitov authored Jul 22, 2019
1 parent 3035bf8 commit 042b7b2
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Sources/FDB/FDB/FDB+Sync.swift
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ public extension FDB {

try transaction.commitSync()

return bytes.unsafeCast()
return try bytes.cast()
}
}

Expand Down
24 changes: 9 additions & 15 deletions Sources/FDB/Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ import NIO
public typealias Byte = UInt8
public typealias Bytes = [Byte]

internal func _precondition(
_ condition: @autoclosure () -> Bool,
_ message: @autoclosure () -> String = String(),
file: StaticString = #file, line: UInt = #line
) {
guard condition() == true else {
fatalError("Precondition failed: \(message())", file: file, line: line)
}
}

internal extension FDB {
struct OptionsHelper {
@usableFromInline internal static func stringOptionToPointer(
Expand Down Expand Up @@ -62,11 +52,15 @@ internal extension Bool {
}

internal extension Array where Element == Byte {
@usableFromInline func unsafeCast<R>() -> R {
_precondition(
MemoryLayout<R>.size == self.count,
"Memory layout size for result type '\(R.self)' (\(MemoryLayout<R>.size) bytes) does not match with given byte array length (\(self.count) bytes)"
)
@usableFromInline func cast<R>() throws -> R {
guard MemoryLayout<R>.size == self.count else {
throw FDB.Error.unexpectedError(
"""
Memory layout size for result type '\(R.self)' (\(MemoryLayout<R>.size) bytes) does
not match with given byte array length (\(self.count) bytes)
"""
)
}
return self.withUnsafeBytes {
$0.baseAddress!.assumingMemoryBound(to: R.self).pointee
}
Expand Down
3 changes: 1 addition & 2 deletions Sources/FDB/Tuple.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
/// It must be wrapped with control characters first.
/// This is why you should additionally call .pack() from your
/// resulting byte array (see Tuple+Array.swift). Otherwise packing
/// will be incorrect, but most importantly - unpacking will
/// fail with a fatal error.
/// will be incorrect and will fail with an error.
/// Example of custom pack() implementation:
/// ```
/// extension MyValue: FDBTuplePackable {
Expand Down
20 changes: 10 additions & 10 deletions Sources/FDB/Tuple/Tuple+Unpack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ extension FDB.Tuple {
let begin = pos + 1
let end = begin + n
try sanityCheck(begin: begin, end: end)
return (
(Array<Byte>(repeating: 0x00, count: 8 - n) + input[begin ..< end]).reversed().unsafeCast() as Int,
return try (
(Array<Byte>(repeating: 0x00, count: 8 - n) + input[begin ..< end]).reversed().cast() as Int,
end
)
} else if code > FDB.Tuple.Prefix.NEG_INT_START && code < FDB.Tuple.Prefix.INT_ZERO_CODE {
Expand All @@ -103,15 +103,15 @@ extension FDB.Tuple {
throw FDB.Error.unpackTooLargeInt
}
try sanityCheck(begin: begin, end: end)
return (
return try (
(
(
Array<Byte>(
repeating: 0x00,
count: 8 - n
)
+ input[begin ..< end]
).reversed().unsafeCast() as Int
).reversed().cast() as Int
) - sizeLimits[n],
end
)
Expand All @@ -138,17 +138,17 @@ extension FDB.Tuple {
try sanityCheck(begin: pos + 1, end: end)
var bytes = Bytes(input[(pos + 1) ..< end])
transformFloatingPoint(bytes: &bytes, start: 0, encode: false)
return (
Float32(bitPattern: (bytes.unsafeCast() as UInt32).bigEndian),
return try (
Float32(bitPattern: (bytes.cast() as UInt32).bigEndian),
end
)
} else if code == FDB.Tuple.Prefix.DOUBLE {
let end = pos + 1 + MemoryLayout<Double>.size
try sanityCheck(begin: pos + 1, end: end)
var bytes = Bytes(input[(pos + 1) ..< end])
transformFloatingPoint(bytes: &bytes, start: 0, encode: false)
return (
Double(bitPattern: (bytes.unsafeCast() as UInt64).bigEndian),
return try (
Double(bitPattern: (bytes.cast() as UInt64).bigEndian),
end
)
} else if code == FDB.Tuple.Prefix.BOOL_TRUE || code == FDB.Tuple.Prefix.BOOL_FALSE {
Expand All @@ -159,8 +159,8 @@ extension FDB.Tuple {
} else if code == FDB.Tuple.Prefix.UUID {
let end = pos + 1 + MemoryLayout<uuid_t>.size
try sanityCheck(begin: pos + 1, end: end)
return (
UUID(uuid: Bytes(input[(pos + 1) ..< end]).unsafeCast()),
return try (
UUID(uuid: Bytes(input[(pos + 1) ..< end]).cast()),
end
)
}
Expand Down
8 changes: 4 additions & 4 deletions Tests/FDBTests/FDBTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class FDBTests: XCTestCase {
XCTAssertNoThrow(try fdb.increment(key: key))
let result = try fdb.get(key: key)
XCTAssertNotNil(result)
XCTAssertEqual(result!.unsafeCast() as Int64, expected)
try XCTAssertEqual(result!.cast() as Int64, expected)
XCTAssertEqual(result, getBytes(expected))
XCTAssertEqual(try fdb.increment(key: key), expected + 1)
XCTAssertEqual(try fdb.increment(key: key, value: -1), expected)
Expand Down Expand Up @@ -233,7 +233,7 @@ class FDBTests: XCTestCase {
let _ = semaphore.wait(for: 10)
let result: Bytes? = try tr.get(key: key).wait()
XCTAssertNotNil(result)
XCTAssertEqual(result!.unsafeCast() as Int64, expected)
try XCTAssertEqual(result!.cast() as Int64, expected)
XCTAssertEqual(result, getBytes(expected))
// TODO:
// XCTAssertEqual(try fdb.increment(key: key), expected + 1)
Expand Down Expand Up @@ -306,7 +306,7 @@ class FDBTests: XCTestCase {
try transaction.commitSync()
return value
}
resultSync.append(resultValue!.unsafeCast())
try! resultSync.append(resultValue!.cast())
if resultSync.count == etalon.count {
semaphoreSync.signal()
}
Expand All @@ -319,7 +319,7 @@ class FDBTests: XCTestCase {
return transaction.get(key: keyAsync, commit: true)
}
.map { (bytes: Bytes?, transaction: FDB.Transaction) -> Void in
let value: Int64 = bytes!.unsafeCast()
let value: Int64 = try! bytes!.cast()
resultAsync.append(value)
if resultAsync.count == etalon.count {
semaphoreAsync.signal()
Expand Down
13 changes: 0 additions & 13 deletions Tests/FDBTests/Helpers.swift

This file was deleted.

0 comments on commit 042b7b2

Please sign in to comment.