diff --git a/.license_header_template b/.license_header_template new file mode 100644 index 0000000..31a6e18 --- /dev/null +++ b/.license_header_template @@ -0,0 +1,13 @@ +@@===----------------------------------------------------------------------===@@ +@@ +@@ This source file is part of the swift-libp2p open source project +@@ +@@ Copyright (c) YEARS swift-libp2p project authors +@@ Licensed under MIT +@@ +@@ See LICENSE for license information +@@ See CONTRIBUTORS for the list of swift-libp2p project authors +@@ +@@ SPDX-License-Identifier: MIT +@@ +@@===----------------------------------------------------------------------===@@ diff --git a/.licenseignore b/.licenseignore new file mode 100644 index 0000000..f72ca30 --- /dev/null +++ b/.licenseignore @@ -0,0 +1,11 @@ +.github/workflows/configs/.flake8 +**/*.yml +*.md +*.txt +Package.swift +Package.resolved +.gitignore +.swift-format +.licenseignore +.license_header_template +Sources/Multicodec/Codecs.swift diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..7e8ae73 --- /dev/null +++ b/.swift-format @@ -0,0 +1,68 @@ +{ + "version" : 1, + "indentation" : { + "spaces" : 4 + }, + "tabWidth" : 4, + "fileScopedDeclarationPrivacy" : { + "accessLevel" : "private" + }, + "spacesAroundRangeFormationOperators" : false, + "indentConditionalCompilationBlocks" : false, + "indentSwitchCaseLabels" : false, + "lineBreakAroundMultilineExpressionChainComponents" : false, + "lineBreakBeforeControlFlowKeywords" : false, + "lineBreakBeforeEachArgument" : true, + "lineBreakBeforeEachGenericRequirement" : true, + "lineLength" : 120, + "maximumBlankLines" : 1, + "respectsExistingLineBreaks" : true, + "prioritizeKeepingFunctionOutputTogether" : true, + "noAssignmentInExpressions" : { + "allowedFunctions" : [ + "XCTAssertNoThrow", + "XCTAssertThrowsError" + ] + }, + "rules" : { + "AllPublicDeclarationsHaveDocumentation" : false, + "AlwaysUseLiteralForEmptyCollectionInit" : false, + "AlwaysUseLowerCamelCase" : false, + "AmbiguousTrailingClosureOverload" : true, + "BeginDocumentationCommentWithOneLineSummary" : false, + "DoNotUseSemicolons" : true, + "DontRepeatTypeInStaticProperties" : true, + "FileScopedDeclarationPrivacy" : true, + "FullyIndirectEnum" : true, + "GroupNumericLiterals" : true, + "IdentifiersMustBeASCII" : true, + "NeverForceUnwrap" : false, + "NeverUseForceTry" : false, + "NeverUseImplicitlyUnwrappedOptionals" : false, + "NoAccessLevelOnExtensionDeclaration" : true, + "NoAssignmentInExpressions" : true, + "NoBlockComments" : true, + "NoCasesWithOnlyFallthrough" : true, + "NoEmptyTrailingClosureParentheses" : true, + "NoLabelsInCasePatterns" : true, + "NoLeadingUnderscores" : false, + "NoParensAroundConditions" : true, + "NoVoidReturnOnFunctionSignature" : true, + "OmitExplicitReturns" : true, + "OneCasePerLine" : true, + "OneVariableDeclarationPerLine" : true, + "OnlyOneTrailingClosureArgument" : true, + "OrderedImports" : true, + "ReplaceForEachWithForLoop" : true, + "ReturnVoidInsteadOfEmptyTuple" : true, + "UseEarlyExits" : false, + "UseExplicitNilCheckInConditions" : false, + "UseLetInEveryBoundCaseVariable" : false, + "UseShorthandTypeNames" : true, + "UseSingleLinePropertyGetter" : false, + "UseSynthesizedInitializer" : false, + "UseTripleSlashForDocumentationComments" : true, + "UseWhereClausesInForLoops" : false, + "ValidateDocumentationComments" : false + } +} diff --git a/Package.swift b/Package.swift index 539f597..34f38ad 100644 --- a/Package.swift +++ b/Package.swift @@ -1,5 +1,17 @@ -// swift-tools-version:5.4 -// The swift-tools-version declares the minimum version of Swift required to build this package. +// swift-tools-version:5.5 +//===----------------------------------------------------------------------===// +// +// This source file is part of the swift-libp2p open source project +// +// Copyright (c) 2022-2025 swift-libp2p project authors +// Licensed under MIT +// +// See LICENSE for license information +// See CONTRIBUTORS for the list of swift-libp2p project authors +// +// SPDX-License-Identifier: MIT +// +//===----------------------------------------------------------------------===// import PackageDescription @@ -7,21 +19,21 @@ let package = Package( name: "swift-multicodec", platforms: [ .macOS(.v10_10), - .iOS(.v10) + .iOS(.v10), ], products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. .executable( name: "update-codecs", - targets: ["Updater"]), + targets: ["Updater"] + ), .library( name: "Multicodec", - targets: ["Multicodec"]), + targets: ["Multicodec"] + ), ], dependencies: [ // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - //.package(name: "VarInt", path: "../VarInt") //Use this when attempting to run update-codecs (until our repo is public) .package(url: "https://github.com/swift-libp2p/swift-varint.git", from: "0.0.1") ], targets: [ @@ -29,14 +41,17 @@ let package = Package( // Targets can depend on other targets in this package, and on products in packages which this package depends on. .executableTarget( name: "Updater", - dependencies: []), + dependencies: [] + ), .target( name: "Multicodec", dependencies: [ - .product(name: "VarInt", package: "swift-varint"), - ]), + .product(name: "VarInt", package: "swift-varint") + ] + ), .testTarget( name: "MulticodecTests", - dependencies: ["Multicodec"]), + dependencies: ["Multicodec"] + ), ] ) diff --git a/README.md b/README.md index a2ae6eb..4428ab0 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,11 @@ let package = Package( ) ``` - ## Usage ### Example -```Swift +```swift import Multicodec @@ -72,7 +71,7 @@ Updating the Codec enum is done by running the following command at the projects ## Contributing -Contributions are welcomed! This code is very much a proof of concept. I can guarantee you there's a better / safer way to accomplish the same results. Any suggestions, improvements, or even just critques, are welcome! +Contributions are welcomed! This code is very much a proof of concept. I can guarantee you there's a better / safer way to accomplish the same results. Any suggestions, improvements, or even just critiques, are welcome! Let's make this code better together! 🤝 diff --git a/Sources/Multicodec/Codecs+Equatable.swift b/Sources/Multicodec/Codecs+Equatable.swift index f2b2646..5611900 100644 --- a/Sources/Multicodec/Codecs+Equatable.swift +++ b/Sources/Multicodec/Codecs+Equatable.swift @@ -1,30 +1,37 @@ +//===----------------------------------------------------------------------===// // -// Codecs+Equatable.swift -// +// This source file is part of the swift-libp2p open source project // -// Created by Brandon Toms on 5/1/22. +// Copyright (c) 2022-2025 swift-libp2p project authors +// Licensed under MIT // +// See LICENSE for license information +// See CONTRIBUTORS for the list of swift-libp2p project authors +// +// SPDX-License-Identifier: MIT +// +//===----------------------------------------------------------------------===// import Foundation -public extension Codecs { - static func ==(lhs: Codecs, rhs: Codecs) -> Bool { - return lhs.rawValue == rhs.rawValue +extension Codecs { + public static func == (lhs: Codecs, rhs: Codecs) -> Bool { + lhs.rawValue == rhs.rawValue } - - static func ==(lhs: Codecs, rhs: Int64) -> Bool { - return lhs.rawValue == rhs + + public static func == (lhs: Codecs, rhs: Int64) -> Bool { + lhs.rawValue == rhs } - static func ==(lhs: Codecs, rhs: Int) -> Bool { - return lhs.rawValue == Int64(rhs) + public static func == (lhs: Codecs, rhs: Int) -> Bool { + lhs.rawValue == Int64(rhs) } - static func ==(lhs: Codecs, rhs: String) -> Bool { - return lhs.name == rhs + public static func == (lhs: Codecs, rhs: String) -> Bool { + lhs.name == rhs } - - func isEqual(object: AnyObject?) -> Bool { + + public func isEqual(object: AnyObject?) -> Bool { if let obj = object as? Codecs { return self.rawValue == obj.rawValue } else if let obj = object as? Int64 { @@ -57,4 +64,3 @@ public extension Codecs { // return lhs.rawValue == rhs // } //} - diff --git a/Sources/Multicodec/Codecs.swift b/Sources/Multicodec/Codecs.swift index 80e0bfb..b2fd0ea 100644 --- a/Sources/Multicodec/Codecs.swift +++ b/Sources/Multicodec/Codecs.swift @@ -1,9 +1,20 @@ +// swift-format-ignore-file +//===----------------------------------------------------------------------===// // -// Codecs.swift +// This source file is part of the swift-libp2p open source project // +// Copyright (c) 2022-2025 swift-libp2p project authors +// Licensed under MIT // -// Created by Brandon Toms on 5/1/22. -// Updated on 2/8/24 +// See LICENSE for license information +// See CONTRIBUTORS for the list of swift-libp2p project authors +// +// SPDX-License-Identifier: MIT +// +//===----------------------------------------------------------------------===// +// +// This file was generated automatically (do NOT modify this file) +// Updated on 2/28/25 import Foundation import VarInt @@ -68,6 +79,7 @@ public enum Codecs:UInt64, CaseIterable, Equatable { case git_raw = 0x78 case torrent_info = 0x7b case torrent_file = 0x7c + case blake3_hashseq = 0x80 case leofcoin_block = 0x81 case leofcoin_tx = 0x82 case leofcoin_pr = 0x83 @@ -154,6 +166,7 @@ public enum Codecs:UInt64, CaseIterable, Equatable { case wss = 0x01de case p2p_websocket_star = 0x01df case http = 0x01e0 + case http_path = 0x01e1 case swhid_1_snp = 0x01f0 case json = 0x0200 case messagepack = 0x0201 @@ -185,6 +198,16 @@ public enum Codecs:UInt64, CaseIterable, Equatable { case x448_pub = 0x1204 case rsa_pub = 0x1205 case sm2_pub = 0x1206 + case vlad = 0x1207 + case provenance_log = 0x1208 + case provenance_log_entry = 0x1209 + case provenance_log_script = 0x120a + case mlkem_512_pub = 0x120b + case mlkem_768_pub = 0x120c + case mlkem_1024_pub = 0x120d + case multisig = 0x1239 + case multikey = 0x123a + case nonce = 0x123b case ed25519_priv = 0x1300 case secp256k1_priv = 0x1301 case x25519_priv = 0x1302 @@ -196,11 +219,32 @@ public enum Codecs:UInt64, CaseIterable, Equatable { case bls12_381_g1_priv = 0x1309 case bls12_381_g2_priv = 0x130a case bls12_381_g1g2_priv = 0x130b + case bls12_381_g1_pub_share = 0x130c + case bls12_381_g2_pub_share = 0x130d + case bls12_381_g1_priv_share = 0x130e + case bls12_381_g2_priv_share = 0x130f + case sm2_priv = 0x1310 + case lamport_sha3_512_pub = 0x1a14 + case lamport_sha3_384_pub = 0x1a15 + case lamport_sha3_256_pub = 0x1a16 + case lamport_sha3_512_priv = 0x1a24 + case lamport_sha3_384_priv = 0x1a25 + case lamport_sha3_256_priv = 0x1a26 + case lamport_sha3_512_priv_share = 0x1a34 + case lamport_sha3_384_priv_share = 0x1a35 + case lamport_sha3_256_priv_share = 0x1a36 + case lamport_sha3_512_sig = 0x1a44 + case lamport_sha3_384_sig = 0x1a45 + case lamport_sha3_256_sig = 0x1a46 + case lamport_sha3_512_sig_share = 0x1a54 + case lamport_sha3_384_sig_share = 0x1a55 + case lamport_sha3_256_sig_share = 0x1a56 case kangarootwelve = 0x1d01 case aes_gcm_256 = 0x2000 case silverpine = 0x3f42 case sm3_256 = 0x534d case sha256a = 0x7012 + case chacha20_poly1305 = 0xa000 case blake2b_8 = 0xb201 case blake2b_16 = 0xb202 case blake2b_24 = 0xb203 @@ -530,18 +574,25 @@ public enum Codecs:UInt64, CaseIterable, Equatable { case rdfc_1 = 0xb403 case ssz = 0xb501 case ssz_sha2_256_bmt = 0xb502 + case sha2_256_chunked = 0xb510 case json_jcs = 0xb601 case iscc = 0xcc01 case zeroxcert_imprint_256 = 0xce11 case nonstandard_sig = 0xd000 + case bcrypt_pbkdf = 0xd00d case es256k = 0xd0e7 - case bls_12381_g1_sig = 0xd0ea - case bls_12381_g2_sig = 0xd0eb + case bls12_381_g1_sig = 0xd0ea + case bls12_381_g2_sig = 0xd0eb case eddsa = 0xd0ed case eip_191 = 0xd191 case jwk_jcs_pub = 0xeb51 case fil_commitment_unsealed = 0xf101 case fil_commitment_sealed = 0xf102 + case shelter_contract_manifest = 0x511e00 + case shelter_contract_text = 0x511e01 + case shelter_contract_data = 0x511e02 + case shelter_file_manifest = 0x511e03 + case shelter_file_chunk = 0x511e04 case plaintextv2 = 0x706c61 case holochain_adr_v0 = 0x807124 case holochain_adr_v1 = 0x817124 @@ -557,6 +608,18 @@ public enum Codecs:UInt64, CaseIterable, Equatable { case es284 = 0xd01201 case es512 = 0xd01202 case rs256 = 0xd01205 + case es256k_msig = 0xd01300 + case bls12_381_g1_msig = 0xd01301 + case bls12_381_g2_msig = 0xd01302 + case eddsa_msig = 0xd01303 + case bls12_381_g1_share_msig = 0xd01304 + case bls12_381_g2_share_msig = 0xd01305 + case lamport_msig = 0xd01306 + case lamport_share_msig = 0xd01307 + case es256_msig = 0xd01308 + case es384_msig = 0xd01309 + case es521_msig = 0xd0130a + case rs256_msig = 0xd0130b case scion = 0xd02000 @@ -717,6 +780,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "ipld" case .torrent_file: return "ipld" + case .blake3_hashseq: + return "ipld" case .leofcoin_block: return "ipld" case .leofcoin_tx: @@ -889,6 +954,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "multiaddr" case .http: return "multiaddr" + case .http_path: + return "multiaddr" case .swhid_1_snp: return "ipld" case .json: @@ -951,6 +1018,26 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "key" case .sm2_pub: return "key" + case .vlad: + return "vlad" + case .provenance_log: + return "serialization" + case .provenance_log_entry: + return "serialization" + case .provenance_log_script: + return "serialization" + case .mlkem_512_pub: + return "key" + case .mlkem_768_pub: + return "key" + case .mlkem_1024_pub: + return "key" + case .multisig: + return "multiformat" + case .multikey: + return "multiformat" + case .nonce: + return "nonce" case .ed25519_priv: return "key" case .secp256k1_priv: @@ -973,6 +1060,46 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "key" case .bls12_381_g1g2_priv: return "key" + case .bls12_381_g1_pub_share: + return "key" + case .bls12_381_g2_pub_share: + return "key" + case .bls12_381_g1_priv_share: + return "key" + case .bls12_381_g2_priv_share: + return "key" + case .sm2_priv: + return "key" + case .lamport_sha3_512_pub: + return "key" + case .lamport_sha3_384_pub: + return "key" + case .lamport_sha3_256_pub: + return "key" + case .lamport_sha3_512_priv: + return "key" + case .lamport_sha3_384_priv: + return "key" + case .lamport_sha3_256_priv: + return "key" + case .lamport_sha3_512_priv_share: + return "key" + case .lamport_sha3_384_priv_share: + return "key" + case .lamport_sha3_256_priv_share: + return "key" + case .lamport_sha3_512_sig: + return "multisig" + case .lamport_sha3_384_sig: + return "multisig" + case .lamport_sha3_256_sig: + return "multisig" + case .lamport_sha3_512_sig_share: + return "multisig" + case .lamport_sha3_384_sig_share: + return "multisig" + case .lamport_sha3_256_sig_share: + return "multisig" case .kangarootwelve: return "multihash" case .aes_gcm_256: @@ -983,6 +1110,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "multihash" case .sha256a: return "hash" + case .chacha20_poly1305: + return "multikey" case .blake2b_8: return "multihash" case .blake2b_16: @@ -1641,6 +1770,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "serialization" case .ssz_sha2_256_bmt: return "multihash" + case .sha2_256_chunked: + return "multihash" case .json_jcs: return "ipld" case .iscc: @@ -1649,11 +1780,13 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "zeroxcert" case .nonstandard_sig: return "varsig" + case .bcrypt_pbkdf: + return "multihash" case .es256k: return "varsig" - case .bls_12381_g1_sig: + case .bls12_381_g1_sig: return "varsig" - case .bls_12381_g2_sig: + case .bls12_381_g2_sig: return "varsig" case .eddsa: return "varsig" @@ -1665,6 +1798,16 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "filecoin" case .fil_commitment_sealed: return "filecoin" + case .shelter_contract_manifest: + return "shelter" + case .shelter_contract_text: + return "shelter" + case .shelter_contract_data: + return "shelter" + case .shelter_file_manifest: + return "shelter" + case .shelter_file_chunk: + return "shelter" case .plaintextv2: return "multiaddr" case .holochain_adr_v0: @@ -1695,6 +1838,30 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "varsig" case .rs256: return "varsig" + case .es256k_msig: + return "multisig" + case .bls12_381_g1_msig: + return "multisig" + case .bls12_381_g2_msig: + return "multisig" + case .eddsa_msig: + return "multisig" + case .bls12_381_g1_share_msig: + return "multisig" + case .bls12_381_g2_share_msig: + return "multisig" + case .lamport_msig: + return "multisig" + case .lamport_share_msig: + return "multisig" + case .es256_msig: + return "multisig" + case .es384_msig: + return "multisig" + case .es521_msig: + return "multisig" + case .rs256_msig: + return "multisig" case .scion: return "multiaddr" @@ -1747,6 +1914,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "Torrent file info field (bencoded)" case .torrent_file: return "Torrent file (bencoded)" + case .blake3_hashseq: + return "BLAKE3 hash sequence - per Iroh collections spec" case .leofcoin_block: return "Leofcoin Block" case .leofcoin_tx: @@ -1802,9 +1971,9 @@ public enum Codecs:UInt64, CaseIterable, Equatable { case .zcash_tx: return "Zcash Tx" case .caip_50: - return "CAIP-50 multi-chain account id" + return "CAIP-50 multi-chain account ID" case .streamid: - return "Ceramic Stream Id" + return "Ceramic Stream ID" case .stellar_block: return "Stellar Block" case .stellar_tx: @@ -1877,6 +2046,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "Secure Scuttlebutt - Secret Handshake Stream" case .certhash: return "TLS certificate's fingerprint as a multihash" + case .http_path: + return "Percent-encoded path to an HTTP resource" case .swhid_1_snp: return "SoftWare Heritage persistent IDentifier version 1 snapshot" case .json: @@ -1927,6 +2098,26 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "RSA public key. DER-encoded ASN.1 type RSAPublicKey according to IETF RFC 8017 (PKCS #1)" case .sm2_pub: return "SM2 public key (compressed)" + case .vlad: + return "Verifiable Long-lived ADdress" + case .provenance_log: + return "Verifiable and permissioned append-only log" + case .provenance_log_entry: + return "Verifiable and permissioned append-only log entry" + case .provenance_log_script: + return "Verifiable and permissioned append-only log script" + case .mlkem_512_pub: + return "ML-KEM 512 public key; as specified by FIPS 203" + case .mlkem_768_pub: + return "ML-KEM 768 public key; as specified by FIPS 203" + case .mlkem_1024_pub: + return "ML-KEM 1024 public key; as specified by FIPS 203" + case .multisig: + return "Digital signature multiformat" + case .multikey: + return "Encryption key multiformat" + case .nonce: + return "Nonce random value" case .ed25519_priv: return "Ed25519 private key" case .secp256k1_priv: @@ -1949,6 +2140,46 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "BLS12-381 G2 private key" case .bls12_381_g1g2_priv: return "BLS12-381 G1 and G2 private key" + case .bls12_381_g1_pub_share: + return "BLS12-381 G1 public key share" + case .bls12_381_g2_pub_share: + return "BLS12-381 G2 public key share" + case .bls12_381_g1_priv_share: + return "BLS12-381 G1 private key share" + case .bls12_381_g2_priv_share: + return "BLS12-381 G2 private key share" + case .sm2_priv: + return "SM2 private key" + case .lamport_sha3_512_pub: + return "Lamport public key based on SHA3-512" + case .lamport_sha3_384_pub: + return "Lamport public key based on SHA3-384" + case .lamport_sha3_256_pub: + return "Lamport public key based on SHA3-256" + case .lamport_sha3_512_priv: + return "Lamport private key based on SHA3-512" + case .lamport_sha3_384_priv: + return "Lamport private key based on SHA3-384" + case .lamport_sha3_256_priv: + return "Lamport private key based on SHA3-256" + case .lamport_sha3_512_priv_share: + return "Lamport private key share based on SHA3-512 and split with Shamir gf256" + case .lamport_sha3_384_priv_share: + return "Lamport private key share based on SHA3-384 and split with Shamir gf256" + case .lamport_sha3_256_priv_share: + return "Lamport private key share based on SHA3-256 and split with Shamir gf256" + case .lamport_sha3_512_sig: + return "Lamport signature based on SHA3-512" + case .lamport_sha3_384_sig: + return "Lamport signature based on SHA3-384" + case .lamport_sha3_256_sig: + return "Lamport signature based on SHA3-256" + case .lamport_sha3_512_sig_share: + return "Lamport signature share based on SHA3-512 and split with Shamir gf256" + case .lamport_sha3_384_sig_share: + return "Lamport signature share based on SHA3-384 and split with Shamir gf256" + case .lamport_sha3_256_sig_share: + return "Lamport signature share based on SHA3-256 and split with Shamir gf256" case .kangarootwelve: return "KangarooTwelve is an extendable-output hash function based on Keccak-p" case .aes_gcm_256: @@ -1957,6 +2188,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "Experimental QUIC over yggdrasil and ironwood routing protocol" case .sha256a: return "The sum of multiple sha2-256 hashes; as specified by Ceramic CIP-124." + case .chacha20_poly1305: + return "ChaCha20_Poly1305 encryption scheme" case .blake2b_8: return "Blake2b consists of 64 output lengths that give different hashes" case .blake2s_8: @@ -1985,6 +2218,8 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "SimpleSerialize (SSZ) serialization" case .ssz_sha2_256_bmt: return "SSZ Merkle tree root using SHA2-256 as the hashing function and SSZ serialization for the block binary" + case .sha2_256_chunked: + return "Hash of concatenated SHA2-256 digests of 8*2^n MiB source chunks; n = ceil(log2(source_size/(10^4 * 8MiB)))" case .json_jcs: return "The result of canonicalizing an input according to JCS - JSON Canonicalisation Scheme (RFC 8785)" case .iscc: @@ -1993,12 +2228,14 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "0xcert Asset Imprint (root hash)" case .nonstandard_sig: return "Namespace for all not yet standard signature algorithms" + case .bcrypt_pbkdf: + return "Bcrypt-PBKDF key derivation function" case .es256k: - return "ES256K Siganture Algorithm (secp256k1)" - case .bls_12381_g1_sig: - return "G1 signature for BLS-12381-G2" - case .bls_12381_g2_sig: - return "G2 signature for BLS-12381-G1" + return "ES256K Signature Algorithm (secp256k1)" + case .bls12_381_g1_sig: + return "G1 signature for BLS12-381" + case .bls12_381_g2_sig: + return "G2 signature for BLS12-381" case .eddsa: return "Edwards-Curve Digital Signature Algorithm" case .eip_191: @@ -2009,6 +2246,16 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "Filecoin piece or sector data commitment merkle node/root (CommP & CommD)" case .fil_commitment_sealed: return "Filecoin sector data commitment merkle node/root - sealed and replicated (CommR)" + case .shelter_contract_manifest: + return "Shelter protocol contract manifest" + case .shelter_contract_text: + return "Shelter protocol contract text" + case .shelter_contract_data: + return "Shelter protocol contract data (contract chain)" + case .shelter_file_manifest: + return "Shelter protocol file manifest" + case .shelter_file_chunk: + return "Shelter protocol file chunk" case .holochain_adr_v0: return "Holochain v0 address + 8 R-S (63 x Base-32)" case .holochain_adr_v1: @@ -2037,6 +2284,30 @@ public enum Codecs:UInt64, CaseIterable, Equatable { return "ES512 Signature Algorithm" case .rs256: return "RS256 Signature Algorithm" + case .es256k_msig: + return "ES256K (secp256k1) Signature as Multisig" + case .bls12_381_g1_msig: + return "G1 signature for BLS-12381-G2 as Multisig" + case .bls12_381_g2_msig: + return "G2 signature for BLS-12381-G1 as Multisig" + case .eddsa_msig: + return "Edwards-Curve Digital Signature as Multisig" + case .bls12_381_g1_share_msig: + return "G1 threshold signature share for BLS-12381-G2 as Multisig" + case .bls12_381_g2_share_msig: + return "G2 threshold signature share for BLS-12381-G1 as Multisig" + case .lamport_msig: + return "Lamport signature as Multisig" + case .lamport_share_msig: + return "Lamport threshold signature share as Multisig" + case .es256_msig: + return "ECDSA P-256 Signature as Multisig" + case .es384_msig: + return "ECDSA P-384 Signature as Multisig" + case .es521_msig: + return "ECDSA P-521 Signature as Multisig" + case .rs256_msig: + return "RS256 Signature as Multisig" case .scion: return "SCION Internet architecture" default: return nil diff --git a/Sources/Multicodec/Multicodec.swift b/Sources/Multicodec/Multicodec.swift index 6d3ad79..7d0ad76 100644 --- a/Sources/Multicodec/Multicodec.swift +++ b/Sources/Multicodec/Multicodec.swift @@ -1,21 +1,30 @@ +//===----------------------------------------------------------------------===// // -// Multicodec.swift -// SwiftMulticodec +// This source file is part of the swift-libp2p open source project +// +// Copyright (c) 2022-2025 swift-libp2p project authors +// Licensed under MIT +// +// See LICENSE for license information +// See CONTRIBUTORS for the list of swift-libp2p project authors +// +// SPDX-License-Identifier: MIT +// +//===----------------------------------------------------------------------===// // // Created by Teo Sartori // Modified by Brandon Toms on 5/1/2022 -// + import Foundation import VarInt -enum MulticodecError : Error { +enum MulticodecError: Error { case PrefixExtractionBufferTooSmall case PrefixExtractionValueOverflow case UnknownCodecString case UnknownCodecId } - /// Extract the prefix value from a multicodec prefixed byte buffer /// /// - Parameter bytes: a multicodec prefixed byte buffer @@ -28,7 +37,7 @@ public func extractPrefix(bytes: [UInt8]) throws -> UInt64 { if bytesRead == 0 { throw MulticodecError.PrefixExtractionBufferTooSmall } throw MulticodecError.PrefixExtractionValueOverflow } - + return prefix } @@ -38,7 +47,7 @@ public func extractPrefix(bytes: [UInt8]) throws -> UInt64 { /// - Returns: the prefix value for the given multicodec as bytes /// - Throws: UnknownCodecString if the name was invalid public func getPrefix(multiCodec: String) throws -> [UInt8] { - return putUVarInt(try Codecs(multiCodec).rawValue) + putUVarInt(try Codecs(multiCodec).rawValue) } /// Return the prefix value for a given multicodec string @@ -47,10 +56,9 @@ public func getPrefix(multiCodec: String) throws -> [UInt8] { /// - Returns: the prefix value for the given multicodec as bytes /// - Throws: UnknownCodecString if the name was invalid public func getPrefix(multiCodec: Codecs) -> [UInt8] { - return putUVarInt(multiCodec.rawValue) + putUVarInt(multiCodec.rawValue) } - /// Add multicodec prefix to the front of the given byte buffer /// /// - Parameters: @@ -59,7 +67,7 @@ public func getPrefix(multiCodec: Codecs) -> [UInt8] { /// - Returns: the prefixed byte buffer /// - Throws: UnknownCodecString if given an invalid multicodec name public func addPrefix(multiCodec: String, bytes: [UInt8]) throws -> [UInt8] { - return try getPrefix(multiCodec: multiCodec) + bytes + try getPrefix(multiCodec: multiCodec) + bytes } /// Add multicodec prefix to the front of the given byte buffer @@ -70,7 +78,7 @@ public func addPrefix(multiCodec: String, bytes: [UInt8]) throws -> [UInt8] { /// - Returns: the prefixed byte buffer /// - Throws: UnknownCodecString if given an invalid multicodec name public func addPrefix(code: Int64, bytes: [UInt8]) throws -> [UInt8] { - return try getPrefix(multiCodec: try Codecs(code).name) + bytes + try getPrefix(multiCodec: try Codecs(code).name) + bytes } /// Add multicodec prefix to the front of the given byte buffer @@ -81,7 +89,7 @@ public func addPrefix(code: Int64, bytes: [UInt8]) throws -> [UInt8] { /// - Returns: the prefixed byte buffer /// - Throws: UnknownCodecString if given an invalid multicodec name public func addPrefix(code: UInt64, bytes: [UInt8]) throws -> [UInt8] { - return try getPrefix(multiCodec: try Codecs(code).name) + bytes + try getPrefix(multiCodec: try Codecs(code).name) + bytes } /// Add multicodec prefix to the front of the given byte buffer @@ -91,8 +99,8 @@ public func addPrefix(code: UInt64, bytes: [UInt8]) throws -> [UInt8] { /// - bytes: the byte buffer to prefix /// - Returns: the prefixed byte buffer /// - Throws: UnknownCodecString if given an invalid multicodec name -public func addPrefix(code: Int, bytes: [UInt8]) throws -> [UInt8] { - return try getPrefix(multiCodec: try Codecs(code).name) + bytes +public func addPrefix(code: Int, bytes: [UInt8]) throws -> [UInt8] { + try getPrefix(multiCodec: try Codecs(code).name) + bytes } /// Add multicodec prefix to the front of the given byte buffer @@ -102,10 +110,9 @@ public func addPrefix(code: Int, bytes: [UInt8]) throws -> [UInt8] { /// - bytes: the byte buffer to prefix /// - Returns: the prefixed byte buffer public func addPrefix(codec: Codecs, bytes: [UInt8]) -> [UInt8] { - return getPrefix(multiCodec: codec) + bytes + getPrefix(multiCodec: codec) + bytes } - /// Remove the prefix from a prefixed byte buffer /// /// - Parameter bytes: the prefixed byte buffer @@ -116,7 +123,6 @@ public func removePrefix(bytes: [UInt8]) throws -> [UInt8] { return Array(bytes[prefix.count...]) } - /// Get the codec name of the codec in the given byte buffer /// /// - Parameter bytes: the multicodec prefixed byte buffer @@ -131,27 +137,29 @@ public func getCodecEnum(bytes: [UInt8]) throws -> Codecs { return try Codecs(prefix) } -public extension String { +extension String { /// Encodes a String into it's UTF8 Byte Array with the specified Multicodec prefix - func encodeUTF8(as codec:Codecs) -> [UInt8] { - return addPrefix(codec: codec, bytes: Array(self.utf8)) + public func encodeUTF8(as codec: Codecs) -> [UInt8] { + addPrefix(codec: codec, bytes: Array(self.utf8)) } } -public extension Array where Element == UInt8 { - func multiCodec() throws -> (codec:Codecs, bytes:[UInt8]) { +extension Array where Element == UInt8 { + public func multiCodec() throws -> (codec: Codecs, bytes: [UInt8]) { let codec = try getCodecEnum(bytes: self) return (codec: codec, bytes: try removePrefix(bytes: self)) } - - func extractCodec() throws -> (codec:Codecs, bytes:[UInt8]) { + + public func extractCodec() throws -> (codec: Codecs, bytes: [UInt8]) { let codec = try getCodecEnum(bytes: self) return (codec: codec, bytes: try removePrefix(bytes: self)) } - - func decodeMulticodec(using encoding:String.Encoding) throws -> (codec:Codecs, contents:String) { + + public func decodeMulticodec(using encoding: String.Encoding) throws -> (codec: Codecs, contents: String) { let codec = try getCodecEnum(bytes: self) - guard let str = String(bytes: try removePrefix(bytes: self), encoding: encoding) else { throw MulticodecError.UnknownCodecId } //Better Error + guard let str = String(bytes: try removePrefix(bytes: self), encoding: encoding) else { + throw MulticodecError.UnknownCodecId + } //Better Error return (codec: codec, contents: str) } } diff --git a/Sources/Updater/main.swift b/Sources/Updater/main.swift index 1b1a166..9c6319a 100644 --- a/Sources/Updater/main.swift +++ b/Sources/Updater/main.swift @@ -1,11 +1,19 @@ +//===----------------------------------------------------------------------===// // -// Updater.swift -// +// This source file is part of the swift-libp2p open source project // -// Created by Brandon Toms on 5/1/22. +// Copyright (c) 2022-2025 swift-libp2p project authors +// Licensed under MIT // +// See LICENSE for license information +// See CONTRIBUTORS for the list of swift-libp2p project authors +// +// SPDX-License-Identifier: MIT +// +//===----------------------------------------------------------------------===// import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif @@ -22,121 +30,134 @@ import FoundationNetworking // MARK: - Multiformat Codec Table Repository URL var CSVDocumentURL = "https://raw.githubusercontent.com/multiformats/multicodec/master/table.csv" - // MARK: - Templates let HEADER = """ -// -// Codecs.swift -// -// -// Created by Brandon Toms on 5/1/22. -// Updated on {{+date_updated+}} - -import Foundation -import VarInt - -/// An Enum for navigating supported Multiformat Codecs and their properties, most importantly their Name and Integer Code -/// -/// - Warning: Do not use the Codecs `rawValue` directly, instead make sure to use the `code` property to ensure backward compatibility with deprecated codecs. -/// -/// This enumeration is autogenerated from the [multicodec table repository](https://raw.githubusercontent.com/multiformats/multicodec/master/table.csv) -/// -/// To fetch the latest Multicodecs simply run the following cmd at the Multicodec package root -/// ``` -/// swift run update-codecs -/// ``` -""" + // swift-format-ignore-file + //===----------------------------------------------------------------------===// + // + // This source file is part of the swift-libp2p open source project + // + // Copyright (c) 2022-2025 swift-libp2p project authors + // Licensed under MIT + // + // See LICENSE for license information + // See CONTRIBUTORS for the list of swift-libp2p project authors + // + // SPDX-License-Identifier: MIT + // + //===----------------------------------------------------------------------===// + // + // This file was generated automatically (do NOT modify this file) + // Updated on {{+date_updated+}} + + import Foundation + import VarInt + + /// An Enum for navigating supported Multiformat Codecs and their properties, most importantly their Name and Integer Code + /// + /// - Warning: Do not use the Codecs `rawValue` directly, instead make sure to use the `code` property to ensure backward compatibility with deprecated codecs. + /// + /// This enumeration is autogenerated from the [multicodec table repository](https://raw.githubusercontent.com/multiformats/multicodec/master/table.csv) + /// + /// To fetch the latest Multicodecs simply run the following cmd at the Multicodec package root + /// ``` + /// swift run update-codecs + /// ``` + """ let ENUM_DEFINITION_TEMPLATE = """ -{{+enum_scope+}} enum {{+enum_title+}}{{+enum_rawType+}}{{+enum_protocols+}} { - {{+enum_cases+}} - {{+enum_additional_components+}} - {{+enum_computed_properties+}} - {{+enum_functions+}} -} -""" + {{+enum_scope+}} enum {{+enum_title+}}{{+enum_rawType+}}{{+enum_protocols+}} { + {{+enum_cases+}} + {{+enum_additional_components+}} + {{+enum_computed_properties+}} + {{+enum_functions+}} + } + """ let ENUM_CASE = """ -case {{+case_title+}}{{+case_associatedValues+}}{{+case_rawValue+}} -""" + case {{+case_title+}}{{+case_associatedValues+}}{{+case_rawValue+}} + """ let ENUM_COMPUTED_PROPERTY = """ -{{+enum_scope+}} var {{+cp_title+}}:{{+cp_type+}} { - switch self { - {{+cp_case+}} - {{+cp_default+}} + {{+enum_scope+}} var {{+cp_title+}}:{{+cp_type+}} { + switch self { + {{+cp_case+}} + {{+cp_default+}} + } } -} -""" + """ let COMPUTED_PROPERTY_CASE = """ -case .{{+case_title+}}: - return {{+case_value+}} -""" + case .{{+case_title+}}: + return {{+case_value+}} + """ let ENUM_ADDITIONAL_COMPONENTS = """ - /// Allows instantiation of a Codec based on it's name - /// ``` - /// let p2p = try? Codecs("p2p") - /// print(p2p.code) //"0x01a5" - /// print(p2p.name) //"p2p" - /// print(p2p.tag) //"multihash" - /// print(p2p.description) //"libp2p" - /// ``` - /// - Note: The string name is lowercased and replaces dashes (-) for underscores (_) before checking for a match... - {{+enum_scope+}} init(_ name:String) throws { - let n = name.replacingOccurrences(of: "-", with: "_").lowercased() - guard let match = Codecs.allCases.first(where: { "\\($0)" == n }) else { throw MulticodecError.UnknownCodecString } - self = match - } + /// Allows instantiation of a Codec based on it's name + /// ``` + /// let p2p = try? Codecs("p2p") + /// print(p2p.code) //"0x01a5" + /// print(p2p.name) //"p2p" + /// print(p2p.tag) //"multihash" + /// print(p2p.description) //"libp2p" + /// ``` + /// - Note: The string name is lowercased and replaces dashes (-) for underscores (_) before checking for a match... + {{+enum_scope+}} init(_ name:String) throws { + let n = name.replacingOccurrences(of: "-", with: "_").lowercased() + guard let match = Codecs.allCases.first(where: { "\\($0)" == n }) else { throw MulticodecError.UnknownCodecString } + self = match + } - /// Instantiation via signed VarInt - {{+enum_scope+}} init(_ bytes:[UInt8]) throws { - if let s = Codecs(rawValue: uVarInt(bytes).0) { + /// Instantiation via signed VarInt + {{+enum_scope+}} init(_ bytes:[UInt8]) throws { + if let s = Codecs(rawValue: uVarInt(bytes).0) { + self = s + } else { throw MulticodecError.UnknownCodecId } + } + + {{+enum_scope+}} init(_ code:Int) throws { + guard let s = Codecs(rawValue: UInt64(code)) else { throw MulticodecError.UnknownCodecId } self = s - } else { throw MulticodecError.UnknownCodecId } - } - - {{+enum_scope+}} init(_ code:Int) throws { - guard let s = Codecs(rawValue: UInt64(code)) else { throw MulticodecError.UnknownCodecId } - self = s - } - - {{+enum_scope+}} init(_ code:Int64) throws { - guard let s = Codecs(rawValue: UInt64(code)) else { throw MulticodecError.UnknownCodecId } - self = s - } - - {{+enum_scope+}} init(_ code:UInt64) throws { - guard let s = Codecs(rawValue: code) else { throw MulticodecError.UnknownCodecId } - self = s - } + } + + {{+enum_scope+}} init(_ code:Int64) throws { + guard let s = Codecs(rawValue: UInt64(code)) else { throw MulticodecError.UnknownCodecId } + self = s + } + + {{+enum_scope+}} init(_ code:UInt64) throws { + guard let s = Codecs(rawValue: code) else { throw MulticodecError.UnknownCodecId } + self = s + } - /// Returns a list of all known Codec names - {{+enum_scope+}} static var codecNames:[String] { return Codecs.allCases.map { $0.name } } + /// Returns a list of all known Codec names + {{+enum_scope+}} static var codecNames:[String] { return Codecs.allCases.map { $0.name } } - /// Returns a list of Codecs that have the specified tag (ex: 'multiaddr' or 'multihash') - {{+enum_scope+}} static func codecs(withTag _tag:String) -> [Codecs] { return Codecs.allCases.filter( { $0.tag == _tag }) } + /// Returns a list of Codecs that have the specified tag (ex: 'multiaddr' or 'multihash') + {{+enum_scope+}} static func codecs(withTag _tag:String) -> [Codecs] { return Codecs.allCases.filter( { $0.tag == _tag }) } - /// Returns a list of all known Codec codes - {{+enum_scope+}} static var codecCodes:[UInt64] { return Codecs.allCases.map { $0.rawValue } } - - /// Returns the code for this Codec - {{+enum_scope+}} var code:UInt64 { - return self.rawValue - } - - /// Returns the name for this Codec - {{+enum_scope+}} var name:String { return "\\(self)".replacingOccurrences(of: "_", with: "-") } - - /// Returns the code for this Codec as a VarInt Byte Buffer - {{+enum_scope+}} var asVarInt:[UInt8] { return putUVarInt(self.rawValue) } -""" + /// Returns a list of all known Codec codes + {{+enum_scope+}} static var codecCodes:[UInt64] { return Codecs.allCases.map { $0.rawValue } } + + /// Returns the code for this Codec + {{+enum_scope+}} var code:UInt64 { + return self.rawValue + } + + /// Returns the name for this Codec + {{+enum_scope+}} var name:String { return "\\(self)".replacingOccurrences(of: "_", with: "-") } + + /// Returns the code for this Codec as a VarInt Byte Buffer + {{+enum_scope+}} var asVarInt:[UInt8] { return putUVarInt(self.rawValue) } + """ // MARK: - Network Data Fetch -func fetchContents(url:String) -> String? { - guard let u = URL(string: url) else { print("Invalid URL String"); return nil } +func fetchContents(url: String) -> String? { + guard let u = URL(string: url) else { + print("Invalid URL String") + return nil + } do { let data = try Data(contentsOf: u) let str = String(decoding: data, as: UTF8.self) @@ -153,154 +174,194 @@ func fetchContents(url:String) -> String? { // MARK: - CSV Parsing struct CSVData { - let rowNum:Int - let columns:[(key:String, value:String)] + let rowNum: Int + let columns: [(key: String, value: String)] } -func parseStringIntoCSV(_ csv:String, headerRow:Int? = nil) -> [CSVData] { - var rows = csv.split(separator: "\n") //TODO: Handle Carriage Returns... - var headerKeys:[String] = [] +func parseStringIntoCSV(_ csv: String, headerRow: Int? = nil) -> [CSVData] { + var rows = csv.split(separator: "\n") //TODO: Handle Carriage Returns... + var headerKeys: [String] = [] if let hr = headerRow, rows.count > hr { headerKeys = rows[hr].split(separator: ",").map { stripLeadingSpaces(String($0)) } rows.remove(at: hr) } return rows.enumerated().compactMap { - CSVData(rowNum: $0.offset, columns: $0.element.split(separator: ",").enumerated().map { - if headerKeys.count > $0.offset { - return (key: headerKeys[$0.offset], value: stripLeadingSpaces(String($0.element))) - } else { - return (key: "", value: stripLeadingSpaces(String($0.element))) + CSVData( + rowNum: $0.offset, + columns: $0.element.split(separator: ",").enumerated().map { + if headerKeys.count > $0.offset { + return (key: headerKeys[$0.offset], value: stripLeadingSpaces(String($0.element))) + } else { + return (key: "", value: stripLeadingSpaces(String($0.element))) + } } - }) + ) } } -func stripLeadingSpaces(_ str:String) -> String { - var s = str; while s.hasPrefix(" ") { s = String(s.dropFirst()) }; return s +func stripLeadingSpaces(_ str: String) -> String { + var s = str + while s.hasPrefix(" ") { s = String(s.dropFirst()) } + return s } - // MARK: - Enumeration Building Blocks class EnumCase { - let title:String - let rawValue:String? - let associatedValue:String? - - var computedProperties:[String:Any] = [:] - - init(title:String, rawValue:String) { + let title: String + let rawValue: String? + let associatedValue: String? + + var computedProperties: [String: Any] = [:] + + init(title: String, rawValue: String) { self.title = title self.rawValue = rawValue self.associatedValue = nil } - - init(title:String, associatedValue:String) { + + init(title: String, associatedValue: String) { self.title = title self.associatedValue = associatedValue self.rawValue = nil } - - init(title:String) { + + init(title: String) { self.title = title self.associatedValue = nil self.rawValue = nil } } -enum Scope:String { - case INTERNAL = "internal" - case OPEN = "open" - case PUBLIC = "public" - case PRIVATE = "private" +enum Scope: String { + case INTERNAL = "internal" + case OPEN = "open" + case PUBLIC = "public" + case PRIVATE = "private" case FILEPRIVATE = "fileprivate" } struct ComputedProperty { - let title:String - let type:Any - let defaultValue:String - let caseKey:String + let title: String + let type: Any + let defaultValue: String + let caseKey: String } -func generateEnum(scope:Scope, title:String, rawType:Any? = nil, protocolConformances:[String], cases:[EnumCase], computedProps:[ComputedProperty] = []) -> Data? { +func generateEnum( + scope: Scope, + title: String, + rawType: Any? = nil, + protocolConformances: [String], + cases: [EnumCase], + computedProps: [ComputedProperty] = [] +) -> Data? { let dateFormatter = DateFormatter() dateFormatter.dateStyle = .short var e = HEADER.replacingOccurrences(of: "{{+date_updated+}}", with: dateFormatter.string(from: Date())) - + e = e + "\n" + ENUM_DEFINITION_TEMPLATE e = e.replacingOccurrences(of: "{{+enum_scope+}}", with: scope.rawValue) - e = e.replacingOccurrences(of: "{{+enum_title+}}", with: title) //Enforce CamelCase??? + e = e.replacingOccurrences(of: "{{+enum_title+}}", with: title) //Enforce CamelCase??? if let rt = rawType { e = e.replacingOccurrences(of: "{{+enum_rawType+}}", with: ":\(rt.self)") if !protocolConformances.isEmpty { - e = e.replacingOccurrences(of: "{{+enum_protocols+}}", with: protocolConformances.map { ", \($0)" }.joined()) - } else { e = e.replacingOccurrences(of: "{{+enum_protocols+}}", with: "") } + e = e.replacingOccurrences( + of: "{{+enum_protocols+}}", + with: protocolConformances.map { ", \($0)" }.joined() + ) + } else { + e = e.replacingOccurrences(of: "{{+enum_protocols+}}", with: "") + } } else { e = e.replacingOccurrences(of: "{{+enum_rawType+}}", with: "") if !protocolConformances.isEmpty { - e = e.replacingOccurrences(of: "{{+enum_protocols+}}", with: protocolConformances.enumerated().map { - if $0.offset == 0 { return ": \($0.element)" } - return ", \($0.element)" - }.joined()) - } else { e = e.replacingOccurrences(of: "{{+enum_protocols+}}", with: "") } + e = e.replacingOccurrences( + of: "{{+enum_protocols+}}", + with: protocolConformances.enumerated().map { + if $0.offset == 0 { return ": \($0.element)" } + return ", \($0.element)" + }.joined() + ) + } else { + e = e.replacingOccurrences(of: "{{+enum_protocols+}}", with: "") + } } - + //Find the largest Key for formatting reasons... var largestKey = 0 - cases.forEach { if $0.title.count > largestKey { largestKey = $0.title.count } } + for c in cases { + if c.title.count > largestKey { largestKey = c.title.count } + } largestKey = largestKey + 1 - - e = e.replacingOccurrences(of: "{{+enum_cases+}}", with: cases.map { generateCase($0, rawValueOffset: largestKey) }.joined(separator: "\n\t")) - - let additionalComponents = ENUM_ADDITIONAL_COMPONENTS.replacingOccurrences(of: "{{+enum_scope+}}", with: scope.rawValue) + + e = e.replacingOccurrences( + of: "{{+enum_cases+}}", + with: cases.map { generateCase($0, rawValueOffset: largestKey) }.joined(separator: "\n\t") + ) + + let additionalComponents = ENUM_ADDITIONAL_COMPONENTS.replacingOccurrences( + of: "{{+enum_scope+}}", + with: scope.rawValue + ) e = e.replacingOccurrences(of: "{{+enum_additional_components+}}", with: "\n\(additionalComponents)") - + if !computedProps.isEmpty { - e = e.replacingOccurrences(of: "{{+enum_computed_properties+}}", with: computedProps.map { - generateComputedProperty($0, cases: cases, scope: scope) - }.joined(separator: "\n")) + e = e.replacingOccurrences( + of: "{{+enum_computed_properties+}}", + with: computedProps.map { + generateComputedProperty($0, cases: cases, scope: scope) + }.joined(separator: "\n") + ) } else { e = e.replacingOccurrences(of: "{{+enum_computed_properties+}}", with: "") } e = e.replacingOccurrences(of: "{{+enum_functions+}}", with: "") //print(e) - + return e.data(using: .utf8) } -func generateCase(_ enumCase:EnumCase, rawValueOffset:Int = 1) -> String { +func generateCase(_ enumCase: EnumCase, rawValueOffset: Int = 1) -> String { var c = ENUM_CASE c = c.replacingOccurrences(of: "{{+case_title+}}", with: enumCase.title) if let rv = enumCase.rawValue { - c = c.replacingOccurrences(of: "{{+case_rawValue+}}", with: "\(String(repeating: " ", count: rawValueOffset - enumCase.title.count))= \(rv)") + c = c.replacingOccurrences( + of: "{{+case_rawValue+}}", + with: "\(String(repeating: " ", count: rawValueOffset - enumCase.title.count))= \(rv)" + ) c = c.replacingOccurrences(of: "{{+case_associatedValues+}}", with: "") } else if let av = enumCase.associatedValue { c = c.replacingOccurrences(of: "{{+case_associatedValues+}}", with: "(\(av))") c = c.replacingOccurrences(of: "{{+case_rawValue+}}", with: "") } else { - c = c.replacingOccurrences(of: "{{+case_rawValue+}}", with: "") //Set to empty - c = c.replacingOccurrences(of: "{{+case_associatedValues+}}", with: "") //Set to empty + c = c.replacingOccurrences(of: "{{+case_rawValue+}}", with: "") //Set to empty + c = c.replacingOccurrences(of: "{{+case_associatedValues+}}", with: "") //Set to empty } return c } -func generateComputedProperty(_ compProp:ComputedProperty, cases:[EnumCase], scope:Scope, depthIndent:Int = 1) -> String { +func generateComputedProperty( + _ compProp: ComputedProperty, + cases: [EnumCase], + scope: Scope, + depthIndent: Int = 1 +) -> String { var cp = ENUM_COMPUTED_PROPERTY cp = cp.replacingOccurrences(of: "{{+enum_scope+}}", with: scope.rawValue) cp = cp.replacingOccurrences(of: "{{+cp_title+}}", with: compProp.title) - + var rawType = "\(compProp.type.self)" - if rawType.contains("Optional<") { // TODO: Nested Optionals Not Supported... + if rawType.contains("Optional<") { // TODO: Nested Optionals Not Supported... rawType = rawType.replacingOccurrences(of: "Optional<", with: "") rawType = rawType.replacingOccurrences(of: ">", with: "?") } cp = cp.replacingOccurrences(of: "{{+cp_type+}}", with: rawType) - - var defaultNeeded:Bool = false - let entries:[String] = cases.compactMap { + + var defaultNeeded: Bool = false + let entries: [String] = cases.compactMap { if let val = $0.computedProperties[compProp.caseKey] { var entry = COMPUTED_PROPERTY_CASE - + entry = entry.replacingOccurrences(of: "{{+case_title+}}", with: $0.title) if rawType.lowercased().contains("string") { @@ -314,19 +375,25 @@ func generateComputedProperty(_ compProp:ComputedProperty, cases:[EnumCase], sco return nil } if !entries.isEmpty { - cp = cp.replacingOccurrences(of: "{{+cp_case+}}", with: "\(entries.joined(separator: "\n").replacingOccurrences(of: "\n", with: "\n\(String(repeating: "\t", count: depthIndent))"))") + cp = cp.replacingOccurrences( + of: "{{+cp_case+}}", + with: + "\(entries.joined(separator: "\n").replacingOccurrences(of: "\n", with: "\n\(String(repeating: "\t", count: depthIndent))"))" + ) } else { cp = cp.replacingOccurrences(of: "{{+cp_case+}}", with: "") } - - cp = cp.replacingOccurrences(of: "{{+cp_default+}}", with: defaultNeeded ? "default: return \(compProp.defaultValue)" : "") - + + cp = cp.replacingOccurrences( + of: "{{+cp_default+}}", + with: defaultNeeded ? "default: return \(compProp.defaultValue)" : "" + ) + cp = cp.replacingOccurrences(of: "\n", with: "\n\(String(repeating: "\t", count: depthIndent))") - + return "\n\(String(repeating: "\t", count: depthIndent))\(cp)" } - // MARK: - Script to fetch CSV, Parse, Generate ENUM and update Codecs.swift... /// Fetch CSV Data from repository @@ -336,15 +403,22 @@ guard let str = fetchContents(url: CSVDocumentURL) else { let entries = parseStringIntoCSV(str, headerRow: 0) /// Itterate over the CSV data and extract out each Enum case -let enumCases:[EnumCase] = entries.compactMap { - if let name = $0.columns.first(where: {$0.key == "name"})?.value, let rv = $0.columns.first(where: {$0.key == "code"})?.value { +let enumCases: [EnumCase] = entries.compactMap { + if let name = $0.columns.first(where: { $0.key == "name" })?.value, + let rv = $0.columns.first(where: { $0.key == "code" })?.value + { let ec = EnumCase(title: name.replacingOccurrences(of: "-", with: "_"), rawValue: rv) - $0.columns.forEach { ec.computedProperties[$0.key] = $0.value } + for col in $0.columns { + ec.computedProperties[col.key] = col.value + } return ec } return nil -}.filter({ /// Remove Deprecated Codecs (ex: ipfs) ( Looks for the word 'deprecated' in the 'description' column ) - if let desc = $0.computedProperties["description"], let d = desc as? String { return !d.lowercased().contains("deprecated") } +}.filter({ + /// Remove Deprecated Codecs (ex: ipfs) ( Looks for the word 'deprecated' in the 'description' column ) + if let desc = $0.computedProperties["description"], let d = desc as? String { + return !d.lowercased().contains("deprecated") + } return true }) @@ -355,16 +429,35 @@ guard !enumCases.isEmpty else { /// Generate the necessary computed properties to match the table let compPropTag = ComputedProperty(title: "tag", type: String.self, defaultValue: "", caseKey: "tag") -let compPropDes = ComputedProperty(title: "description", type: Optional.self, defaultValue: "nil", caseKey: "description") +let compPropDes = ComputedProperty( + title: "description", + type: Optional.self, + defaultValue: "nil", + caseKey: "description" +) /// Generate the final Enum -guard let data = generateEnum(scope: .PUBLIC, title: "Codecs", rawType: UInt64.self, protocolConformances: ["CaseIterable", "Equatable"], cases: enumCases, computedProps: [compPropTag, compPropDes]) else { +guard + let data = generateEnum( + scope: .PUBLIC, + title: "Codecs", + rawType: UInt64.self, + protocolConformances: ["CaseIterable", "Equatable"], + cases: enumCases, + computedProps: [compPropTag, compPropDes] + ) +else { print("Failed to generate Codecs enumeration. Returning without updating.") exit(EXIT_FAILURE) } /// Write Data to Codecs.swift... -guard let codecsURL = URL(string: "Sources/Multicodec/Codecs.swift", relativeTo: URL(fileURLWithPath: FileManager.default.currentDirectoryPath)) else { +guard + let codecsURL = URL( + string: "Sources/Multicodec/Codecs.swift", + relativeTo: URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + ) +else { print("Failed to locate the local Codecs.swift file for update. Returning without updating.") exit(EXIT_FAILURE) } @@ -377,5 +470,3 @@ do { print("Error Updating Codecs.swift -> \(error.localizedDescription)") exit(EXIT_FAILURE) } - - diff --git a/Tests/MulticodecTests/MulticodecTests.swift b/Tests/MulticodecTests/MulticodecTests.swift index 1e2b389..6f644c2 100644 --- a/Tests/MulticodecTests/MulticodecTests.swift +++ b/Tests/MulticodecTests/MulticodecTests.swift @@ -1,61 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the swift-libp2p open source project +// +// Copyright (c) 2022-2025 swift-libp2p project authors +// Licensed under MIT +// +// See LICENSE for license information +// See CONTRIBUTORS for the list of swift-libp2p project authors +// +// SPDX-License-Identifier: MIT +// +//===----------------------------------------------------------------------===// + +import VarInt import XCTest + @testable import Multicodec -import VarInt final class MulticodecTests: XCTestCase { - + func testCodecRawValueDirect() throws { //Access a Codecs int64 value via the 'rawValue' property - XCTAssertEqual(Codecs.eth_block.rawValue, 144) - XCTAssertEqual(Codecs.dag_pb.rawValue, 112) + XCTAssertEqual(Codecs.eth_block.rawValue, 144) + XCTAssertEqual(Codecs.dag_pb.rawValue, 112) XCTAssertEqual(Codecs.blake2b_8.rawValue, 0xb201) - + //Or the 'code' property - XCTAssertEqual(Codecs.eth_block.code, 144) - XCTAssertEqual(Codecs.dag_pb.code, 112) + XCTAssertEqual(Codecs.eth_block.code, 144) + XCTAssertEqual(Codecs.dag_pb.code, 112) XCTAssertEqual(Codecs.blake2b_8.code, 0xb201) - + //Or compare the Codecs code to an int directly - XCTAssertTrue(Codecs.eth_block == 144) - XCTAssertTrue(Codecs.dag_pb == 112) + XCTAssertTrue(Codecs.eth_block == 144) + XCTAssertTrue(Codecs.dag_pb == 112) XCTAssertTrue(Codecs.blake2b_8 == 0xb201) } - + func testCodecNamesDirect() throws { //Access a Codecs name via the name property XCTAssertEqual(Codecs.eth_block.name, "eth-block") - XCTAssertEqual(Codecs.dag_pb.name, "dag-pb") - XCTAssertEqual(Codecs.udp.name, "udp") + XCTAssertEqual(Codecs.dag_pb.name, "dag-pb") + XCTAssertEqual(Codecs.udp.name, "udp") XCTAssertEqual(Codecs.blake2b_8.name, "blake2b-8") - + //Or compare the Codecs name to a string directly... XCTAssertTrue(Codecs.eth_block == "eth-block") - XCTAssertTrue(Codecs.dag_pb == "dag-pb") - XCTAssertTrue(Codecs.udp == "udp") + XCTAssertTrue(Codecs.dag_pb == "dag-pb") + XCTAssertTrue(Codecs.udp == "udp") XCTAssertTrue(Codecs.blake2b_8 == "blake2b-8") } - + func testCodecIntInstantiation() throws { - XCTAssertEqual(try Codecs(144).name, "eth-block") - XCTAssertEqual(try Codecs(112).name, "dag-pb") - XCTAssertEqual(try Codecs(0x0111).name, "udp") + XCTAssertEqual(try Codecs(144).name, "eth-block") + XCTAssertEqual(try Codecs(112).name, "dag-pb") + XCTAssertEqual(try Codecs(0x0111).name, "udp") XCTAssertEqual(try Codecs(0xb201).name, "blake2b-8") } - + func testCodecsStringInstantiation() throws { let code = try Codecs("keccak-256") XCTAssertEqual(code.rawValue, 0x1b) } - + func testEncodeDecodeBuffer() throws { - let buf:[UInt8] = Array("hey".utf8) + let buf: [UInt8] = Array("hey".utf8) let prefixedBuf = try addPrefix(multiCodec: "protobuf", bytes: buf) XCTAssertEqual(try getCodec(bytes: prefixedBuf), "protobuf") XCTAssertEqual(buf, try removePrefix(bytes: prefixedBuf)) } - + func testEncodeDecodeBuffer1() throws { - let buf:[UInt8] = Array("hey".utf8) + let buf: [UInt8] = Array("hey".utf8) let prefixedBuf = try addPrefix(code: 0x70, bytes: buf) XCTAssertEqual(try getCodec(bytes: prefixedBuf), "dag-pb") XCTAssertEqual(buf, try removePrefix(bytes: prefixedBuf)) @@ -66,7 +81,7 @@ final class MulticodecTests: XCTestCase { XCTAssertEqual(try getCodec(bytes: prefixedBuf), "dag-cbor") XCTAssertEqual("hey", String(bytes: try removePrefix(bytes: prefixedBuf), encoding: .utf8)) } - + func testEncodeDecodeBuffer3() throws { let prefixedBuf = "hey".encodeUTF8(as: .eth_block) XCTAssertEqual(try getCodec(bytes: prefixedBuf), "eth-block") @@ -75,97 +90,96 @@ final class MulticodecTests: XCTestCase { XCTAssertTrue(decoded.codec == Codecs.eth_block) XCTAssertTrue(decoded.contents == "hey") } - + func testEncodeDecodeBufferAllCasesViaString() throws { - let buf:[UInt8] = Array("hey".utf8) + let buf: [UInt8] = Array("hey".utf8) for codec in Codecs.allCases { let prefixedBuf = try addPrefix(multiCodec: codec.name, bytes: buf) XCTAssertEqual(try getCodec(bytes: prefixedBuf), codec.name) XCTAssertEqual(buf, try removePrefix(bytes: prefixedBuf)) } } - + func testEncodeDecodeBufferAllCasesViaCodec() throws { - let buf:[UInt8] = Array("hey".utf8) + let buf: [UInt8] = Array("hey".utf8) for codec in Codecs.allCases { let prefixedBuf = addPrefix(codec: codec, bytes: buf) XCTAssertEqual(try getCodec(bytes: prefixedBuf), codec.name) XCTAssertEqual(buf, try removePrefix(bytes: prefixedBuf)) } } - + func testEncodeDecodeBufferAllCasesViaInt() throws { - let buf:[UInt8] = Array("hey".utf8) + let buf: [UInt8] = Array("hey".utf8) for codec in Codecs.allCases { let prefixedBuf = try addPrefix(code: codec.rawValue, bytes: buf) XCTAssertEqual(try getCodec(bytes: prefixedBuf), codec.name) XCTAssertEqual(buf, try removePrefix(bytes: prefixedBuf)) } } - func testVarIntRoundTrip() throws { XCTAssertEqual(uVarInt(putUVarInt(Codecs.keccak_256.rawValue)).0, 0x1b) } - + /// Int instantiation time is roughly equal between the enum and dictionary (0.00025s) ... func testEnumCodecsIntInstantiationPerformance() throws { measure { - XCTAssertTrue(try! Codecs(144) == "eth-block") - XCTAssertTrue(try! Codecs(112) == "dag-pb") + XCTAssertTrue(try! Codecs(144) == "eth-block") + XCTAssertTrue(try! Codecs(112) == "dag-pb") XCTAssertTrue(try! Codecs(0xb201) == "blake2b-8") } } -// func testDictionaryCodecsIntInstantiationPerformance() throws { -// measure { -// XCTAssertTrue(codecs.first(where: {$1 == 0x90})?.key == "eth-block") -// XCTAssertTrue(codecs.first(where: {$1 == 0x70})?.key == "dag-pb") -// XCTAssertTrue(codecs.first(where: {$1 == 0xb201})?.key == "blake2b-8") -// } -// } - + // func testDictionaryCodecsIntInstantiationPerformance() throws { + // measure { + // XCTAssertTrue(codecs.first(where: {$1 == 0x90})?.key == "eth-block") + // XCTAssertTrue(codecs.first(where: {$1 == 0x70})?.key == "dag-pb") + // XCTAssertTrue(codecs.first(where: {$1 == 0xb201})?.key == "blake2b-8") + // } + // } + /// 0.000958s ( the Enum is 20 times slower than the dictionary when instantiating from string ) func testEnumCodecsStringInstantiationPerformance() throws { measure { - XCTAssertTrue(try! Codecs("eth-block") == 144) - XCTAssertTrue(try! Codecs("dag-pb") == 112) + XCTAssertTrue(try! Codecs("eth-block") == 144) + XCTAssertTrue(try! Codecs("dag-pb") == 112) XCTAssertTrue(try! Codecs("blake2b-8") == 0xb201) } } - + /// 0.0000527 -// func testDictionaryCodecsStringInstantiationPerformance() throws { -// measure { -// XCTAssertTrue(codecs["eth-block"] == 144) -// XCTAssertTrue(codecs["dag-pb"] == 112) -// XCTAssertTrue(codecs["blake2b-8"] == 0xb201) -// } -// } - + // func testDictionaryCodecsStringInstantiationPerformance() throws { + // measure { + // XCTAssertTrue(codecs["eth-block"] == 144) + // XCTAssertTrue(codecs["dag-pb"] == 112) + // XCTAssertTrue(codecs["blake2b-8"] == 0xb201) + // } + // } + func testP2PCodecClassification() throws { //Create our buffer with an unknown codec - let hexInt = UInt64("01a5", radix: 16)! //p2p int64 code - let code:[UInt8] = putUVarInt(hexInt) //p2p code as UInt8 array - let buf:[UInt8] = Array("hey".utf8) //Test buffer string - let prefixedBuf = code + buf //A p2p buffer - + let hexInt = UInt64("01a5", radix: 16)! //p2p int64 code + let code: [UInt8] = putUVarInt(hexInt) //p2p code as UInt8 array + let buf: [UInt8] = Array("hey".utf8) //Test buffer string + let prefixedBuf = code + buf //A p2p buffer + XCTAssertEqual(try getCodec(bytes: prefixedBuf), Codecs.p2p.name) } - + func testP2P() throws { XCTAssertEqual(try Codecs(0x01a5).name, "p2p") } - + func testIPFS() throws { XCTAssertEqual(try Codecs(0xe3).name, "ipfs") } - + func testP2PIPFSEquality() throws { XCTAssertNotEqual(Codecs.ipfs, Codecs.p2p) } // MARK: - Error Handling - + /// throws error on unknown codec name when getting the code func testStringInstantiationWithUnknownCodecName() throws { XCTAssertThrowsError(try Codecs("this-codec-doesnt-exist"), "hi") { (error) in @@ -180,11 +194,11 @@ final class MulticodecTests: XCTestCase { func testGetCodecFromBufferWithUnknownCodec() throws { //Create our buffer with an unknown codec - let hexInt = UInt64("ffee", radix: 16)! //65518 - let code:[UInt8] = putUVarInt(hexInt) - let buf:[UInt8] = Array("hey".utf8) + let hexInt = UInt64("ffee", radix: 16)! //65518 + let code: [UInt8] = putUVarInt(hexInt) + let buf: [UInt8] = Array("hey".utf8) let prefixedBuf = code + buf - + //Ensure it throws the UnknownCodecId Error... XCTAssertThrowsError(try getCodec(bytes: prefixedBuf), "Unknown Codec Id") { (error) in switch error { @@ -195,9 +209,9 @@ final class MulticodecTests: XCTestCase { } } } - + func testPrefixBufferWithUnknownCodec() throws { - let buf:[UInt8] = Array("hey".utf8) + let buf: [UInt8] = Array("hey".utf8) XCTAssertThrowsError(try addPrefix(code: 0xffee, bytes: buf), "Unknown Codec Id") { (error) in switch error { case MulticodecError.UnknownCodecId: @@ -207,31 +221,4 @@ final class MulticodecTests: XCTestCase { } } } - - - static var allTests = [ - ("testCodecsStringInstantiation", testCodecsStringInstantiation), - ("testEncodeDecodeBuffer", testEncodeDecodeBuffer), - ("testEncodeDecodeBuffer1", testEncodeDecodeBuffer1), - ("testEncodeDecodeBuffer2", testEncodeDecodeBuffer2), - ("testEncodeDecodeBuffer3", testEncodeDecodeBuffer3), - ("testEncodeDecodeBufferAllCasesViaString", testEncodeDecodeBufferAllCasesViaString), - ("testEncodeDecodeBufferAllCasesViaCodec", testEncodeDecodeBufferAllCasesViaCodec), - ("testEncodeDecodeBufferAllCasesViaInt", testEncodeDecodeBufferAllCasesViaInt), - ("testVarIntRoundTrip", testVarIntRoundTrip), - ("testEnumCodecsIntInstantiationPerformance", testEnumCodecsIntInstantiationPerformance), - //("testDictionaryCodecsIntInstantiationPerformance", testDictionaryCodecsIntInstantiationPerformance), - ("testEnumCodecsStringInstantiationPerformance", testEnumCodecsStringInstantiationPerformance), - //("testDictionaryCodecsStringInstantiationPerformance", testDictionaryCodecsStringInstantiationPerformance), - ("testCodecRawValueDirect", testCodecRawValueDirect), - ("testCodecIntInstantiation", testCodecIntInstantiation), - ("testCodecNamesDirect", testCodecNamesDirect), - ("testP2PCodecClassification", testP2PCodecClassification), - ("testP2P", testP2P), - ("testIPFS", testIPFS), - ("testP2PIPFSEquality", testP2PIPFSEquality), - ("testStringInstantiationWithUnknownCodecName", testStringInstantiationWithUnknownCodecName), - ("testGetCodecFromBufferWithUnknownCodec", testGetCodecFromBufferWithUnknownCodec), - ("testPrefixBufferWithUnknownCodec", testPrefixBufferWithUnknownCodec) - ] }