Skip to content

Commit e67a1cc

Browse files
committed
binary
1 parent d891373 commit e67a1cc

19 files changed

+452
-1
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
.swiftpm

Package.resolved

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// swift-tools-version:5.4
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "Binary",
8+
products: [
9+
.library(name: "Binary", targets: ["Binary"]),
10+
],
11+
dependencies: [
12+
.package(name: "List", url: "[email protected]:spacenation/swift-list.git", .upToNextMajor(from: "1.0.0")),
13+
],
14+
targets: [
15+
.target(name: "Binary", dependencies: ["List"]),
16+
.testTarget(name: "BinaryTests", dependencies: ["Binary"])
17+
]
18+
)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# swift-binary
1+
### Binary

Sources/Binary/Binary.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Foundation
2+
@_exported import List
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Foundation
2+
3+
extension BinaryFloatingPoint {
4+
public func scaled<T: FixedWidthInteger>(in range: ClosedRange<Self>) -> T {
5+
T(Self(T.max) * self.normalized(in: range))
6+
}
7+
}
8+
9+
extension BinaryFloatingPoint {
10+
public func normalized(in range: ClosedRange<Self> = .unitInterval) -> Self {
11+
guard range.upperBound - range.lowerBound > 0 else { return 0 }
12+
let value = Swift.min(Swift.max(self, range.lowerBound), range.upperBound)
13+
return Self(value - range.lowerBound) / Self(range.upperBound - range.lowerBound)
14+
}
15+
}
16+
17+
extension ClosedRange where Bound : BinaryFloatingPoint {
18+
public static var unitInterval: Self { 0.0...1.0 }
19+
}

Sources/Binary/Bit.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Foundation
2+
3+
public enum Bit {
4+
case zero
5+
case one
6+
}
7+
8+
public extension Bit {
9+
init(_ int: UInt8) {
10+
self = int == 0 ? .zero : .one
11+
}
12+
13+
init?(_ character: Character) {
14+
switch character {
15+
case "0":
16+
self = .zero
17+
case "1":
18+
self = .one
19+
default:
20+
return nil
21+
}
22+
}
23+
}
24+
25+
public extension Bool {
26+
init(bit: Bit) {
27+
switch bit {
28+
case .zero:
29+
self = false
30+
case .one:
31+
self = true
32+
}
33+
}
34+
}
35+
36+
public extension UInt8 {
37+
var bits: [Bit] {
38+
Array((0...7)).reversed().map { self.bit(at: $0) }
39+
}
40+
}
41+
42+
public extension UInt8 {
43+
func bit(at index: Int) -> Bit {
44+
let bits = (0...7).map { UInt8(1) << $0 }
45+
return (self & bits[index] != 0) ? .one : .zero
46+
}
47+
}
48+
49+
public extension Collection where Element == UInt8 {
50+
var bits: [Bit] {
51+
self.flatMap { $0.bits }
52+
}
53+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Foundation
2+
3+
public enum BitsExtensionStrategy: Equatable {
4+
case fixed
5+
case signExtended(UInt)
6+
case zeroExtended(UInt)
7+
case zeroBackfill(UInt)
8+
}

Sources/Binary/ByteOrder.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Foundation
2+
3+
public enum ByteOrder: Equatable {
4+
case littleEndian
5+
case bigEndian
6+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Foundation
2+
3+
extension FixedWidthInteger {
4+
public func scaled<T: FixedWidthInteger>() -> T {
5+
let sizeDelta = MemoryLayout<Self>.size * 8 - MemoryLayout<T>.size * 8
6+
if sizeDelta > 0 {
7+
return T(self >> sizeDelta)
8+
}
9+
if sizeDelta < 0 {
10+
return T(self) >> sizeDelta
11+
}
12+
return T(self)
13+
}
14+
15+
public func scaled<T: BinaryFloatingPoint>() -> T {
16+
T(self) / T(Self.max)
17+
}
18+
}
19+
20+
extension FixedWidthInteger where Self: UnsignedInteger {
21+
public func scalingDown(factor: Self) -> Self {
22+
let portion: Float = Float(factor) / Float(Self.max)
23+
let newValue = Float(self) * portion
24+
return Self.init(Swift.max(0, Swift.min(newValue, Float(Self.max))))
25+
}
26+
27+
public func scalingUp(factor: Self) -> Self {
28+
guard factor > 0 else { return self }
29+
let portion: Float = Float(Self.max) / Float(factor)
30+
let newValue = Float(self) * portion
31+
return Self.init(Swift.max(0, Swift.min(newValue, Float(Self.max))))
32+
}
33+
}
34+
35+
extension FixedWidthInteger {
36+
public func normalized(in range: ClosedRange<Self> = .maxRange) -> Float {
37+
guard range.upperBound - range.lowerBound > 0 else { return 0 }
38+
let value = Swift.min(Swift.max(self, range.lowerBound), range.upperBound)
39+
return Float(value - range.lowerBound) / Float(range.upperBound - range.lowerBound)
40+
}
41+
}
42+
43+
extension Range where Bound: FixedWidthInteger {
44+
public static var maxRange: Self {
45+
Bound.min..<Bound.max
46+
}
47+
}
48+
49+
extension ClosedRange where Bound: FixedWidthInteger {
50+
public static var maxRange: Self {
51+
Bound.min...Bound.max
52+
}
53+
}

0 commit comments

Comments
 (0)