Skip to content

Commit cefbf3f

Browse files
committed
updated version and readme
1 parent b206861 commit cefbf3f

File tree

4 files changed

+86
-68
lines changed

4 files changed

+86
-68
lines changed

.github/workflows/build.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jobs:
55
runs-on: macOS-latest
66
steps:
77
- name: Checkout
8-
uses: actions/checkout@v2
8+
uses: actions/checkout@v3
99
- name: Select Xcode
1010
run: sudo xcode-select -s /Applications/Xcode_13.4.app
1111
- name: Build and Test SPM
@@ -19,6 +19,6 @@ jobs:
1919
options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined
2020
steps:
2121
- name: Checkout
22-
uses: actions/checkout@v2
22+
uses: actions/checkout@v3
2323
- name: Build and Test
2424
run: swift test

.github/workflows/deploy.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
runs-on: macOS-latest
88
steps:
99
- name: Checkout
10-
uses: actions/checkout@v2
10+
uses: actions/checkout@v3
1111
- name: Select Xcode
1212
run: sudo xcode-select -s /Applications/Xcode_13.4.app
1313
- name: Publish Pod

README.md

+82-64
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ Setup instructions:
3535
Add this to the dependency section of your `Package.swift` manifest:
3636

3737
```Swift
38-
.package(url: "https://github.com/tesseract-one/swift-scale-codec.git", from: "0.2.0")
38+
.package(url: "https://github.com/tesseract-one/swift-scale-codec.git", from: "0.3.0")
3939
```
4040

4141
- **CocoaPods:** Put this in your `Podfile`:
4242

4343
```Ruby
44-
pod 'ScaleCodec', '~> 0.2'
44+
pod 'ScaleCodec', '~> 0.3'
4545
```
4646

4747
## Usage Examples
@@ -57,10 +57,10 @@ import ScaleCodec
5757

5858
let data = Data([0xff, 0xff, 0xff, 0xff])
5959

60-
let encoded = try SCALE.default.encode(UInt32.max)
60+
let encoded = try encode(UInt32.max)
6161
assert(encoded == data)
6262

63-
let uint32 = try SCALE.default.decode(UInt32.self, from: data)
63+
let uint32 = try decode(UInt32.self, from: data)
6464
assert(uint32 == UInt32.max)
6565
```
6666

@@ -77,20 +77,20 @@ import ScaleCodec
7777

7878
let data = Data([0x07, 0x00, 0x00, 0x00, 0x00, 0x01])
7979

80-
let encoded = try SCALE.default.encode(UInt64(1 << 32), .compact)
80+
let encoded = try encode(UInt64(1 << 32), .compact)
8181
assert(encoded == data))
8282

83-
let compact = try SCALE.default.decode(UInt64.self, .compact, from: data)
83+
let compact = try decode(UInt64.self, .compact, from: data)
8484
assert(compact == UInt64(1 << 32))
8585

86-
// without helper methods
87-
// let encoded = try SCALE.default.encode(SCompact(UInt64(1 << 32)))
88-
// let compact = try SCALE.default.decode(SCompact<UInt64>.self, from: data).value
86+
// without custom encoding methods
87+
// let encoded = try encode(Compact(UInt64(1 << 32)))
88+
// let compact = try decode(Compact<UInt64>.self, from: data).value
8989
```
9090

91-
#### Int[128-512] and UInt[128-512]
91+
#### Int[128-1024] and UInt[128-1024]
9292

93-
`Int[128-512]` and `UInt[128-512]` types implemented as `BigInt` and `BigUInt` Swift types. For proper encoding ScaleCodec has `SInt[128-512]` and `SUInt[128-512]` wrappers. Decoder and encoder has extension methods for simpler usage.
93+
`Int[128-1024]` and `UInt[128-1024]` types implemented with `DoubleWidth` Swift type from Apple. It works fine for 128-256 bits but slow for 512-1024 bits.
9494

