This repository has been archived by the owner on May 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathIo.swift
138 lines (112 loc) · 3.65 KB
/
Io.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//
// Io.swift
// SwiftMultihash
//
// Created by Matteo Sartori on 01/06/15.
// Licensed under MIT See LICENCE for details
//
/*
This is the inital port of the golang io wrapper for Multihash.
It is a direct translation of the go implementation and as such
may use some paradigms that are not idiomatic Swift.
A more Swifty future version would extend NSInputStream and NSOutputStream
with multihashReader and multihashWriter methods.
*/
import Foundation
enum MultihashIOError : Error {
case endOfBuffer
case operationFailure
}
// English language error descriptions
extension MultihashIOError {
var description: String {
get {
switch self {
case .endOfBuffer:
return "End of buffer reached."
case .operationFailure:
return "Operation failure."
}
}
}
}
let defaultBufSize = 1024
// Reader is an NSInputStream wrapper that exposes a function
// to read a whole multihash and return it.
public protocol Reader {
func readMultihash() throws -> Multihash
}
// Writer is an NSOutputStream wrapper that exposes a function
// to write a whole multihash.
public protocol Writer {
func writeMultihash(_ mHash: Multihash) throws
}
public func newReader(_ reader: InputStream) -> Reader {
return MultihashReader(inStream: reader)
}
public func newWriter(_ writer: OutputStream) -> Writer {
return MultihashWriter(outStream: writer)
}
public struct MultihashReader {
let inStream: InputStream
}
public struct MultihashWriter {
let outStream: OutputStream
}
extension MultihashReader: Reader {
public func read() throws -> [UInt8] {
var readBuf = [UInt8](repeating: 0, count: defaultBufSize)
try _ = inStream.readToBuffer(&readBuf, maxLength: defaultBufSize)
return readBuf
}
public func readMultihash() throws -> Multihash {
// Read just the header first.
var multihashHeader = [UInt8](repeating: 0, count: 2)
try _ = inStream.readToBuffer(&multihashHeader, maxLength: multihashHeader.count)
let hashLength = Int(multihashHeader[1])
if hashLength > 127 {
// return varints not yet supported error
throw MultihashIOError.endOfBuffer
}
// Read the rest
var multiHash = [UInt8](repeating: 0, count: hashLength)
try _ = inStream.readToBuffer(&multiHash, maxLength: hashLength)
return try cast(multihashHeader+multiHash)
}
}
extension InputStream {
func readToBuffer(_ buffer: UnsafeMutablePointer<UInt8>, maxLength len: Int) throws -> Int {
let result = read(buffer, maxLength: len)
switch true {
case result == 0:
throw MultihashIOError.endOfBuffer
case result < 0:
throw MultihashIOError.operationFailure
default:
return result
}
}
}
extension MultihashWriter: Writer {
func write(_ buffer: [UInt8]) throws {
var buf = buffer
try _ = outStream.writeBuffer(&buf, maxLength: buf.count)
}
public func writeMultihash(_ mHash: Multihash) throws {
var hashBuf = mHash.value
try _ = outStream.writeBuffer(&hashBuf, maxLength: hashBuf.count)
}
}
extension OutputStream {
func writeBuffer(_ buffer: UnsafePointer<UInt8>, maxLength len: Int) throws -> Int {
let result = write(buffer, maxLength: len)
switch true {
case result == 0:
throw MultihashIOError.endOfBuffer
case result < 0:
throw MultihashIOError.operationFailure
default:
return result
}
}
}