Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Sources/CacheAdvance/BigEndianHostSwappable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ protocol BigEndianHostSwappable where Self: FixedWidthInteger {
/// Converts the big-endian value in x to the current endian format and returns the resulting value.
static func swapToHost(_ x: Self) -> Self

/// The maximum representable integer in this type.
static var max: Self { get }

}

extension BigEndianHostSwappable {
Expand Down
2 changes: 1 addition & 1 deletion Sources/CacheAdvance/CacheAdvance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public final class CacheAdvance<T: Codable> {
throw CacheAdvanceError.fileNotWritable
}

let encodableMessage = EncodableMessage(message: message, encoder: encoder)
let encodableMessage = EncodableMessage<T, MessageSpan>(message: message, encoder: encoder)
let messageData = try encodableMessage.encodedData()
let bytesNeededToStoreMessage = Bytes(messageData.count)

Expand Down
4 changes: 2 additions & 2 deletions Sources/CacheAdvance/EncodableMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import Foundation
/// `[messageSize][data]`
/// - `messageSize` is a big-endian encoded `MessageSpan` of length `messageSpanStorageLength`.
/// - `data` is length `messageSize`.
struct EncodableMessage<T: Codable> {
struct EncodableMessage<T: Codable, Size: BigEndianHostSwappable> {

// MARK: Initialization

Expand All @@ -40,7 +40,7 @@ struct EncodableMessage<T: Codable> {
/// The encoded message, prefixed with the size of the message blob.
func encodedData() throws -> Data {
let messageData = try encoder.encode(message)
guard messageData.count < MessageSpan.max else {
guard messageData.count < Size.max else {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Utilizing a generic here let me run a test where I passed in a message that would throw the error below without that message requiring multiple gigabytes of RAM.

// We can't encode the length this message in a MessageSpan.
throw CacheAdvanceError.messageLargerThanCacheCapacity
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/CacheAdvanceTests/CacheAdvanceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ final class CacheAdvanceTests: XCTestCase {
let encoder = JSONEncoder()
return try FileHeader.expectedEndOfHeaderInFile
+ messages.reduce(0) { allocatedSize, message in
let encodableMessage = EncodableMessage(message: message, encoder: encoder)
let encodableMessage = EncodableMessage<T, MessageSpan>(message: message, encoder: encoder)
let data = try encodableMessage.encodedData()
return allocatedSize + UInt64(data.count)
}
Expand Down
11 changes: 8 additions & 3 deletions Tests/CacheAdvanceTests/EncodableMessageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class EncodableMessageTests: XCTestCase {
func test_encodedData_encodesCorrectSize() throws {
let message = TestableMessage("This is a test")
let data = try encoder.encode(message)
let encodedMessage = EncodableMessage<TestableMessage>(message: message, encoder: encoder)
let encodedMessage = EncodableMessage<TestableMessage, MessageSpan>(message: message, encoder: encoder)
let encodedData = try encodedMessage.encodedData()

let prefix = encodedData.subdata(in: 0..<MessageSpan.storageLength)
Expand All @@ -37,19 +37,24 @@ final class EncodableMessageTests: XCTestCase {
func test_encodedData_isOfCorrectLength() throws {
let message = TestableMessage("This is a test")
let data = try encoder.encode(message)
let encodedMessage = EncodableMessage<TestableMessage>(message: message, encoder: encoder)
let encodedMessage = EncodableMessage<TestableMessage, MessageSpan>(message: message, encoder: encoder)
let encodedData = try encodedMessage.encodedData()
XCTAssertEqual(encodedData.count, data.count + MessageSpan.storageLength)
}

func test_encodedData_hasDataPostfix() throws {
let message = TestableMessage("This is a test")
let data = try encoder.encode(message)
let encodedMessage = EncodableMessage<TestableMessage>(message: message, encoder: encoder)
let encodedMessage = EncodableMessage<TestableMessage, MessageSpan>(message: message, encoder: encoder)
let encodedData = try encodedMessage.encodedData()
XCTAssertEqual(encodedData.advanced(by: MessageSpan.storageLength), data)
}

func test_encodedData_whenMessageDataTooLarge_throwsError() throws {
let encodedMessage = EncodableMessage<Data, UInt8>(message: Data(count: Int(UInt8.max)), encoder: encoder)
XCTAssertThrowsError(try encodedMessage.encodedData())
}

// MARK: Private

private let encoder = JSONEncoder()
Expand Down