9595
```Swift
9696
import ScaleCodec
@@ -100,15 +100,11 @@ let data = Data([
100100
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
101101
])
102102

103-
let encoded = try SCALE.default.encode(BigUInt(2).pow(128) - 1, .b128)
103+
let encoded = try encode(UInt128(UInt256(2)^128 - 1))
104104
assert(encoded == data))
105105

106-
let compact = try SCALE.default.decode(BigUInt.self, .b128, from: data)
107-
assert(compact == BigUInt(2).pow(128) - 1)
108-
109-
// without helper methods
110-
// let encoded = try SCALE.default.encode(SUInt256(BigUInt(2).pow(128) - 1))
111-
// let compact = try SCALE.default.decode(SUInt256.self, from: data).int
106+
let compact = try decode(UInt128.self, from: data)
107+
assert(compact == UInt128(UInt256(2)^128 - 1))
112108
```
113109

114110
#### Data fixed encoding
@@ -120,11 +116,13 @@ import ScaleCodec
120116

121117
let data = Data([0x07, 0x00, 0x00, 0x00, 0x00, 0x01]
122118

123-
let encoded = try SCALE.default.encoder().encode(data, .fixed(6)).output
124-
assert(encoded == data))
119+
var encoder = encoder()
120+
try encoder.encode(data, .fixed(6))
121+
assert(encoder.output == data))
125122

126-
let decoded = try SCALE.default.decoder(data: encoded).decode(Data.self, .fixed(6))
127-
assert(decoded == encoded == data)
123+
var decoder = decoder(from: encoder.output)
124+
let decoded = try decoder.decode(Data.self, .fixed(6))
125+
assert(decoded == encoder.output == data)
128126
```
129127

130128
### Container types
@@ -136,9 +134,9 @@ import ScaleCodec
136134

137135
let array: [UInt32] = [1, 2, 3, 4, 5]
138136

139-
let data = try SCALE.default.encode(array)
137+
let data = try encode(array)
140138

141-
let decoded: [UInt32] = try SCALE.default.decode(from: data)
139+
let decoded: [UInt32] = try decode(from: data)
142140

143141
assert(array == decoded)
144142
```
@@ -152,32 +150,31 @@ import ScaleCodec
152150

153151
let array: [UInt32] = [1, 2, 3, 4, 5]
154152

155-
let data = try SCALE.default.encode(array, .fixed(5))
153+
let data = try encode(array, .fixed(5))
156154

157-
let decoded: [UInt32] = try SCALE.default.decode(.fixed(5), from: data)
155+
let decoded: [UInt32] = try decode(.fixed(5), from: data)
158156

159157
assert(array == decoded)
160158
```
161159

162-
163160
### Tuples
164161

165-
Tuple encoding and decoding supported through `STuple*` set of wrappers. ScaleCodec provides `STuple()` helper which can create approptiate `STuple*` instance for a tuple. `STuple*` wrappers can be nested to support bigger tuples. ScaleCodec also has set of helper methods for tuples support.
162+
Tuple encoding and decoding supported through `Tuple*` set of wrappers. ScaleCodec provides `Tuple()` helper which can create approptiate `Tuple*` instance for a tuple. `Tuple*` wrappers can be nested to support bigger tuples. ScaleCodec also has set of helper methods for tuples support.
166163

167164
```Swift
168165
import ScaleCodec
169166

170167
let tuple = (UInt32.max, "Hello")
171168

172-
let encoded = try SCALE.default.encode(tuple)
169+
let encoded = try encode(tuple)
173170

174-
let decoded: (UInt32, String) = try SCALE.default.decode(from: encoded)
171+
let decoded: (UInt32, String) = try decode(from: encoded)
175172

176173
assert(tuple == decoded)
177174

178175
// without helper methods
179-
// let encoded = try SCALE.default.encode(STuple(tuple)) // or directly STuple2(tuple)
180-
// let decoded = try SCALE.default.decode(STuple2<UInt32, String>.self, from: encoded).tuple
176+
// let encoded = try encode(Tuple(tuple)) // or directly Tuple2(tuple)
177+
// let decoded = try decode(Tuple2<UInt32, String>.self, from: encoded).tuple
181178
```
182179

183180
### Enums
@@ -189,30 +186,30 @@ Simple enums without associated values can be encoded automatically if enum supp
189186
```Swift
190187
import ScaleCodec
191188

