-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of github.com:AcalaNetwork/boka
* 'master' of github.com:AcalaNetwork/boka: sorted set (#93)
- Loading branch information
Showing
6 changed files
with
153 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
public protocol CodableAlias<Alias>: Codable { | ||
associatedtype Alias: Codable | ||
|
||
init(alias: Alias) | ||
var alias: Alias { get } | ||
} | ||
|
||
@propertyWrapper | ||
public struct CodingAs<T: CodableAlias>: Codable { | ||
public var wrappedValue: T.Alias | ||
|
||
public init(wrappedValue: T.Alias) { | ||
self.wrappedValue = wrappedValue | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.singleValueContainer() | ||
wrappedValue = try container.decode(T.self).alias | ||
} | ||
|
||
public func encode(to encoder: Encoder) throws { | ||
var container = encoder.singleValueContainer() | ||
try container.encode(T(alias: wrappedValue)) | ||
} | ||
} | ||
|
||
extension CodingAs: Sendable where T: Sendable, T.Alias: Sendable {} | ||
|
||
extension CodingAs: Equatable where T: Equatable, T.Alias: Equatable {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Foundation | ||
|
||
public struct SortedSet<T: Codable & Hashable & Comparable>: Codable, CodableAlias { | ||
public typealias Alias = Set<T> | ||
|
||
public var alias: Alias | ||
|
||
public init(alias: Alias) { | ||
self.alias = alias | ||
} | ||
|
||
public init(from decoder: Decoder) throws { | ||
let container = try decoder.singleValueContainer() | ||
let array = try container.decode([T].self) | ||
|
||
// ensure array is sorted and unique | ||
var previous: T? | ||
for item in array { | ||
guard previous == nil || item > previous! else { | ||
throw DecodingError.dataCorrupted( | ||
DecodingError.Context( | ||
codingPath: container.codingPath, | ||
debugDescription: "Array is not sorted" | ||
) | ||
) | ||
} | ||
previous = item | ||
} | ||
|
||
alias = Set(array) | ||
} | ||
|
||
public func encode(to encoder: Encoder) throws { | ||
var container = encoder.singleValueContainer() | ||
var array = Array(alias) | ||
array.sort() | ||
try container.encode(array) | ||
} | ||
} | ||
|
||
extension SortedSet: Sendable where T: Sendable, Alias: Sendable {} | ||
|
||
extension SortedSet: Equatable where T: Equatable, Alias: Equatable {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import Foundation | ||
import Testing | ||
|
||
@testable import Codec | ||
|
||
struct UInt8Alias: CodableAlias, Codable { | ||
typealias T = UInt8 | ||
|
||
var extraByte: UInt8 = 0xAB | ||
var value: UInt8 | ||
|
||
init(alias: UInt8) { | ||
value = alias | ||
} | ||
|
||
var alias: UInt8 { | ||
value | ||
} | ||
} | ||
|
||
struct TestCodable: Codable { | ||
@CodingAs<UInt8Alias> var value: UInt8 | ||
} | ||
|
||
struct CodingAsTests { | ||
@Test func testCodingAs() throws { | ||
let testCase = TestCodable(value: 0x23) | ||
let encoded = try JamEncoder.encode(testCase) | ||
#expect(encoded == Data([0xAB, 0x23])) | ||
let decoded = try JamDecoder.decode(TestCodable.self, from: encoded, withConfig: testCase) | ||
#expect(decoded.value == 0x23) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import Foundation | ||
import Testing | ||
|
||
@testable import Codec | ||
|
||
struct SortedSetTests { | ||
@Test func encode() throws { | ||
let testCase: SortedSet<UInt8> = SortedSet(alias: [1, 2, 3]) | ||
let encoded = try JamEncoder.encode(testCase) | ||
#expect(encoded == Data([3, 1, 2, 3])) | ||
} | ||
|
||
@Test func decode() throws { | ||
let decoded = try JamDecoder.decode(SortedSet<UInt8>.self, from: Data([12, 1, 2, 3])) | ||
#expect(decoded.alias == [1, 2, 3]) | ||
} | ||
|
||
@Test func invalidData() throws { | ||
#expect(throws: DecodingError.self) { | ||
try JamDecoder.decode(SortedSet<UInt>.self, from: Data([12, 1, 2, 2])) | ||
} | ||
|
||
#expect(throws: DecodingError.self) { | ||
try JamDecoder.decode(SortedSet<UInt>.self, from: Data([12, 3, 2, 1])) | ||
} | ||
} | ||
} |