Skip to content

Instantly share code, notes, and snippets.

@alexbosworth
Created January 12, 2017 17:59
Show Gist options
  • Save alexbosworth/e4ec97154fd8425628adfcfc16aca399 to your computer and use it in GitHub Desktop.
Save alexbosworth/e4ec97154fd8425628adfcfc16aca399 to your computer and use it in GitHub Desktop.
/** Compact Size UInt
*/
enum CompactSizeUInt {
case uint8(UInt8), uint16(UInt16), uint32(UInt32), uint64(UInt64)
// MARK: - Init
/** Create from hex string
*/
init(from hex: String) throws {
let bytes = [Byte](try Data(hex: hex))
let hexByteLength = CompactSizeMarker.hexByteLength
// Confirm that the hex has a discriminant
guard let discriminant = bytes.first else { throw CompactSizeUIntError.expectedDiscriminant }
let compactSizeMarker = try CompactSizeMarker(from: discriminant)
let valueStartIndex = hex.index(hex.startIndex, offsetBy: CompactSizeMarker.discriminantByteLength * hexByteLength)
// Confirm that there are enough bytes in the hex
guard bytes.count >= compactSizeMarker.variableByteLength else { throw CompactSizeUIntError.insufficientBytes }
let range = valueStartIndex..<hex.index(valueStartIndex, offsetBy: compactSizeMarker.valueHexOffset)
let valueData = try Data(hex: hex.substring(with: range))
switch compactSizeMarker {
case .uint8:
self = CompactSizeUInt.uint8(discriminant)
case .uint16: // fd
self = CompactSizeUInt.uint16(UInt16(fromLittleEndian: valueData))
case .uint32: // fe
self = CompactSizeUInt.uint32(UInt32(fromLittleEndian: valueData))
case .uint64: // ff
self = CompactSizeUInt.uint64(UInt64(fromLittleEndian: valueData))
}
}
// MARK: - Error
/** Errors
*/
enum CompactSizeUIntError: String, Error {
case expectedDiscriminant
case insufficientBytes
}
// MARK: - Value Information
/** Get the size marker for this uint
*/
var marker: CompactSizeMarker {
switch self {
case .uint8(_):
return .uint8
case .uint16(_):
return .uint16
case .uint32(_):
return .uint32
case .uint64(_):
return .uint64
}
}
/** Determine the uint64 value
*/
var uint64Value: UInt64 {
switch self {
case .uint8(let val):
return UInt64(val)
case .uint16(let val):
return UInt64(val)
case .uint32(let val):
return UInt64(val)
case .uint64(let val):
return UInt64(val)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment