Skip to content

Commit 2412d3a

Browse files
committed
Add sha1Hash method
1 parent ac203b1 commit 2412d3a

File tree

12 files changed

+259
-18
lines changed

12 files changed

+259
-18
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ playground.xcworkspace
4949
# Carthage
5050
#
5151
# Add this line if you want to avoid checking in source code from Carthage dependencies.
52-
# Carthage/Checkouts
53-
52+
Carthage/Checkouts
5453
Carthage/Build
5554

5655
# fastlane

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "CryptoSwift"]
2+
path = CryptoSwift
3+
url = https://github.com/krzyzanowskim/CryptoSwift.git

BencodeKit.xcodeproj/project.pbxproj

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
9EA794CF1E3B1D42000D6C50 /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB798381E3AEE1F005A7C9E /* List.swift */; };
1414
9EA794D01E3B1E0F000D6C50 /* Decode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EA794CB1E3B0F82000D6C50 /* Decode.swift */; };
1515
9EA794D11E3B1E8F000D6C50 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB798361E3AEE1F005A7C9E /* Dictionary.swift */; };
16+
9EA794EB1E41D11A000D6C50 /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EA794E71E41D104000D6C50 /* CryptoSwift.framework */; };
17+
9EA794ED1E41DC86000D6C50 /* OrderedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EA794EC1E41DC86000D6C50 /* OrderedDictionary.swift */; };
1618
9EB798241E3AE7EA005A7C9E /* BencodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EB7981A1E3AE7EA005A7C9E /* BencodeKit.framework */; };
1719
9EB798291E3AE7EA005A7C9E /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB798281E3AE7EA005A7C9E /* Tests.swift */; };
1820
9EB7982B1E3AE7EA005A7C9E /* BencodeKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EB7981D1E3AE7EA005A7C9E /* BencodeKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -22,6 +24,20 @@
2224
/* End PBXBuildFile section */
2325

2426
/* Begin PBXContainerItemProxy section */
27+
9EA794E61E41D104000D6C50 /* PBXContainerItemProxy */ = {
28+
isa = PBXContainerItemProxy;
29+
containerPortal = 9EA794E11E41D104000D6C50 /* CryptoSwift.xcodeproj */;
30+
proxyType = 2;
31+
remoteGlobalIDString = 754BE45519693E190098E6F3;
32+
remoteInfo = CryptoSwift;
33+
};
34+
9EA794E81E41D104000D6C50 /* PBXContainerItemProxy */ = {
35+
isa = PBXContainerItemProxy;
36+
containerPortal = 9EA794E11E41D104000D6C50 /* CryptoSwift.xcodeproj */;
37+
proxyType = 2;
38+
remoteGlobalIDString = 754BE46019693E190098E6F3;
39+
remoteInfo = Tests;
40+
};
2541
9EB798251E3AE7EA005A7C9E /* PBXContainerItemProxy */ = {
2642
isa = PBXContainerItemProxy;
2743
containerPortal = 9EB7980F1E3AE7B7005A7C9E /* Project object */;
@@ -34,6 +50,8 @@
3450
/* Begin PBXFileReference section */
3551
9EA794C91E3B0E44000D6C50 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Extensions.swift; path = Sources/Types/Extensions.swift; sourceTree = "<group>"; };
3652
9EA794CB1E3B0F82000D6C50 /* Decode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Decode.swift; sourceTree = "<group>"; };
53+
9EA794E11E41D104000D6C50 /* CryptoSwift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CryptoSwift.xcodeproj; path = Carthage/Checkouts/CryptoSwift/CryptoSwift.xcodeproj; sourceTree = "<group>"; };
54+
9EA794EC1E41DC86000D6C50 /* OrderedDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionary.swift; sourceTree = "<group>"; };
3755
9EB7981A1E3AE7EA005A7C9E /* BencodeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BencodeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3856
9EB7981D1E3AE7EA005A7C9E /* BencodeKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BencodeKit.h; sourceTree = "<group>"; };
3957
9EB7981E1E3AE7EA005A7C9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -53,6 +71,7 @@
5371
isa = PBXFrameworksBuildPhase;
5472
buildActionMask = 2147483647;
5573
files = (
74+
9EA794EB1E41D11A000D6C50 /* CryptoSwift.framework in Frameworks */,
5675
);
5776
runOnlyForDeploymentPostprocessing = 0;
5877
};
@@ -67,12 +86,31 @@
6786
/* End PBXFrameworksBuildPhase section */
6887

6988
/* Begin PBXGroup section */
89+
9EA794E21E41D104000D6C50 /* Products */ = {
90+
isa = PBXGroup;
91+
children = (
92+
9EA794E71E41D104000D6C50 /* CryptoSwift.framework */,
93+
9EA794E91E41D104000D6C50 /* Tests.xctest */,
94+
);
95+
name = Products;
96+
sourceTree = "<group>";
97+
};
98+
9EA794EA1E41D109000D6C50 /* Frameworks */ = {
99+
isa = PBXGroup;
100+
children = (
101+
9EA794E11E41D104000D6C50 /* CryptoSwift.xcodeproj */,
102+
);
103+
name = Frameworks;
104+
sourceTree = "<group>";
105+
};
70106
9EB7980E1E3AE7B7005A7C9E = {
71107
isa = PBXGroup;
72108
children = (
73109
9EB798321E3AE884005A7C9E /* Sources */,
74110
9EA794C91E3B0E44000D6C50 /* Extensions.swift */,
111+
9EA794EC1E41DC86000D6C50 /* OrderedDictionary.swift */,
75112
9EB798271E3AE7EA005A7C9E /* Tests */,
113+
9EA794EA1E41D109000D6C50 /* Frameworks */,
76114
9EB7981B1E3AE7EA005A7C9E /* Products */,
77115
);
78116
sourceTree = "<group>";
@@ -199,6 +237,12 @@
199237
mainGroup = 9EB7980E1E3AE7B7005A7C9E;
200238
productRefGroup = 9EB7981B1E3AE7EA005A7C9E /* Products */;
201239
projectDirPath = "";
240+
projectReferences = (
241+
{
242+
ProductGroup = 9EA794E21E41D104000D6C50 /* Products */;
243+
ProjectRef = 9EA794E11E41D104000D6C50 /* CryptoSwift.xcodeproj */;
244+
},
245+
);
202246
projectRoot = "";
203247
targets = (
204248
9EB798191E3AE7EA005A7C9E /* BencodeKit */,
@@ -207,6 +251,23 @@
207251
};
208252
/* End PBXProject section */
209253

254+
/* Begin PBXReferenceProxy section */
255+
9EA794E71E41D104000D6C50 /* CryptoSwift.framework */ = {
256+
isa = PBXReferenceProxy;
257+
fileType = wrapper.framework;
258+
path = CryptoSwift.framework;
259+
remoteRef = 9EA794E61E41D104000D6C50 /* PBXContainerItemProxy */;
260+
sourceTree = BUILT_PRODUCTS_DIR;
261+
};
262+
9EA794E91E41D104000D6C50 /* Tests.xctest */ = {
263+
isa = PBXReferenceProxy;
264+
fileType = wrapper.cfbundle;
265+
path = Tests.xctest;
266+
remoteRef = 9EA794E81E41D104000D6C50 /* PBXContainerItemProxy */;
267+
sourceTree = BUILT_PRODUCTS_DIR;
268+
};
269+
/* End PBXReferenceProxy section */
270+
210271
/* Begin PBXResourcesBuildPhase section */
211272
9EB798181E3AE7EA005A7C9E /* Resources */ = {
212273
isa = PBXResourcesBuildPhase;
@@ -236,6 +297,7 @@
236297
9EB7983B1E3AEE1F005A7C9E /* Integer.swift in Sources */,
237298
9EA794CE1E3B1691000D6C50 /* String.swift in Sources */,
238299
9EA794D11E3B1E8F000D6C50 /* Dictionary.swift in Sources */,
300+
9EA794ED1E41DC86000D6C50 /* OrderedDictionary.swift in Sources */,
239301
9EA794CF1E3B1D42000D6C50 /* List.swift in Sources */,
240302
9EA794CA1E3B0E44000D6C50 /* Extensions.swift in Sources */,
241303
);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "5DACB94A295467AC42BB859D293EBBB616E74CA7",
3+
"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4+
5+
},
6+
"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7+
"5DACB94A295467AC42BB859D293EBBB616E74CA7" : 9223372036854775807,
8+
"C3D8ED1CB28D809ADCE2C0DE74935E8A502ACD53" : 9223372036854775807
9+
},
10+
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "6F419A56-5F35-417F-BBBB-FC8C714B2AB6",
11+
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12+
"5DACB94A295467AC42BB859D293EBBB616E74CA7" : "BencodeKit\/",
13+
"C3D8ED1CB28D809ADCE2C0DE74935E8A502ACD53" : "BencodeKit\/CryptoSwift\/"
14+
},
15+
"DVTSourceControlWorkspaceBlueprintNameKey" : "BencodeKit",
16+
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
17+
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "BencodeKit.xcodeproj",
18+
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19+
{
20+
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:MonadicConsulting\/BencodeKit.git",
21+
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22+
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "5DACB94A295467AC42BB859D293EBBB616E74CA7"
23+
},
24+
{
25+
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/krzyzanowskim\/CryptoSwift.git",
26+
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27+
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "C3D8ED1CB28D809ADCE2C0DE74935E8A502ACD53"
28+
}
29+
]
30+
}

Cartfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github "krzyzanowskim/CryptoSwift"

Cartfile.resolved

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github "krzyzanowskim/CryptoSwift" "0.6.7"

OrderedDictionary.swift

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//
2+
// OrderedDictionary.swift
3+
// BencodeKit
4+
//
5+
// Created by Charlotte Tortorella on 1/2/17.
6+
//
7+
//
8+
9+
import Foundation
10+
11+
public struct BencodeDictionary: Collection {
12+
public func index(after i: Index) -> Index {
13+
return i + 1
14+
}
15+
16+
public var startIndex: Index {
17+
return 0
18+
}
19+
20+
public var endIndex: Index {
21+
return elements.count
22+
}
23+
24+
private var elements: [(String, Bencode)] = []
25+
26+
public typealias Index = Int
27+
28+
var keys: [String] {
29+
return elements.map { $0.0 }
30+
}
31+
32+
var values: [Bencode] {
33+
return elements.map { $0.1 }
34+
}
35+
36+
init(_ elements: [(String, Bencode)] = []) {
37+
self.elements = elements
38+
}
39+
40+
mutating func update(value: Bencode?, forKey key: String) {
41+
elements = elements.filter { $0.0 != key }
42+
if let value = value {
43+
elements.append(key, value)
44+
}
45+
}
46+
47+
func value(forKey key: String) -> Bencode? {
48+
return elements.first { $0.0 == key }?.1
49+
}
50+
51+
public subscript(index: String) -> Bencode? {
52+
get {
53+
return value(forKey: index)
54+
}
55+
set(newValue) {
56+
update(value: newValue, forKey: index)
57+
}
58+
}
59+
60+
public subscript(index: Index) -> (String, Bencode) {
61+
get {
62+
return elements[index]
63+
}
64+
set(newValue) {
65+
elements[index] = newValue
66+
}
67+
}
68+
}

Sources/Bencode.swift

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
// Copyright © 2017 Monadic Consulting. All rights reserved.
77
//
88

