Skip to content

Commit

Permalink
added subscript
Browse files Browse the repository at this point in the history
  • Loading branch information
Caynan Sousa committed Jun 21, 2017
1 parent ced1551 commit d3eb33c
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 37 deletions.
5 changes: 4 additions & 1 deletion Horus.playground/Contents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ let pi: Float = try floatBin.scanValue(start: 0, length: 4)
let binStr: Binary = [0x48, 0x6F, 0x72, 0x75, 0x73, 0x00] // => "Horus\0"

try binStr.get(offset: 0, length: 5)
try binStr.get(offset: 1)
try binStr.get(offset: 1)

bin[1...2].count
bin[1..<2].count
11 changes: 7 additions & 4 deletions Horus.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@
};
3549BB601DA38ADB00C63030 = {
CreatedOnToolsVersion = 8.0;
DevelopmentTeam = 4PQKGKU5R7;
LastSwiftMigration = 0800;
ProvisioningStyle = Automatic;
};
Expand Down Expand Up @@ -1080,12 +1081,13 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_TEAM = 4PQKGKU5R7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/Carthage/Build/iOS";
PRODUCT_BUNDLE_IDENTIFIER = org.caynan.HorusTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
Expand All @@ -1099,12 +1101,13 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ENABLE_MODULES = YES;
DEVELOPMENT_TEAM = 4PQKGKU5R7;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/Carthage/Build/iOS";
PRODUCT_BUNDLE_IDENTIFIER = org.caynan.HorusTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
Expand All @@ -1124,7 +1127,7 @@
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(PROJECT_DIR)/Carthage/Build/iOS";
MACOSX_DEPLOYMENT_TARGET = 10.10;
PRODUCT_BUNDLE_IDENTIFIER = org.caynan.HorusTests;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -1147,7 +1150,7 @@
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(PROJECT_DIR)/Carthage/Build/iOS";
MACOSX_DEPLOYMENT_TARGET = 10.10;
PRODUCT_BUNDLE_IDENTIFIER = org.caynan.HorusTests;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
98 changes: 66 additions & 32 deletions Sources/Binary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import Foundation
/// Wrapper for immutable parsing of binary data.
public struct Binary: ExpressibleByArrayLiteral {
public typealias Element = UInt8

// MARK: - Properties

/// Underlaying data for this struct.
private let data: Data

// MARK: - Initializers

/**
Initialize with an array literal.
Expand All @@ -36,7 +36,7 @@ public struct Binary: ExpressibleByArrayLiteral {
public init(arrayLiteral elements: Element...) {
self.data = Data(bytes: elements)
}

/**
Initialize with a `Data` Object.
Expand All @@ -51,7 +51,7 @@ public struct Binary: ExpressibleByArrayLiteral {
public init(with data: Data) {
self.data = data
}

/**
Initialize with an Array.
Expand All @@ -66,7 +66,41 @@ public struct Binary: ExpressibleByArrayLiteral {
public init(with data: [UInt8]) {
self.data = Data(bytes: data)
}


/// Get a byte on a given index.
///
/// - Parameter index: The index
public subscript(index: Int) -> UInt8 {
precondition(index < self.count, "Index out of bounds.")

return self.data[index]
}

/// Accesses the bytes at the specified range of indexes.
///
/// - Parameter range: The range of indexes (the upperBound is not included)
public subscript(range: Range<Int>) -> Binary {
precondition(range.lowerBound >= 0 && range.upperBound < self.count, "Index out of bounds.")

let range = Range(range.lowerBound..<range.upperBound)
let subData = Data(self.data[range])
return Binary(with: subData)
}

/// Accesses the bytes at the specified range of indexes.
///
/// - Parameter range: A closed range (e.g: lowerBound...upperBound)
public subscript(range: CountableClosedRange<Int>) -> Binary {
precondition(range.lowerBound >= 0 && range.upperBound < self.count, "Index out of bounds.")

return self[range.lowerBound..<range.upperBound + 1]
}

/// The number of bytes contained in self.
public var count: Int {
return self.data.count
}

// MARK: - Integer parsing
/**
Scan an Integer from data.
Expand All @@ -83,11 +117,11 @@ public struct Binary: ExpressibleByArrayLiteral {
*/
public func scanValue<T: Integer>(start: Int, length: Int) throws -> T {
let end = start + length
guard end <= self.data.count else { throw BinaryError.outOfBounds }
return self.data.subdata(in: start..<end).withUnsafeBytes{ $0.pointee }
guard end <= self.count else { throw BinaryError.outOfBounds }

return self.data.subdata(in: start..<end).withUnsafeBytes { $0.pointee }
}

/**
Scan an Integer from data, auto inferring length from the return type. See note for caveats.
Expand All @@ -108,11 +142,11 @@ public struct Binary: ExpressibleByArrayLiteral {
*/
public func get<T: Integer>(at offset: Int) throws -> T {
let end = offset + MemoryLayout<T>.size
guard end <= self.data.count else { throw BinaryError.outOfBounds }
guard end <= self.count else { throw BinaryError.outOfBounds }

return try self.scanValue(start: offset, length: end)
}

/**
Scan a `FloatingPoint` from data.
Expand All @@ -128,11 +162,11 @@ public struct Binary: ExpressibleByArrayLiteral {
*/
public func scanValue<T: FloatingPoint>(start: Int, length: Int) throws -> T {
let end = start + length
guard end <= self.data.count else { throw BinaryError.outOfBounds }
return self.data.subdata(in: start..<end).withUnsafeBytes{ $0.pointee }
guard end <= self.count else { throw BinaryError.outOfBounds }

return self.data.subdata(in: start..<end).withUnsafeBytes { $0.pointee }
}

/**
Scan a `FloatingPoint` from data, auto inferring length from the return type.
Expand All @@ -147,11 +181,11 @@ public struct Binary: ExpressibleByArrayLiteral {
*/
public func get<T: FloatingPoint>(at offset: Int) throws -> T {
let end = offset + MemoryLayout<T>.size
guard end <= self.data.count else { throw BinaryError.outOfBounds }
guard end <= self.count else { throw BinaryError.outOfBounds }

return try self.scanValue(start: offset, length: end)
}

/**
Parse `String` of known size from underlying data.
Expand All @@ -167,17 +201,17 @@ public struct Binary: ExpressibleByArrayLiteral {
*/
public func get(offset: Int, length: Int, encoding: String.Encoding = .ascii) throws -> String {
let end = offset + length
guard end <= self.data.count else { throw BinaryError.outOfBounds }
guard end <= self.count else { throw BinaryError.outOfBounds }

let strData = self.data.subdata(in: offset..<end)

guard let response = String(bytes: strData, encoding: encoding) else {
throw BinaryError.failedConversion
}

return response
}

/**
Parse Nul('\0') terminated `String` from underlying data.
Expand All @@ -192,9 +226,9 @@ public struct Binary: ExpressibleByArrayLiteral {
*/
public func get(offset: Int, encoding: String.Encoding = .ascii) throws -> String {
guard offset <= data.count else { throw BinaryError.outOfBounds }

// Find the index of the Nul character, or nil if can't find one.
let nulIndex = data.withUnsafeBytes { (pointer: UnsafePointer<CChar>) -> Int? in
let nulIndex = data.withUnsafeBytes { (_: UnsafePointer<CChar>) -> Int? in
for idx in offset..<data.count {
guard CChar(data[idx]) != CChar(0) else {
return idx
Expand All @@ -203,15 +237,15 @@ public struct Binary: ExpressibleByArrayLiteral {
// Case when we reach the end the string before finding '\0'
return nil
}

guard let stringEnd = nulIndex else { throw BinaryError.nonNulTerminatedString }

let strData = self.data.subdata(in: offset..<stringEnd)

guard let response = String(data: strData, encoding: encoding) else {
throw BinaryError.failedConversion
}

return response
}
}
4 changes: 4 additions & 0 deletions Tests/BinarySpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ class BinarySpec: QuickSpec {

// MARK: Signed Integers
// TODO: Add test for remaining Integer types.
it("Should parse Int") {

}

}

// MARK: FloatingPoint numbers
Expand Down
Empty file modified scripts/bootstrap
100644 → 100755
Empty file.

0 comments on commit d3eb33c

Please sign in to comment.