192-
enum Test: CaseIterable, ScaleCodable {
189+
enum Test: CaseIterable, ScaleCodec.Codable {
193190
case A
194191
case B
195192
}
196193

197-
let data = try SCALE.default.encode(Test.A)
194+
let data = try encode(Test.A)
198195

199-
let decoded: Test = try SCALE.default.decode(from: data)
196+
let decoded: Test = try decode(from: data)
200197

201198
assert(decoded == Test.A)
202199
```
203200

204201
#### Complex enums
205202

206-
Encoding and decoding for complex enums with associated values should be implemented manually. Two protocols need to be implemented: `ScaleEncodable` and `ScaleDecodable` (`ScaleCodable` can be used as common alias).
203+
Encoding and decoding for complex enums with associated values should be implemented manually. Two protocols need to be implemented: `Encodable` and `Decodable` (`Codable` can be used as common alias).
207204

208205
```Swift
209206
import ScaleCodec
210207

211-
enum Test: ScaleCodable {
208+
enum Test: ScaleCodec.Codable {
212209
case A(String?)
213210
case B(UInt32, String) // UInt32 will use Compact encoding.
214211

215-
init(from decoder: ScaleDecoder) throws {
212+
init<D: ScaleCodec.Decoder>(from decoder: inout D) throws {
216213
let opt = try decoder.decode(.enumCaseId)
217214
switch opt {
218215
case 0: self = try .A(decoder.decode())
@@ -221,31 +218,36 @@ enum Test: ScaleCodable {
221218
}
222219
}
223220

224-
func encode(in encoder: ScaleEncoder) throws {
221+
func encode<E: ScaleCodec.Encoder>(in encoder: inout E) throws {
225222
switch self {
226-
case .A(let str): try encoder.encode(0, .enumCaseId).encode(str)
227-
case .B(let int, let str): try encoder.encode(1, .enumCaseId).encode(int, .compact).encode(str)
223+
case .A(let str):
224+
try encoder.encode(0, .enumCaseId)
225+
try encoder.encode(str)
226+
case .B(let int, let str):
227+
try encoder.encode(1, .enumCaseId)
228+
try encoder.encode(int, .compact)
229+
try encoder.encode(str)
228230
}
229231
}
230232
}
231233

232234
let val = Test.B(100, "World!")
233235

234-
let data = try SCALE.default.encode(val)
236+
let data = try encode(val)
235237

236-
let decoded: Test = try SCALE.default.decode(from: data)
238+
let decoded: Test = try decode(from: data)
237239

238240
assert(decoded == val)
239241
```
240242

241243
### Classes and Structures
242244

243-
`ScaleEncodable` and `ScaleDecodable` should be implemented for classes and structures. `ScaleEncoder` and `ScaleDecoder` have helpers methods for standard containers and types.
245+
`Encodable` and `Decodable` should be implemented for classes and structures. `Encoder` and `Decoder` have helpers methods for standard containers and types.
244246

245247
```Swift
246248
import ScaleCodec
247249

248-
struct Test: ScaleCodable, Equatable {
250+
struct Test: ScaleCodec.Codable, Equatable {
249251
let var1: String?
250252
let var2: BigUInt // will use Compact encoding.
251253
let var3: [UInt32] // UInt32 will use Compact encoding.
@@ -254,39 +256,38 @@ struct Test: ScaleCodable, Equatable {
254256
var1 = v1; var2 = v2; var3 = v3
255257
}
256258

257-
init(from decoder: ScaleDecoder) throws {
259+
init<D: ScaleCodec.Decoder>(from decoder: inout D) throws {
258260
var1 = try decoder.decode()
259261
var2 = try decoder.decode(.compact)
260-
var3 = try decoder.decode(Array<SCompact<UInt32>>.self).map { $0.value }
262+
var3 = try decoder.decode(Array<Compact<UInt32>>.self).map { $0.value }
261263
}
262264

263-
func encode(in encoder: ScaleEncoder) throws {
264-
try encoder
265-
.encode(var1)
266-
.encode(var2, .compact)
267-
.encode(var3.map { SCompact($0) })
265+
func encode<E: ScaleCodec.Encoder>(in encoder: inout E) throws {
266+
try encoder.encode(var1)
267+
try encoder.encode(var2, .compact)
268+
try encoder.encode(var3.map { Compact($0) })
268269
}
269270
}
270271

271272
let val = Test(nil, 123456789, [1, 2, 3, 4, 5])
272273

273-
let data = try SCALE.default.encode(val)
274+
let data = try encode(val)
274275

275-
let decoded: Test = try SCALE.default.decode(from: data)
276+
let decoded: Test = try decode(from: data)
276277

277278
assert(decoded == val)
278279
```
279280

280281
#### Fixed classes and structures
281282

282-
Classes and structures can be created from fixed encoded `Array` and `Data` object. For convenience ScaleCodec has two sets of protocols: (`ScaleFixedEncodable`, `ScaleFixedDecodable`) and (`ScaleFixedDataEncodable`, `ScaleFixedDataDecodable`).
283+
Classes and structures can be created from fixed encoded `Array` and `Data` object. For convenience ScaleCodec has two sets of protocols: (`FixedEncodable`, `FixedDecodable`) and (`FixedDataEncodable`, `FixedDataDecodable`).
283284

284285
Example:
285286

286287
```Swift
287288
import ScaleCodec
288289

289-
struct StringArray4: Equatable, ScaleFixed {
290+
struct StringArray4: Equatable, FixedCodable {
290291
typealias Element = String // Fixed Array element type
291292

292293
static var fixedElementCount: Int = 4 // amount of elements in Fixed Array
@@ -297,16 +298,16 @@ struct StringArray4: Equatable, ScaleFixed {
297298
self.array = array
298299
}
299300

300-
init(decoding values: [String]) throws { // decoding from Fixed Array
301+
init(values: [String]) throws { // decoding from Fixed Array
301302
self.init(values)
302303
}
303304

304-
func encode() throws -> [String] { // encoding to Fixed Array
305+
func values() throws -> [String] { // encoding to Fixed Array
305306
return self.array
306307
}
307308
}
308309

309-
private struct Data4: Equatable, ScaleFixedData {
310+
private struct Data4: Equatable, FixedDataCodable {
310311
var data: Data
311312

312313
static var fixedBytesCount: Int = 4 // amount of bytes in Fixed Data
@@ -319,29 +320,46 @@ private struct Data4: Equatable, ScaleFixedData {
319320
self.init(data)
320321
}
321322

322-
func encode() throws -> Data { // encoding to Fixed Data
323+
func serialize() throws -> Data { // encoding to Fixed Data
323324
return self.data
324325
}
325326
}
326327

327328
let string4 = StringArray4(["1", "2", "3", "4"])
328329

329-
let dataS4 = try SCALE.default.encode(string4)
330+
let dataS4 = try encode(string4)
330331

331-
let decoded: StringArray4 = try SCALE.default.decode(from: dataS4)
332+
let decoded: StringArray4 = try decode(from: dataS4)
332333

333334
assert(decoded == string4)
334335

335336
let data4 = Data4(Data([1, 2, 3, 4]))
336337

337-
let dataE4 = try SCALE.default.encode(data4)
338+
let dataE4 = try encode(data4)
338339

339-
let decoded: Data4 = try SCALE.default.decode(from: dataE4)
340+
let decoded: Data4 = try decode(from: dataE4)
340341

341342
assert(decoded == data4)
342343

343344
```
344345

346+
### Size calculation instead of full parsing
347+
For some cases it is better to calculate size of encoded type, instead of full parsing. In most cases it will be much quicker. For this purposes ScaleCodec has `SizeCalculable` protocol. It implemented for all base types and containers.
348+
349+
```Swift
350+
import ScaleCodec
351+
352+
let data = Data([0x10, 0x04, 0x41, 0x04, 0x42, 0x04, 0x43, 0x0c, 0x44, 0x44, 0x44])
353+
var decoder = decoder(from: data)
354+
var skipDecoder = decoder.skippable() // special decoder which can skip data
355+
356+
let size = try Array<String>.calculateSize(in: &skipDecoder)
357+
assert(size == 11)
358+
359+
let decoded = try decoder.decode(Array<String>.self)
360+
assert(decoded == ["A", "B", "C", "DDD"])
361+
```
362+
345363
## License
346364

347365
ScaleCodec can be used, distributed and modified under [the Apache 2.0 license](LICENSE).

ScaleCodec.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'ScaleCodec'
3-
s.version = '0.2.1'
3+
s.version = '0.3.0'
44
s.summary = 'SCALE codec implementation for Swift language'
55

66
s.description = <<-DESC

0 commit comments

Comments
 (0)