9+
import CryptoSwift
10+
911
public enum BencodingError: Error {
1012
case emptyString
1113
case nonExistentFile(String)
@@ -19,7 +21,6 @@ public enum BencodingError: Error {
1921
case unterminatedList(Data.Index)
2022
case invalidDictionary(Data.Index)
2123
case nonStringDictionaryKey(Data.Index)
22-
case nonAsciiDictionaryKey(Data.Index)
2324
case unterminatedDictionary(Data.Index)
2425
case nonAsciiString
2526
}
@@ -28,7 +29,7 @@ public indirect enum Bencode: Equatable {
2829
case integer(Int)
2930
case bytes(Data)
3031
case list([Bencode])
31-
case dictionary([(String, Bencode)])
32+
case dictionary(BencodeDictionary)
3233

3334
init(_ integer: Int) {
3435
self = .integer(integer)
@@ -48,20 +49,51 @@ public indirect enum Bencode: Equatable {
4849
}
4950

5051
init(_ dictionary: [(String, Bencode)]) {
52+
self.init(BencodeDictionary(dictionary))
53+
}
54+
55+
init(_ dictionary: BencodeDictionary) {
5156
self = .dictionary(dictionary)
5257
}
5358

54-
func stringRepresentation() throws -> String {
59+
func encodedString() -> String {
5560
switch self {
5661
case .integer(let integer):
5762
return "i\(String(integer))e"
5863
case .bytes(let bytes):
59-
guard let string = String(bytes: bytes, encoding: .ascii) else { throw BencodingError.nonAsciiString }
64+
let string = bytes.reduce("") { string, byte in
65+
string.appendingFormat("%c", byte)
66+
}
6067
return "\(string.characters.count):\(string)"
6168
case .list(let list):
62-
return try "l\(list.map({ try $0.stringRepresentation() }).joined())e"
69+
return "l\(list.map({ $0.encodedString() }).joined())e"
70+
case .dictionary(let dictionary):
71+
return "d\(dictionary.map({ "\($0.characters.count):\($0)\($1.encodedString())" }).joined())e"
72+
}
73+
}
74+
75+
func toString() -> String {
76+
switch self {
77+
case .integer(let integer):
78+
return String(integer)
79+
case .bytes(let bytes):
80+
return bytes.reduce("") { string, byte in
81+
string.appendingFormat("%c", byte)
82+
}
83+
case .list(let list):
84+
return "[" + list.map({ $0.toString() }).joined(separator: ", ") + "]"
6385
case .dictionary(let dictionary):
64-
return try "d\(dictionary.map({ "\($0.characters.count):\($0)\(try $1.stringRepresentation())" }).joined())e"
86+
return "[" + dictionary.map({ "\"\($0)\": \($1.toString())" }).joined(separator: ", ") + "]"
87+
}
88+
89+
}
90+
91+
subscript(index: String) -> Bencode? {
92+
get {
93+
guard case .dictionary(let dictionary) = self else {
94+
return nil
95+
}
96+
return dictionary[index]
6597
}
6698
}
6799
}
@@ -96,6 +128,14 @@ public extension Bencode {
96128
}
97129
}
98130

131+
public extension Bencode {
132+
func sha1Hash() -> String {
133+
return SHA1().calculate(for: encoded().bytes).reduce("") { hex, byte in
134+
hex.appendingFormat("%02x", byte)
135+
}
136+
}
137+
}
138+
99139
public extension Bencode {
100140
public static func ==(lhs: Bencode, rhs: Bencode) -> Bool {
101141
switch (lhs, rhs) {

Sources/Types/Dictionary.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ internal func bdecodeDictionary(_ data: Data, _ index: Data.Index) throws -> (Be
2424
}
2525

2626
let (valueMatch, nextIndex) = try bdecode(data, valueIndex)
27-
guard let stringKey = String(bytes: key, encoding: .ascii) else {
28-
throw BencodingError.nonAsciiDictionaryKey(currentIndex)
27+
28+
let stringKey = key.reduce("") { string, byte in
29+
string.appendingFormat("%c", byte)
2930
}
3031
values.append(stringKey, valueMatch)
3132
currentIndex = nextIndex
@@ -34,5 +35,5 @@ internal func bdecodeDictionary(_ data: Data, _ index: Data.Index) throws -> (Be
3435
}
3536
}
3637

37-
return (.dictionary(values), data.index(after: currentIndex))
38+
return (.dictionary(BencodeDictionary(values)), data.index(after: currentIndex))
3839
}

Sources/Types/Integer.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ internal func bdecodeInteger(_ data: Data, _ index: Data.Index) throws -> (match
2121
throw BencodingError.negativeZeroEncountered(index)
2222
}
2323

24-
print(integerString)
25-
2624
guard let value = Int(integerString) else {
2725
throw BencodingError.contaminatedInteger(index)
2826
}

0 commit comments

Comments
 (0)