diff --git a/Cargo.lock b/Cargo.lock index 206ea4ba3..f75528a60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1412,15 +1412,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "identified_vec" -version = "0.1.11" -source = "git+https://github.com/Sajjon/identified_vec/?rev=4480b418b69894ad96542bd94f80e9be63515e37#4480b418b69894ad96542bd94f80e9be63515e37" -dependencies = [ - "serde", - "thiserror 1.0.57", -] - [[package]] name = "idna" version = "0.5.0" @@ -1462,6 +1453,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.2.6" +source = "git+https://github.com/indexmap-rs/indexmap?rev=3f0fffb85b99a2a37bbee363703f8509dd03e2d7#3f0fffb85b99a2a37bbee363703f8509dd03e2d7" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + [[package]] name = "indexmap-nostd" version = "0.4.0" @@ -2544,7 +2545,7 @@ dependencies = [ "enum-iterator", "hex 0.4.3 (git+https://github.com/KokaKiwi/rust-hex/?rev=b2b4370b5bf021b98ee7adc92233e8de3f2de792)", "hkdf", - "identified_vec", + "indexmap 2.2.6", "iota-crypto", "iso8601-timestamp", "itertools 0.12.0", diff --git a/Cargo.toml b/Cargo.toml index 62e10141d..cdefbe304 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -109,17 +109,15 @@ itertools = { git = "https://github.com/rust-itertools/itertools/", rev = "98eca # enum-as-inner = "0.6.0" enum-as-inner = { git = "https://github.com/bluejekyll/enum-as-inner/", rev = "c15f6e5c4f98ec865e181ae1fff9fc13a1a2e4e2" } -# identified_vec = "0.1.11" -identified_vec = { git = "https://github.com/Sajjon/identified_vec/", rev = "4480b418b69894ad96542bd94f80e9be63515e37", features = [ - "serde", - "id_prim", -] } - # uniffi = "0.27.0" uniffi = { git = "https://github.com/mozilla/uniffi-rs/", rev = "d52c5460ae42ecad1e73a5b394ac96d48f4769de", features = [ "cli", ] } +indexmap = { git = "https://github.com/indexmap-rs/indexmap", rev = "3f0fffb85b99a2a37bbee363703f8509dd03e2d7", features = [ + "serde", +] } + # SLIP10 implementation # iota_crypto = "0.23.1" iota-crypto = { git = "https://github.com/iotaledger/crypto.rs", rev = "47460d64fd0514af136ea1c2c6f3aa29ed89d1b8", features = [ diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Accounts+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Accounts+Wrap+Functions.swift deleted file mode 100644 index 1e825943a..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Accounts+Wrap+Functions.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension Accounts { - public init(_ elements: [Account]) { - self = newAccounts(accounts: elements) - } - - public init(element: Account) { - self = newAccountsWithAccount(account: element) - } - - public var elements: [Account] { - accountsGetElements(accounts: self) - } - - public func appending(_ account: Account) -> Self { - newAccountsByAppending(account: account, to: self) - } - - public func updatingOrInserting(element account: Element, at index: Int) -> Self { - newAccountsByUpdatingOrInsertingAtIndex(account: account, to: self, index: UInt64(index)) - } - - public func removing(_ id: Account.ID) -> Self { - newAccountsRemovedById(idOfAccount: id, from: self) - } - - public func updatingOrAppending(_ account: Account) -> Self { - newAccountsByUpdatingOrAppending(account: account, to: self) - } - - public func removing(element account: Account) -> Self { - newAccountsRemovedElement(account: account, from: self) - } - - public func get(id: Account.ID) -> Account? { - accountsGetAccountById(accounts: self, id: id) - } - - public var count: Int { - Int(accountsElementCount(accounts: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AccountsForDisplay+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AccountsForDisplay+Wrap+Functions.swift deleted file mode 100644 index 180b1f146..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AccountsForDisplay+Wrap+Functions.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension AccountsForDisplay { - public init(_ elements: [Element]) { - self = newAccountsForDisplay(accountsForDisplay: elements) - } - - public init(element: Element) { - self = newAccountsForDisplayWithAccountForDisplay(accountForDisplay: element) - } - - public var elements: [Element] { - accountsForDisplayGetElements(accountsForDisplay: self) - } - - public func appending(_ element: Element) -> Self { - newAccountsForDisplayByAppending(accountForDisplay: element, to: self) - } - - public func updatingOrInserting(element: Element, at index: Int) -> Self { - newAccountsForDisplayByUpdatingOrInsertingAtIndex(accountForDisplay: element, to: self, index: UInt64(index)) - } - - public func removing(_ id: Element.ID) -> Self { - newAccountsForDisplayRemovedById(idOfAccountForDisplay: id, from: self) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newAccountsForDisplayByUpdatingOrAppending(accountForDisplay: element, to: self) - } - - public func removing(element: Element) -> Self { - newAccountsForDisplayRemovedElement(accountForDisplay: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - accountsForDisplayGetAccountForDisplayById(accountsForDisplay: self, id: id) - } - - public var count: Int { - Int(accountsForDisplayElementCount(accountsForDisplay: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AccountsOrPersonas+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AccountsOrPersonas+Wrap+Functions.swift deleted file mode 100644 index 2c2d60f43..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AccountsOrPersonas+Wrap+Functions.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension AccountsOrPersonas { - public init(_ elements: [Element]) { - self = newAccountsOrPersonas(accountsOrPersonas: elements) - } - - public init(element: Element) { - self = newAccountsOrPersonasWithAccountOrPersona(accountOrPersona: element) - } - - public var elements: [Element] { - accountsOrPersonasGetElements(accountsOrPersonas: self) - } - - public func appending(_ element: Element) -> Self { - newAccountsOrPersonasByAppending(accountOrPersona: element, to: self) - } - - public func updatingOrInserting(element: Element, at index: Int) -> Self { - newAccountsOrPersonasByUpdatingOrInsertingAtIndex(accountOrPersona: element, to: self, index: UInt64(index)) - } - - public func removing(_ id: Element.ID) -> Self { - newAccountsOrPersonasRemovedById(idOfAccountOrPersona: id, from: self) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newAccountsOrPersonasByUpdatingOrAppending(accountOrPersona: element, to: self) - } - - public func removing(element: Element) -> Self { - newAccountsOrPersonasRemovedElement(accountOrPersona: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - accountsOrPersonasGetAccountOrPersonaById(accountsOrPersonas: self, id: id) - } - - public var count: Int { - Int(accountsOrPersonasElementCount(accountsOrPersonas: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AssetsExceptionList+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AssetsExceptionList+Wrap+Functions.swift deleted file mode 100644 index b2b1853cf..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AssetsExceptionList+Wrap+Functions.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-22. -// - -import Foundation -import SargonUniFFI - -extension AssetsExceptionList { - public init(_ elements: [Element]) { - self = newAssetsExceptionList(assetsExceptionList: elements) - } - - public init(element: Element) { - self = newAssetsExceptionListWithAssetException(assetException: element) - } - - public var elements: [Element] { - assetsExceptionListGetElements(assetsExceptionList: self) - } - - public func appending(_ element: Element) -> Self { - newAssetsExceptionListByAppending(assetException: element, to: self) - } - - public func updatingOrInserting(element: Element, at index: Int) -> Self { - newAssetsExceptionListByUpdatingOrInsertingAtIndex( - assetException: element, - to: self, - index: UInt64( - index - ) - ) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newAssetsExceptionListByUpdatingOrAppending(assetException: element, to: self) - } - - public func removing(_ id: Element.ID) -> Self { - newAssetsExceptionListRemovedById(idOfAssetException: id, from: self) - } - - public func removing(element: Element) -> Self { - newAssetsExceptionListRemovedElement(assetException: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - assetsExceptionListGetAssetExceptionById(assetsExceptionList: self, id: id) - } - - public var count: Int { - Int(assetsExceptionListElementCount(assetsExceptionList: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AuthorizedDapps+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AuthorizedDapps+Wrap+Functions.swift deleted file mode 100644 index 614b7e657..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/AuthorizedDapps+Wrap+Functions.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension AuthorizedDapps { - public init(_ elements: [AuthorizedDapp]) { - self = newAuthorizedDapps(authorizedDapps: elements) - } - - public init(element: AuthorizedDapp) { - self = newAuthorizedDappsWithAuthorizedDapp(authorizedDapp: element) - } - - public var elements: [AuthorizedDapp] { - authorizedDappsGetElements(authorizedDapps: self) - } - - public func appending(_ authorizedDapp: AuthorizedDapp) -> Self { - newAuthorizedDappsByAppending(authorizedDapp: authorizedDapp, to: self) - } - - public func updatingOrInserting(element authorizedDapp: Element, at index: Int) -> Self { - newAuthorizedDappsByUpdatingOrInsertingAtIndex(authorizedDapp: authorizedDapp, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ authorizedDapp: AuthorizedDapp) -> Self { - newAuthorizedDappsByUpdatingOrAppending(authorizedDapp: authorizedDapp, to: self) - } - - public func removing(_ id: AuthorizedDapp.ID) -> Self { - newAuthorizedDappsRemovedById(idOfAuthorizedDapp: id, from: self) - } - - public func removing(element dapp: AuthorizedDapp) -> Self { - newAuthorizedDappsRemovedElement(authorizedDapp: dapp, from: self) - } - - public func get(id: AuthorizedDapp.ID) -> AuthorizedDapp? { - authorizedDappsGetAuthorizedDappById(authorizedDapps: self, id: id) - } - - public var count: Int { - Int(authorizedDappsElementCount(authorizedDapps: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/DepositorsAllowList+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/DepositorsAllowList+Wrap+Functions.swift deleted file mode 100644 index 67aa0341d..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/DepositorsAllowList+Wrap+Functions.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-22. -// - -import Foundation -import SargonUniFFI - - -extension DepositorsAllowList { - - public init(_ elements: [Element]) { - self = newDepositorsAllowList(depositorsAllowList: elements) - } - - public init(element: Element) { - self = newDepositorsAllowListWithResourceOrNonFungible(resourceOrNonFungible: element) - } - - public var elements: [Element] { - depositorsAllowListGetElements(depositorsAllowList: self) - } - - public func appending(_ element: Element) -> Self { - newDepositorsAllowListByAppending(resourceOrNonFungible: element, to: self) - } - - public func updatingOrInserting(element: Element, at index: Int) -> Self { - newDepositorsAllowListByUpdatingOrInsertingAtIndex( - resourceOrNonFungible: element, - to: self, - index: UInt64( - index - ) - ) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newDepositorsAllowListByUpdatingOrAppending(resourceOrNonFungible: element, to: self) - } - - public func removing(_ id: Element.ID) -> Self { - newDepositorsAllowListRemovedById(idOfResourceOrNonFungible: id, from: self) - } - - public func removing(element: Element) -> Self { - newDepositorsAllowListRemovedElement(resourceOrNonFungible: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - depositorsAllowListGetResourceOrNonFungibleById(depositorsAllowList: self, id: id) - } - - public var count: Int { - Int(depositorsAllowListElementCount(depositorsAllowList: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/DetailedAuthorizedPersonas+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/DetailedAuthorizedPersonas+Wrap+Functions.swift deleted file mode 100644 index 856a46601..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/DetailedAuthorizedPersonas+Wrap+Functions.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation -import SargonUniFFI - -extension DetailedAuthorizedPersonas { - public init(_ elements: [Element]) { - self = newDetailedAuthorizedPersonas(detailedAuthorizedPersonas: elements) - } - - public init(element: Element) { - self = newDetailedAuthorizedPersonasWithAuthorizedPersonaDetailed(authorizedPersonaDetailed: element) - } - - public var elements: [Element] { - detailedAuthorizedPersonasGetElements(detailedAuthorizedPersonas: self) - } - - public func appending(_ element: Element) -> Self { - newDetailedAuthorizedPersonasByAppending(authorizedPersonaDetailed: element, to: self) - } - - public func updatingOrInserting(element: Element, at index: Int) -> Self { - newDetailedAuthorizedPersonasByUpdatingOrInsertingAtIndex(authorizedPersonaDetailed: element, to: self, index: UInt64(index)) - } - - public func removing(_ id: Element.ID) -> Self { - newDetailedAuthorizedPersonasRemovedById(idOfAuthorizedPersonaDetailed: id, from: self) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newDetailedAuthorizedPersonasByUpdatingOrAppending(authorizedPersonaDetailed: element, to: self) - } - - public func removing(element: Element) -> Self { - newDetailedAuthorizedPersonasRemovedElement(authorizedPersonaDetailed: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - detailedAuthorizedPersonasGetAuthorizedPersonaDetailedById(detailedAuthorizedPersonas: self, id: id) - } - - public var count: Int { - Int(detailedAuthorizedPersonasElementCount(detailedAuthorizedPersonas: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/EntityFlags+Wrap+Function.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/EntityFlags+Wrap+Function.swift deleted file mode 100644 index 906524084..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/EntityFlags+Wrap+Function.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension EntityFlags { - public init(_ elements: [EntityFlag]) { - self = newEntityFlags(entityFlags: elements) - } - - public init(element: EntityFlag) { - self = newEntityFlagsWithEntityFlag(entityFlag: element) - } - - public var elements: [EntityFlag] { - entityFlagsGetElements(entityFlags: self) - } - - public func appending(_ entityFlag: EntityFlag) -> Self { - newEntityFlagsByAppending(entityFlag: entityFlag, to: self) - } - - public func updatingOrInserting(element entityFlag: Element, at index: Int) -> Self { - newEntityFlagsByUpdatingOrInsertingAtIndex(entityFlag: entityFlag, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ entityFlag: EntityFlag) -> Self { - newEntityFlagsByUpdatingOrAppending(entityFlag: entityFlag, to: self) - } - - public func removing(_ id: EntityFlag) -> Self { - newEntityFlagsRemovedById(idOfEntityFlag: id, from: self) - } - - public func removing(element flag: EntityFlag) -> Self { - newEntityFlagsRemovedElement(entityFlag: flag, from: self) - } - - public func get(id: EntityFlag.ID) -> EntityFlag? { - entityFlagsGetEntityFlagById(entityFlags: self, id: id) - } - - public var count: Int { - Int(entityFlagsElementCount(entityFlags: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/FactorSources+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/FactorSources+Wrap+Functions.swift deleted file mode 100644 index 409f50afd..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/FactorSources+Wrap+Functions.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension FactorSources { - public init(_ elements: [FactorSource]) throws { - self = try newFactorSources(factorSources: elements) - } - - public init(element: FactorSource) { - self = newFactorSourcesWithFactorSource(factorSource: element) - } - - public var elements: [FactorSource] { - factorSourcesGetElements(factorSources: self) - } - - public func appending(_ factorSource: FactorSource) -> Self { - newFactorSourcesByAppending(factorSource: factorSource, to: self) - } - - public func updatingOrInserting(element factorSource: Element, at index: Int) -> Self { - newFactorSourcesByUpdatingOrInsertingAtIndex(factorSource: factorSource, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ factorSource: FactorSource) -> Self { - newFactorSourcesByUpdatingOrAppending(factorSource: factorSource, to: self) - } - - /// FactorSources is NonEmpty, so this throws if the resulting collection would be empty when removing - /// the element by ID would result in an empty copy. - public func removing(_ id: FactorSource.ID) throws -> Self { - try newFactorSourcesRemovedById(idOfFactorSource: id, from: self) - } - - /// FactorSources is NonEmpty, so this throws if the resulting collection would be empty when removing - /// the element would result in an empty copy. - public func removing(element factorSource: FactorSource) throws -> Self { - try newFactorSourcesRemovedElement(factorSource: factorSource, from: self) - } - - - public func get(id: FactorSource.ID) -> FactorSource? { - factorSourcesGetFactorSourceById(factorSources: self, id: id) - } - - public var count: Int { - Int(factorSourcesElementCount(factorSources: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Gateways+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Gateways+Wrap+Functions.swift deleted file mode 100644 index af89cebc2..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Gateways+Wrap+Functions.swift +++ /dev/null @@ -1,45 +0,0 @@ -import Foundation -import SargonUniFFI - -extension Gateways { - - public init(_ elements: [Element]) { - self = newGateways(gateways: elements) - } - - public init(element: Element) { - self = newGatewaysWithGateway(gateway: element) - } - - public var elements: [Element] { - gatewaysGetElements(gateways: self) - } - - public func appending(_ element: Element) -> Self { - newGatewaysByAppending(gateway: element, to: self) - } - - public func updatingOrInserting(element gateway: Element, at index: Int) -> Self { - newGatewaysByUpdatingOrInsertingAtIndex(gateway: gateway, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newGatewaysByUpdatingOrAppending(gateway: element, to: self) - } - - public func removing(_ id: Element.ID) -> Self { - newGatewaysRemovedById(idOfGateway: id, from: self) - } - - public func removing(element: Element) -> Self { - newGatewaysRemovedElement(gateway: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - gatewaysGetGatewayById(gateways: self, id: id) - } - - public var count: Int { - Int(gatewaysElementCount(gateways: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/P2PLinks+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/P2PLinks+Wrap+Functions.swift deleted file mode 100644 index 3029c5cb0..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/P2PLinks+Wrap+Functions.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension P2pLinks { - public init(_ elements: [P2pLink]) { - self = newP2PLinks(p2PLinks: elements) - } - - public init(element: P2pLink) { - self = newP2PLinksWithP2PLink(p2PLink: element) - } - - public var elements: [P2pLink] { - p2PLinksGetElements(p2PLinks: self) - } - - public func appending(_ link: P2pLink) -> Self { - newP2PLinksByAppending(p2PLink: link, to: self) - } - - public func updatingOrInserting(element p2PLink: Element, at index: Int) -> Self { - newP2PLinksByUpdatingOrInsertingAtIndex(p2PLink: p2PLink, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ link: P2pLink) -> Self { - newP2PLinksByUpdatingOrAppending(p2PLink: link, to: self) - } - - public func removing(_ id: P2PLink.ID) -> Self { - newP2PLinksRemovedById(idOfP2PLink: id, from: self) - } - - public func removing(element link: P2pLink) -> Self { - newP2PLinksRemovedElement(p2PLink: link, from: self) - } - - public func get(id: P2pLink.ID) -> P2pLink? { - p2PLinksGetP2PLinkById(p2PLinks: self, id: id) - } - - public var count: Int { - Int(p2PLinksElementCount(p2PLinks: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Personas+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Personas+Wrap+Functions.swift deleted file mode 100644 index 718be1b0e..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/Personas+Wrap+Functions.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension Personas { - public init(_ elements: [Persona]) { - self = newPersonas(personas: elements) - } - - public init(element: Persona) { - self = newPersonasWithPersona(persona: element) - } - - public var elements: [Persona] { - personasGetElements(personas: self) - } - - public func appending(_ persona: Persona) -> Self { - newPersonasByAppending(persona: persona, to: self) - } - - public func updatingOrInserting(element persona: Element, at index: Int) -> Self { - newPersonasByUpdatingOrInsertingAtIndex(persona: persona, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ persona: Persona) -> Self { - newPersonasByUpdatingOrAppending(persona: persona, to: self) - } - - public func removing(_ id: Persona.ID) -> Self { - newPersonasRemovedById(idOfPersona: id, from: self) - } - - public func removing(element persona: Persona) -> Self { - newPersonasRemovedElement(persona: persona, from: self) - } - - public func get(id: Persona.ID) -> Persona? { - personasGetPersonaById(personas: self, id: id) - } - - public var count: Int { - Int(personasElementCount(personas: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/ProfileNetworks+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/ProfileNetworks+Wrap+Functions.swift deleted file mode 100644 index 89ce1b5de..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/ProfileNetworks+Wrap+Functions.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension ProfileNetworks { - - public init(_ elements: [ProfileNetwork]) { - self = newProfileNetworks(profileNetworks: elements) - } - - public init(element: ProfileNetwork) { - self = newProfileNetworksWithProfileNetwork(profileNetwork: element) - } - - public var elements: [ProfileNetwork] { - profileNetworksGetElements(profileNetworks: self) - } - - public func appending(_ network: ProfileNetwork) -> Self { - newProfileNetworksByAppending(profileNetwork: network, to: self) - } - - public func updatingOrInserting(element profileNetwork: Element, at index: Int) -> Self { - newProfileNetworksByUpdatingOrInsertingAtIndex(profileNetwork: profileNetwork, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ network: ProfileNetwork) -> Self { - newProfileNetworksByUpdatingOrAppending(profileNetwork: network, to: self) - } - - public func removing(_ id: ProfileNetwork.ID) -> Self { - newProfileNetworksRemovedById(idOfProfileNetwork: id, from: self) - } - - public func removing(element network: ProfileNetwork) -> Self { - newProfileNetworksRemovedElement(profileNetwork: network, from: self) - } - - public func get(id: ProfileNetwork.ID) -> ProfileNetwork? { - profileNetworksGetProfileNetworkById(profileNetworks: self, id: id) - } - - public var count: Int { - Int(profileNetworksElementCount(profileNetworks: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/ReferencesToAuthorizedPersonas+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/ReferencesToAuthorizedPersonas+Wrap+Functions.swift deleted file mode 100644 index bbbc79556..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/ReferencesToAuthorizedPersonas+Wrap+Functions.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension ReferencesToAuthorizedPersonas { - public init(_ elements: [Element]) { - self = newReferencesToAuthorizedPersonas(referencesToAuthorizedPersonas: elements) - } - - public init(element: Element) { - self = newReferencesToAuthorizedPersonasWithAuthorizedPersonaSimple(authorizedPersonaSimple: element) - } - - public var elements: [Element] { - referencesToAuthorizedPersonasGetElements(referencesToAuthorizedPersonas: self) - } - - public func appending(_ element: Element) -> Self { - newReferencesToAuthorizedPersonasByAppending(authorizedPersonaSimple: element, to: self) - } - - public func updatingOrInserting(element: Element, at index: Int) -> Self { - newReferencesToAuthorizedPersonasByUpdatingOrInsertingAtIndex(authorizedPersonaSimple: element, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newReferencesToAuthorizedPersonasByUpdatingOrAppending(authorizedPersonaSimple: element, to: self) - } - - public func removing(_ id: Element.ID) -> Self { - newReferencesToAuthorizedPersonasRemovedById(idOfAuthorizedPersonaSimple: id, from: self) - } - - public func removing(element: Element) -> Self { - newReferencesToAuthorizedPersonasRemovedElement(authorizedPersonaSimple: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - referencesToAuthorizedPersonasGetAuthorizedPersonaSimpleById(referencesToAuthorizedPersonas: self, id: id) - } - - public var count: Int { - Int(referencesToAuthorizedPersonasElementCount(referencesToAuthorizedPersonas: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/SupportedCurves+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/SupportedCurves+Wrap+Functions.swift deleted file mode 100644 index 4d2a41883..000000000 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Collection/SupportedCurves+Wrap+Functions.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension SupportedCurves { - - public init(_ elements: [Element]) throws { - self = try newSupportedCurves(supportedCurves: elements) - } - - public init(element: Element) { - self = newSupportedCurvesWithSLIP10Curve(sLIP10Curve: element) - } - - public var elements: [Element] { - supportedCurvesGetElements(supportedCurves: self) - } - - public func appending(_ element: Element) -> Self { - newSupportedCurvesByAppending(sLIP10Curve: element, to: self) - } - - public func updatingOrInserting(element sLIP10Curve: Element, at index: Int) -> Self { - newSupportedCurvesByUpdatingOrInsertingAtIndex(sLIP10Curve: sLIP10Curve, to: self, index: UInt64(index)) - } - - public func updatingOrAppending(_ element: Element) -> Self { - newSupportedCurvesByUpdatingOrAppending(sLIP10Curve: element, to: self) - } - - public func removing(_ id: Element.ID) throws -> Self { - try newSupportedCurvesRemovedById(idOfSLIP10Curve: id, from: self) - } - - public func removing(element: Element) throws -> Self { - try newSupportedCurvesRemovedElement(sLIP10Curve: element, from: self) - } - - public func get(id: Element.ID) -> Element? { - supportedCurvesGetSLIP10CurveById(supportedCurves: self, id: id) - } - - public var count: Int { - Int(supportedCurvesElementCount(supportedCurves: self)) - } -} diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Gateway+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Gateway+Wrap+Functions.swift index 8aede2657..ba8ef6d3a 100644 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Gateway+Wrap+Functions.swift +++ b/apple/Sources/Sargon/Extensions/Methods/Profile/Gateway+Wrap+Functions.swift @@ -14,7 +14,7 @@ extension Gateway { gatewayIsWellknown(gateway: self) } - public static let wellknown: Gateways = gatewayWellknownGateways() + public static let wellknown: [Gateway] = gatewayWellknownGateways() public init(url: String, networkID: NetworkID) throws { self = try newGatewayWithUrlOnNetwork(url: url, networkId: networkID) diff --git a/apple/Sources/Sargon/Extensions/Methods/Profile/Profile+Wrap+Functions.swift b/apple/Sources/Sargon/Extensions/Methods/Profile/Profile+Wrap+Functions.swift index e98b0e17e..306c763fc 100644 --- a/apple/Sources/Sargon/Extensions/Methods/Profile/Profile+Wrap+Functions.swift +++ b/apple/Sources/Sargon/Extensions/Methods/Profile/Profile+Wrap+Functions.swift @@ -18,6 +18,15 @@ extension Profile { ) } + public func toString() -> String { + profileToString(profile: self) + } + + + public func toDebugString() -> String { + profileToDebugString(profile: self) + } + public func profileSnapshot() -> Data { profileToJsonBytes(profile: self) } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Accounts+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Accounts+SampleValues.swift index 63de0f215..2ac56bab1 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Accounts+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Accounts+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension Accounts { +extension [Account] { public static let sample: Self = newAccountsSample() public static let sampleOther: Self = newAccountsSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsForDisplay+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsForDisplay+SampleValues.swift index 50866d7af..0be872a6c 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsForDisplay+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsForDisplay+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension AccountsForDisplay { +extension [AccountForDisplay] { public static let sample: Self = newAccountsForDisplaySample() public static let sampleOther: Self = newAccountsForDisplaySampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsOrPersonas+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsOrPersonas+SampleValues.swift index 664baab5d..06226a6aa 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsOrPersonas+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AccountsOrPersonas+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension AccountsOrPersonas { +extension [AccountOrPersona] { public static let sample: Self = newAccountsOrPersonasSample() public static let sampleOther: Self = newAccountsOrPersonasSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AssetsExceptionList+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AssetsExceptionList+SampleValues.swift index 84cbfa2e7..a8dd47746 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AssetsExceptionList+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AssetsExceptionList+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension AssetsExceptionList { +extension [AssetException] { public static let sample: Self = newAssetsExceptionListSample() public static let sampleOther: Self = newAssetsExceptionListSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AuthorizedDapps+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AuthorizedDapps+SampleValues.swift index a7615fe0f..1c38b0c26 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AuthorizedDapps+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/AuthorizedDapps+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension AuthorizedDapps { +extension [AuthorizedDapp] { public static let sample: Self = newAuthorizedDappsSample() public static let sampleOther: Self = newAuthorizedDappsSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DepositorsAllowList+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DepositorsAllowList+SampleValues.swift index aa076b676..327be51f4 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DepositorsAllowList+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DepositorsAllowList+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension DepositorsAllowList { +extension [ResourceOrNonFungible] { public static let sample: Self = newDepositorsAllowListSample() public static let sampleOther: Self = newDepositorsAllowListSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DetailedAuthorizedPersonas+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DetailedAuthorizedPersonas+SampleValues.swift index b09974ab3..acf954629 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DetailedAuthorizedPersonas+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/DetailedAuthorizedPersonas+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension DetailedAuthorizedPersonas { +extension [AuthorizedPersonaDetailed] { public static let sample: Self = newDetailedAuthorizedPersonasSample() public static let sampleOther: Self = newDetailedAuthorizedPersonasSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/EntityFlags+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/EntityFlags+SampleValues.swift index 6e2df600e..33e1cdb0f 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/EntityFlags+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/EntityFlags+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension EntityFlags { +extension [EntityFlag] { public static let sample: Self = newEntityFlagsSample() public static let sampleOther: Self = newEntityFlagsSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/FactorSources+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/FactorSources+SampleValues.swift index 92d5c96f0..b8e75de9a 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/FactorSources+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/FactorSources+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension FactorSources { +extension [FactorSource] { public static let sample: Self = newFactorSourcesSample() public static let sampleOther: Self = newFactorSourcesSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Gateways+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Gateways+SampleValues.swift index db52c6d65..01adb9096 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Gateways+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Gateways+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension Gateways { +extension [Gateway] { public static let sample: Self = newGatewaysSample() public static let sampleOther: Self = newGatewaysSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/P2PLinks+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/P2PLinks+SampleValues.swift index e362a76c8..ab8134be5 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/P2PLinks+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/P2PLinks+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension P2PLinks { +extension [P2PLink] { public static let sample: Self = newP2PLinksSample() public static let sampleOther: Self = newP2PLinksSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Personas+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Personas+SampleValues.swift index d811e59af..0a96f5d69 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Personas+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/Personas+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension Personas { +extension [Persona] { public static let sample: Self = newPersonasSample() public static let sampleOther: Self = newPersonasSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ProfileNetworks+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ProfileNetworks+SampleValues.swift index 8bd808b1b..cf7bb0505 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ProfileNetworks+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ProfileNetworks+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension ProfileNetworks { +extension [ProfileNetwork] { public static let sample: Self = newProfileNetworksSample() public static let sampleOther: Self = newProfileNetworksSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ReferencesToAuthorizedPersonas+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ReferencesToAuthorizedPersonas+SampleValues.swift index 9c9fb31ea..c0d3bd2cd 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ReferencesToAuthorizedPersonas+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/ReferencesToAuthorizedPersonas+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension ReferencesToAuthorizedPersonas { +extension [AuthorizedPersonaSimple] { public static let sample: Self = newReferencesToAuthorizedPersonasSample() public static let sampleOther: Self = newReferencesToAuthorizedPersonasSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/SupportedCurves+SampleValues.swift b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/SupportedCurves+SampleValues.swift index b507d3ffe..c6e30d507 100644 --- a/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/SupportedCurves+SampleValues.swift +++ b/apple/Sources/Sargon/Extensions/SampleValues/Profile/Collection/SupportedCurves+SampleValues.swift @@ -9,7 +9,7 @@ import Foundation import SargonUniFFI #if DEBUG -extension SupportedCurves { +extension [Slip10Curve] { public static let sample: Self = newSupportedCurvesSample() public static let sampleOther: Self = newSupportedCurvesSampleOther() } diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile+Supporting+Types/AccountOrPersona+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile+Supporting+Types/AccountOrPersona+Swiftified.swift index 221b4f202..cc3efcbe4 100644 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile+Supporting+Types/AccountOrPersona+Swiftified.swift +++ b/apple/Sources/Sargon/Extensions/Swiftified/Profile+Supporting+Types/AccountOrPersona+Swiftified.swift @@ -45,7 +45,7 @@ extension AccountOrPersona: EntityBaseProtocol { } /// Flags that are currently set on entity. - public var flags: EntityFlags { + public var flags: [EntityFlag] { property(\.flags) } diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/AuthorizedDapp/AuthorizedDapps+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/AuthorizedDapp/AuthorizedDapps+Swiftified.swift deleted file mode 100644 index 81c730d6b..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/AuthorizedDapp/AuthorizedDapps+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension AuthorizedDapps: CanBeEmptyIdentifiedCollection { - public typealias Element = AuthorizedDapp -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Accounts+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Accounts+Swiftified.swift deleted file mode 100644 index 0a77ea24b..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Accounts+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension Accounts: CanBeEmptyIdentifiedCollection { - public typealias Element = Account -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AccountsForDisplay+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AccountsForDisplay+Swiftified.swift deleted file mode 100644 index f31b304f6..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AccountsForDisplay+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension AccountsForDisplay: CanBeEmptyIdentifiedCollection { - public typealias Element = AccountForDisplay -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AccountsOrPersonas+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AccountsOrPersonas+Swiftified.swift deleted file mode 100644 index f10029a1b..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AccountsOrPersonas+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension AccountsOrPersonas: CanBeEmptyIdentifiedCollection { - public typealias Element = AccountOrPersona -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AssetsExceptionList+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AssetsExceptionList+Swiftified.swift deleted file mode 100644 index 88eabfb74..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/AssetsExceptionList+Swiftified.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-22. -// - -import Foundation -import SargonUniFFI - -extension AssetsExceptionList: SargonModel {} -extension AssetsExceptionList: CanBeEmptyIdentifiedCollection { - public typealias Element = AssetException -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/DepositorsAllowList+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/DepositorsAllowList+Swiftified.swift deleted file mode 100644 index 3b808bc70..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/DepositorsAllowList+Swiftified.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-22. -// - -import Foundation -import SargonUniFFI - -extension DepositorsAllowList: SargonModel {} -extension DepositorsAllowList: CanBeEmptyIdentifiedCollection { - public typealias Element = ResourceOrNonFungible -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/DetailedAuthorizedPersonas+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/DetailedAuthorizedPersonas+Swiftified.swift deleted file mode 100644 index 5834e93a3..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/DetailedAuthorizedPersonas+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension DetailedAuthorizedPersonas: CanBeEmptyIdentifiedCollection { - public typealias Element = AuthorizedPersonaDetailed -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/EntityFlags+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/EntityFlags+Swiftified.swift deleted file mode 100644 index 7864b2edf..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/EntityFlags+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension EntityFlags: CanBeEmptyIdentifiedCollection { - public typealias Element = EntityFlag -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/FactorSources+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/FactorSources+Swiftified.swift deleted file mode 100644 index b0ce24cc9..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/FactorSources+Swiftified.swift +++ /dev/null @@ -1,5 +0,0 @@ -import SargonUniFFI - -extension FactorSources: NeverEmptyIdentifiedCollection { - public typealias Element = FactorSource -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Gateways+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Gateways+Swiftified.swift deleted file mode 100644 index f056f8cb1..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Gateways+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension Gateways: CanBeEmptyIdentifiedCollection { - public typealias Element = Gateway -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/P2PLinks+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/P2PLinks+Swiftified.swift deleted file mode 100644 index 64995f9e3..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/P2PLinks+Swiftified.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -public typealias P2PLinks = P2pLinks - -extension P2PLinks: CanBeEmptyIdentifiedCollection { - public typealias Element = P2PLink -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Personas+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Personas+Swiftified.swift deleted file mode 100644 index a25f5c2df..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/Personas+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension Personas: CanBeEmptyIdentifiedCollection { - public typealias Element = Persona -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/ProfileNetworks+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/ProfileNetworks+Swiftified.swift deleted file mode 100644 index 41cc21bb9..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/ProfileNetworks+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension ProfileNetworks: CanBeEmptyIdentifiedCollection { - public typealias Element = ProfileNetwork -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/ReferencesToAuthorizedPersonas+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/ReferencesToAuthorizedPersonas+Swiftified.swift deleted file mode 100644 index a8b558647..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/ReferencesToAuthorizedPersonas+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension ReferencesToAuthorizedPersonas: CanBeEmptyIdentifiedCollection { - public typealias Element = AuthorizedPersonaSimple -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/SupportedCurves+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/SupportedCurves+Swiftified.swift deleted file mode 100644 index 15e58aa32..000000000 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Collection/SupportedCurves+Swiftified.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation -import SargonUniFFI - -extension SupportedCurves: NeverEmptyIdentifiedCollection { - public typealias Element = SLIP10Curve -} diff --git a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Profile+Swiftified.swift b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Profile+Swiftified.swift index a226262e3..fb984a6c7 100644 --- a/apple/Sources/Sargon/Extensions/Swiftified/Profile/Profile+Swiftified.swift +++ b/apple/Sources/Sargon/Extensions/Swiftified/Profile/Profile+Swiftified.swift @@ -22,7 +22,7 @@ extension Profile { ) { self.init( header: header, - factorSources: FactorSources(element: deviceFactorSource.asGeneral), + factorSources: [deviceFactorSource.asGeneral], appPreferences: .default, networks: [] ) @@ -38,14 +38,14 @@ extension Profile: Identifiable { extension Profile: CustomStringConvertible { public var description: String { - profileToString(profile: self) + toString() } } extension Profile: CustomDebugStringConvertible { public var debugDescription: String { - profileToDebugString(profile: self) + toDebugString() } } diff --git a/apple/Sources/Sargon/Protocols/Collection/BaseIdentifiedCollection.swift b/apple/Sources/Sargon/Protocols/Collection/BaseIdentifiedCollection.swift deleted file mode 100644 index 592ca00b1..000000000 --- a/apple/Sources/Sargon/Protocols/Collection/BaseIdentifiedCollection.swift +++ /dev/null @@ -1,105 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation - -public protocol BaseIdentifiedCollection: - SargonModel, - RandomAccessCollection, - MutableCollection -where - Index == Array.Index, - Element: Identifiable, - Element: SargonModel -{ - var elements: [Element] { get } - init(element: Element) - func appending(_ element: Element) -> Self - func get(id: Element.ID) -> Element? - func updatingOrAppending(_ element: Element) -> Self - func updatingOrInserting(element: Element, at index: Int) -> Self -} - -extension BaseIdentifiedCollection { - public func contains(id: Element.ID) -> Bool { - get(id: id) != nil - } - - public var ids: [Element.ID] { - map(\.id) - } - -} - - -// MARK: MutableCollection -extension BaseIdentifiedCollection { - - public mutating func append(_ newElement: Self.Element) { - self = appending(newElement) - } - - @inlinable - @inline(__always) - public subscript(position: Int) -> Element { - get { - elements[position] - } - set { - updateOrInsert(element: newValue, at: position) - } - } -} - -extension BaseIdentifiedCollection { - public var startIndex: Index { - elements.startIndex - } - - public var endIndex: Index { - elements.endIndex - } - - public func index(after index: Index) -> Index { - elements.index(after: index) - } - - @discardableResult - public mutating func updateOrInsert(element: Element, at index: Int) -> (originalMember: Element?, index: Int) { - let originalMember = get(id: element.id) - self = updatingOrInserting(element: element, at: index) - let deFactoIndex = self.firstIndex(where: { $0.id == element.id })! - return (originalMember, index: deFactoIndex) - } - - /// Adds the given element to the array unconditionally, either appending it to the array, or - /// replacing an existing value if it's already present. - /// - /// - Parameter item: The value to append or replace. - /// - Returns: The original element that was replaced by this operation, or `nil` if the value was - /// appended to the end of the collection. - /// - Complexity: The operation is expected to perform amortized O(1) copy, hash, and compare - /// operations on the `ID` type, if it implements high-quality hashing. - @inlinable - @discardableResult - public mutating func updateOrAppend(_ item: Element) -> Element? { - let originalElement = get(id: item.id) - - let countBefore = count - self = updatingOrAppending(item) - let countAfter = count - - - if countAfter != countBefore { - // appended - return nil - } else { - // the original element which was replaced - return originalElement - } - } -} diff --git a/apple/Sources/Sargon/Protocols/Collection/CanBeEmptyIdentifiedCollection.swift b/apple/Sources/Sargon/Protocols/Collection/CanBeEmptyIdentifiedCollection.swift deleted file mode 100644 index 72f3c87bb..000000000 --- a/apple/Sources/Sargon/Protocols/Collection/CanBeEmptyIdentifiedCollection.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation - -public protocol CanBeEmptyIdentifiedCollection: - BaseIdentifiedCollection, - RangeReplaceableCollection, - ExpressibleByArrayLiteral -where - ArrayLiteralElement == Self.Element -{ - init(_ elements: [Element]) - - func removing(_ id: Element.ID) -> Self - func removing(element: Element) -> Self -} - -extension CanBeEmptyIdentifiedCollection { - public init() { - self.init([]) - } - - public mutating func replaceSubrange( - _ subrange: Range, - with newElements: C - ) where C : Collection, Self.Element == C.Element { - var elements = self.elements - elements.removeSubrange(subrange) - elements.reserveCapacity(self.count + newElements.count) - for element in newElements.reversed() { - elements.insert(element, at: subrange.startIndex) - } - self = Self(elements) - } - - // This is already implemented on `BaseIdentifiedCollection`, - // but due to a Swift compiler bug in Xcode 15.3 we MUST implement - // it here too 🤷‍♂️. - public mutating func append(_ newElement: Self.Element) { - self = appending(newElement) - } - -} - -extension CanBeEmptyIdentifiedCollection { - public init(arrayLiteral elements: Element...) { - self.init(elements) - } -} - -extension CanBeEmptyIdentifiedCollection { - @discardableResult - public mutating func remove(_ id: Element.ID) -> Element? { - let removed = get(id: id) - self = removing(id) - return removed - } - - @discardableResult - public mutating func remove(element: Element) -> Element? { - let removed = get(id: element.id) - self = removing(element: element) - return removed - } -} - -extension CanBeEmptyIdentifiedCollection { - public subscript( - id id: Element.ID - ) -> Element? { - get { self.get(id: id) } - set { - if let newValue { - precondition(newValue.id == id) - self.updateOrAppend(newValue) - assert(contains(id: id)) - } else { - self.remove(id) - assert(!contains(id: id)) - } - } - } -} diff --git a/apple/Sources/Sargon/Protocols/Collection/NeverEmptyIdentifiedCollection.swift b/apple/Sources/Sargon/Protocols/Collection/NeverEmptyIdentifiedCollection.swift deleted file mode 100644 index 8408acdd5..000000000 --- a/apple/Sources/Sargon/Protocols/Collection/NeverEmptyIdentifiedCollection.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// File.swift -// -// -// Created by Alexander Cyon on 2024-04-14. -// - -import Foundation - -public protocol NeverEmptyIdentifiedCollection: BaseIdentifiedCollection { - init(_ elements: [Element]) throws - - func removing(_ id: Element.ID) throws -> Self - func removing(element: Element) throws -> Self -} - -extension NeverEmptyIdentifiedCollection { - - public mutating func remove(_ id: Element.ID) throws { - self = try removing(id) - } - - public mutating func remove(element: Element) throws { - self = try removing(element: element) - } -} diff --git a/apple/Sources/Sargon/Protocols/EntityProtocol.swift b/apple/Sources/Sargon/Protocols/EntityProtocol.swift index 9285686a0..fe8437f60 100644 --- a/apple/Sources/Sargon/Protocols/EntityProtocol.swift +++ b/apple/Sources/Sargon/Protocols/EntityProtocol.swift @@ -13,7 +13,7 @@ public protocol EntityBaseProtocol: BaseBaseEntityProtocol, CustomStringConverti var networkId: NetworkID { get } var displayName: DisplayName { get } var address: EntityAddress { get } - var flags: EntityFlags { get } + var flags: [EntityFlag] { get } var securityState: EntitySecurityState { get } var entityKind: EntityKind { get } var asGeneral: AccountOrPersona { get } diff --git a/apple/Tests/TestCases/Profile/Account/AccountTests.swift b/apple/Tests/TestCases/Profile/Account/AccountTests.swift index bc8f63323..a5cade5a4 100644 --- a/apple/Tests/TestCases/Profile/Account/AccountTests.swift +++ b/apple/Tests/TestCases/Profile/Account/AccountTests.swift @@ -30,7 +30,6 @@ final class AccountTests: EntityProtocolTest { func test_hidden() { let sut = SUT.sampleStokenetOlivia.flags - XCTAssertEqual(sut.elements, [.deletedByUser]) XCTAssertEqual(sut, [.deletedByUser]) } diff --git a/apple/Tests/TestCases/Profile/Collection/AccountsForDisplayTests.swift b/apple/Tests/TestCases/Profile/Collection/AccountsForDisplayTests.swift index 02a36e89b..7e98b5d3a 100644 --- a/apple/Tests/TestCases/Profile/Collection/AccountsForDisplayTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/AccountsForDisplayTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class AccountsForDisplayTests: CanBeEmptyCollectionTest {} +final class AccountsForDisplayTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/AccountsOrPersonasTests.swift b/apple/Tests/TestCases/Profile/Collection/AccountsOrPersonasTests.swift index f483b8d01..6d4d85fa1 100644 --- a/apple/Tests/TestCases/Profile/Collection/AccountsOrPersonasTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/AccountsOrPersonasTests.swift @@ -4,4 +4,14 @@ import Sargon import SargonUniFFI import XCTest -final class AccountsOrPersonasTests: CanBeEmptyCollectionTest {} + +final class AccountsOrPersonasTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift b/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift index e6abd1ca1..42ae99d97 100644 --- a/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/AccountsTests.swift @@ -1,122 +1,43 @@ import CustomDump import Foundation -@testable import Sargon +import Sargon import SargonUniFFI import XCTest +import SwiftyJSON -final class AccountsTests: CanBeEmptyCollectionTest { - func test_accounts_count() { - var sut: SUT = [] - func doTest(expected: Int) { - XCTAssertEqual(expected, sut.count) - } - doTest(expected: 0) - - sut.append(.sampleMainnet) - doTest(expected: 1) - - sut.append(.sampleMainnet) - doTest(expected: 1) // duplicates prevented, still `1` - - sut.append(.sampleMainnetOther) - doTest(expected: 2) - - sut.append(.sampleMainnetThird) - doTest(expected: 3) - - } - - func test_updating_or_appending_new_update() { - var sample = SUTElement.sample - let sut = SUT(element: sample) - sample.displayName = try! DisplayName(validating: "Changed") - XCTAssertEqual( - sut.updatingOrAppending(sample).elements, - [sample] - ) - } - - func test_update_or_append_update() { - var sample = SUTElement.sample - var sut = SUT(element: sample) - sample.displayName = "New Name" - let elem = sut.updateOrAppend(sample) - XCTAssertEqual(sut.elements, [sample]) - XCTAssertEqual(elem, SUTElement.sample) - } - - func test_update_or_append_append() { - let sample = SUTElement.sample - var sut = SUT(element: sample) - sut.updateOrAppend(SUTElement.sampleOther) - XCTAssertEqual(sut.elements, [sample, .sampleOther]) - } - - - func test_updateOrInsert_exists_wrong_index() { - var sut: SUT = [.sample, .sampleOther] - - let sampleChanged: SUTElement = { - var a = SUTElement.sample - a.displayName = "SampleChanged" - return a - }() - let wrongIndex = 1 - let (originalMember, deFactoIndex) = sut.updateOrInsert(element: sampleChanged, at: wrongIndex) // wrong index - XCTAssertEqual(originalMember, .sample) - XCTAssertNotEqual(deFactoIndex, wrongIndex) - XCTAssertEqual(deFactoIndex, 0) - XCTAssertEqual(sut.elements, [sampleChanged, .sampleOther]) - } - - func test_replaceSubrange_first() { - var sut: SUT = [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetNadia] - sut.replaceSubrange(0..<1, with: [.sampleStokenetOlivia]) - XCTAssertEqual(sut, [.sampleStokenetOlivia, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetNadia]) - } - - func test_replaceSubrange_many_leading() { - var sut: SUT = [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetNadia] - sut.replaceSubrange(0...1, with: [.sampleStokenetPaige, .sampleStokenetOlivia]) - XCTAssertEqual(sut, [.sampleStokenetPaige, .sampleStokenetOlivia, .sampleMainnetCarol, .sampleStokenetNadia]) - } - - func test_replaceSubrange_many_middle() { - var sut: SUT = [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetNadia] - sut.replaceSubrange(1...2, with: [.sampleStokenetPaige, .sampleStokenetOlivia]) - XCTAssertEqual(sut, [.sampleMainnetAlice, .sampleStokenetPaige, .sampleStokenetOlivia, .sampleStokenetNadia]) - } - - func test_replaceSubrange_many_trailing() { - var sut: SUT = [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetNadia] - sut.replaceSubrange(2...3, with: [.sampleStokenetPaige, .sampleStokenetOlivia]) - XCTAssertEqual(sut, [.sampleMainnetAlice, .sampleMainnetBob, .sampleStokenetPaige, .sampleStokenetOlivia]) - } - - func test_replaceSubrange_last() { - var sut: SUT = [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetNadia] - sut.replaceSubrange(3..<4, with: [.sampleStokenetOlivia]) - XCTAssertEqual(sut, [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetOlivia]) +final class AccountsTests: CollectionTest { + override class func sample() -> SUT { + SUT.sample + } + override class func sampleOther() -> SUT { + SUT.sampleOther + } + + /// Have to omit this test... obviously... since it crashes. + /// We can have this test implemented when swift-testing is stable to be used, + /// and we will use "exit tests" to test it: + /// https://forums.swift.org/t/exit-tests-death-tests-and-you/71186 + func omit_crash_if_duplicates() { // this test is relevant for Personas, AuthorizedDapps, ProfileNetworks etc etc... they all use the same rust type, which does not allow duplicates + var profile = Profile.sample + let a = Account.sample + var b = a + b.displayName = "Diff name, also crash" // different value on the element does not affect duplicates check, since it is ID based + profile.networks[0].accounts = [a, b] // Duplicates (by ID), not allowed => crash + let _ = profile.jsonData() // should crash } - - func test_replaceSubrange_last_many() { - var sut: SUT = [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetNadia] - sut.replaceSubrange(3..<4, with: [.sampleStokenetOlivia, .sampleStokenetPaige]) - XCTAssertEqual(sut, [.sampleMainnetAlice, .sampleMainnetBob, .sampleMainnetCarol, .sampleStokenetOlivia, .sampleStokenetPaige]) - } - - func test_updateOrInsert_exists_correct_index() { - var sut: SUT = [.sample, .sampleOther] - let sampleChanged: SUTElement = { - var a = SUTElement.sample - a.displayName = "SampleChanged" - return a - }() - let correctIndex = 0 - let (originalMember, deFactoIndex) = sut.updateOrInsert(element: sampleChanged, at: correctIndex) // correct index - XCTAssertEqual(originalMember, .sample) - XCTAssertEqual(deFactoIndex, correctIndex) - XCTAssertEqual(sut.elements, [sampleChanged, .sampleOther]) + func test_json_decoding_of_profile_fails_if_accounts_contains_duplicates() throws { + var json = JSON(Profile.sample) + json["profileNetworks.accounts"] = [Account.sample, Account.sample] + XCTAssertThrowsError(try Profile(jsonData: json.rawData())) + } + + func test_json_decoding_of_profile_fails_if_accounts_contains_duplicated_ids() throws { + var json = JSON(Profile.sample) + let a = Account.sample + var b = a + b.displayName = "Diff name, also crash" // different value on the element does not affect duplicates check, since it is ID based + json["profileNetworks.accounts"] = [a, b] + XCTAssertThrowsError(try Profile(jsonData: json.rawData())) } } diff --git a/apple/Tests/TestCases/Profile/Collection/AssetsExceptionListTests.swift b/apple/Tests/TestCases/Profile/Collection/AssetsExceptionListTests.swift index cd8f3d815..345a5e89d 100644 --- a/apple/Tests/TestCases/Profile/Collection/AssetsExceptionListTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/AssetsExceptionListTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class AssetsExceptionListTests: CanBeEmptyCollectionTest {} +final class AssetsExceptionListTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/AuthorizedDappsTests.swift b/apple/Tests/TestCases/Profile/Collection/AuthorizedDappsTests.swift index 5b37f93fa..55a74164c 100644 --- a/apple/Tests/TestCases/Profile/Collection/AuthorizedDappsTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/AuthorizedDappsTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class AuthorizedDappsTests: CanBeEmptyCollectionTest {} +final class AuthorizedDappsTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/DepositorsAllowListTests.swift b/apple/Tests/TestCases/Profile/Collection/DepositorsAllowListTests.swift index b990b1350..e2df4eef0 100644 --- a/apple/Tests/TestCases/Profile/Collection/DepositorsAllowListTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/DepositorsAllowListTests.swift @@ -11,4 +11,13 @@ import Sargon import SargonUniFFI import XCTest -final class DepositorsAllowListTests: CanBeEmptyCollectionTest {} +final class DepositorsAllowListTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/DetailedAuthorizedPersonasTests.swift b/apple/Tests/TestCases/Profile/Collection/DetailedAuthorizedPersonasTests.swift index a973e3ec7..576c47efa 100644 --- a/apple/Tests/TestCases/Profile/Collection/DetailedAuthorizedPersonasTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/DetailedAuthorizedPersonasTests.swift @@ -11,4 +11,13 @@ import Sargon import SargonUniFFI import XCTest -final class DetailedAuthorizedPersonasTests: CanBeEmptyCollectionTest {} +final class DetailedAuthorizedPersonasTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/EntityFlagsTests.swift b/apple/Tests/TestCases/Profile/Collection/EntityFlagsTests.swift index dd7929dea..336606d6c 100644 --- a/apple/Tests/TestCases/Profile/Collection/EntityFlagsTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/EntityFlagsTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class EntityFlagsTests: CanBeEmptyCollectionTest {} +final class EntityFlagsTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift b/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift index 8e7ab9095..88bf548dc 100644 --- a/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/FactorSourcesTests.swift @@ -3,5 +3,47 @@ import Foundation import Sargon import SargonUniFFI import XCTest +import SwiftyJSON + +final class FactorSourcesTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } + + /// Have to omit this test... obviously... since it crashes. + /// We can have this test implemented when swift-testing is stable to be used, + /// and we will use "exit tests" to test it: + /// https://forums.swift.org/t/exit-tests-death-tests-and-you/71186 + func omit_crash_if_empty() { + var profile = Profile.sample + profile.factorSources = [] // empty FactorSources is not allowed + let _ = profile.jsonData() // should crash + } + + func test_json_decoding_of_profile_fails_if_factorSources_is_empty() throws { + var json = JSON(Profile.sample) + json["factorSources"] = [] + XCTAssertThrowsError(try Profile(jsonData: json.rawData())) + } + + func test_json_decoding_of_profile_fails_if_factorSources_contains_duplicates() throws { + var json = JSON(Profile.sample) + json["factorSources"] = [FactorSource.sample, FactorSource.sample] + XCTAssertThrowsError(try Profile(jsonData: json.rawData())) + } + + func test_json_decoding_of_profile_fails_if_factorSources_contains_duplicated_ids() throws { + var json = JSON(Profile.sample) + let a = FactorSource.sample + var b = a + b.common.addedOn = .now + json["factorSources"] = [a, b] + XCTAssertThrowsError(try Profile(jsonData: json.rawData())) + } +} -final class FactorSourcesTests: NeverEmptyIdentifiedCollectionTest {} diff --git a/apple/Tests/TestCases/Profile/Collection/GatewaysTests.swift b/apple/Tests/TestCases/Profile/Collection/GatewaysTests.swift index 718ab3b7c..90cd4ad53 100644 --- a/apple/Tests/TestCases/Profile/Collection/GatewaysTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/GatewaysTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class GatewaysTests: CanBeEmptyCollectionTest {} +final class GatewaysTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/P2PLinksTests.swift b/apple/Tests/TestCases/Profile/Collection/P2PLinksTests.swift index ad0da3b0f..e4941d0e9 100644 --- a/apple/Tests/TestCases/Profile/Collection/P2PLinksTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/P2PLinksTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class P2PLinksTests: CanBeEmptyCollectionTest {} +final class P2PLinksTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/PersonasTests.swift b/apple/Tests/TestCases/Profile/Collection/PersonasTests.swift index c02d3e5e9..a3e099923 100644 --- a/apple/Tests/TestCases/Profile/Collection/PersonasTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/PersonasTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class PersonasTests: CanBeEmptyCollectionTest {} +final class PersonasTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/ProfileNetworksTests.swift b/apple/Tests/TestCases/Profile/Collection/ProfileNetworksTests.swift index 03b1f8c45..7adb5230b 100644 --- a/apple/Tests/TestCases/Profile/Collection/ProfileNetworksTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/ProfileNetworksTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class ProfileNetworksTests: CanBeEmptyCollectionTest {} +final class ProfileNetworksTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/ReferencesToAuthorizedPersonasTests.swift b/apple/Tests/TestCases/Profile/Collection/ReferencesToAuthorizedPersonasTests.swift index 4276d05ca..0042b226c 100644 --- a/apple/Tests/TestCases/Profile/Collection/ReferencesToAuthorizedPersonasTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/ReferencesToAuthorizedPersonasTests.swift @@ -11,4 +11,13 @@ import Sargon import SargonUniFFI import XCTest -final class ReferencesToAuthorizedPersonasTests: CanBeEmptyCollectionTest {} +final class ReferencesToAuthorizedPersonasTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Collection/SupportedCurvesTests.swift b/apple/Tests/TestCases/Profile/Collection/SupportedCurvesTests.swift index 8af7b1134..42dd644a0 100644 --- a/apple/Tests/TestCases/Profile/Collection/SupportedCurvesTests.swift +++ b/apple/Tests/TestCases/Profile/Collection/SupportedCurvesTests.swift @@ -4,4 +4,13 @@ import Sargon import SargonUniFFI import XCTest -final class SupportedCurvesTests: NeverEmptyIdentifiedCollectionTest {} +final class SupportedCurvesTests: CollectionTest { + + override class func sample() -> SUT { + SUT.sample + } + + override class func sampleOther() -> SUT { + SUT.sampleOther + } +} diff --git a/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift b/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift index 830cbaa75..28c2cecf7 100644 --- a/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift +++ b/apple/Tests/TestCases/Profile/Factor/DeviceFactorSourceTests.swift @@ -3,6 +3,7 @@ import Foundation import Sargon import SargonUniFFI import XCTest +import SwiftyJSON final class DeviceFactorSourceTests: SpecificFactorSourceTest { func test_id_of_device() { @@ -72,5 +73,10 @@ final class DeviceFactorSourceTests: SpecificFactorSourceTest { func test_hidden() { let sut = SUT.sampleMainnetTuring.flags - XCTAssertEqual(sut.elements, [.deletedByUser]) XCTAssertEqual(sut, [.deletedByUser]) } diff --git a/apple/Tests/TestCases/Profile/ProfileTests.swift b/apple/Tests/TestCases/Profile/ProfileTests.swift index b0ce502f3..d1d40b0d7 100644 --- a/apple/Tests/TestCases/Profile/ProfileTests.swift +++ b/apple/Tests/TestCases/Profile/ProfileTests.swift @@ -44,7 +44,7 @@ final class ProfileTests: Test { XCTAssertEqual(sut.header, header) XCTAssertEqual(sut.appPreferences, .default) XCTAssertEqual(sut.networks, []) - XCTAssertEqual(sut.factorSources.elements, [dfs.asGeneral]) + XCTAssertEqual(sut.factorSources, [dfs.asGeneral]) } func test_analyze_file_not_profile() { diff --git a/apple/Tests/Utils/Collection/BaseIdentifiedCollectionTests.swift b/apple/Tests/Utils/Collection/BaseIdentifiedCollectionTests.swift deleted file mode 100644 index c3ad4bcd5..000000000 --- a/apple/Tests/Utils/Collection/BaseIdentifiedCollectionTests.swift +++ /dev/null @@ -1,136 +0,0 @@ -import CustomDump -import Foundation -import Sargon -import SargonUniFFI -import XCTest - -class BaseCollectionTest: Test { - typealias SUTElement = SUT_.Element - - func test_element_roundtrip() throws { - let element = SUTElement.sample - XCTAssertEqual( - SUT(element: element).elements, - [element] - ) - } - - func test_get_id() { - let element = SUTElement.sample - let sut = SUT(element: element) - XCTAssertEqual(sut.get(id: element.id), element) - } - - func test_appending_new() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - let sut = SUT(element: sample) - XCTAssertEqual( - sut.appending(sampleOther).elements, - [sample, sampleOther] - ) - } - - func test_updating_or_appending_new_append() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - let sut = SUT(element: sample) - XCTAssertEqual( - sut.updatingOrAppending(sampleOther).elements, - [sample, sampleOther] - ) - } - - func test_updating_or_inserting_new_append_last() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - let sut = SUT(element: sample) - XCTAssertEqual( - sut.updatingOrInserting(element: sampleOther, at: 1).elements, - [sample, sampleOther] - ) - } - - func test_updating_or_inserting_new_append_first() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - let sut = SUT(element: sample) - XCTAssertEqual( - sut.updatingOrInserting(element: sampleOther, at: 0).elements, - [sampleOther, sample] - ) - } - - func test_mutable_subscript_set_first() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - var sut = SUT(element: sample) - sut[0] = .sampleOther - XCTAssertEqual( - sut.elements, - [sampleOther, sample] - ) - } - - func test_mutable_subscript_set_last() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - var sut = SUT(element: sample) - sut[1] = .sampleOther - XCTAssertEqual( - sut.elements, - [sample, sampleOther] - ) - } - - func test_contains() { - let sample = SUTElement.sample - let sut = SUT(element: sample) - XCTAssertTrue(sut.contains(id: sample.id)) - XCTAssertFalse(sut.contains(id: SUTElement.sampleOther.id)) - } - - func test_ids() { - func doTest(_ sut: SUT) { - XCTAssertEqual(sut.ids, sut.elements.map(\.id)) - } - SUT.sampleValues.forEach(doTest) - } - - func test_append_new() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - var sut = SUT(element: sample) - sut.append(sampleOther) - XCTAssertEqual( - sut.elements, - [sample, sampleOther] - ) - } - - func test_count() { - let sample = SUTElement.sample - let sampleOther = SUTElement.sampleOther - var sut = SUT(element: sample) - XCTAssertEqual(sut.count, 1) - sut.append(sampleOther) - XCTAssertEqual(sut.count, 2) - } - - func test_appending_new_duplicate_disallowd() { - let sample = SUTElement.sample - let sut = SUT(element: sample) - XCTAssertEqual( - sut.appending(sample).elements, // unchanged - [sample] - ) - } - - func test_append_filter() { - let sut = SUT(element: .sample).appending(.sampleOther) - XCTAssertEqual( - sut.filter({ $0.id == SUTElement.sample.id }), - [SUTElement.sample] - ) - } -} diff --git a/apple/Tests/Utils/Collection/CanBeEmptyCollectionTest.swift b/apple/Tests/Utils/Collection/CanBeEmptyCollectionTest.swift deleted file mode 100644 index e9797e1f4..000000000 --- a/apple/Tests/Utils/Collection/CanBeEmptyCollectionTest.swift +++ /dev/null @@ -1,117 +0,0 @@ -import CustomDump -import Foundation -import Sargon -import SargonUniFFI -import XCTest - -class CanBeEmptyCollectionTest: BaseCollectionTest { - func test_can_be_empty() { - XCTAssertEqual(SUT([]).count, 0) - } - - func test_expressible_by_array_literal() { - XCTAssertEqual(SUT(element: SUTElement.sample), [SUTElement.sample]) - } - - func test_removing_element_by_id() { - let sut: SUT = [.sample, .sampleOther] - XCTAssertEqual( - sut.removing(SUTElement.sample.id), - [.sampleOther] - ) - } - - func test_removing_by_element() { - let sut: SUT = [.sample, .sampleOther] - XCTAssertEqual( - sut.removing(element: SUTElement.sample), - [.sampleOther] - ) - } - - func test_remove_element_by_id() { - var sut: SUT = [.sample, .sampleOther] - let removed = sut.remove(SUTElement.sample.id) - XCTAssertEqual(removed, SUTElement.sample) - XCTAssertEqual( - sut, - [.sampleOther] - ) - } - - func test_init() { - XCTAssertEqual(SUT.init(), SUT.init([])) - XCTAssertEqual(SUT.init().count, 0) - } - - func test_replaceSubrange() { - var sut = [SUTElement.sample] - sut.replaceSubrange(0..<1, with: [SUTElement.sampleOther]) - XCTAssertEqual(sut, [SUTElement.sampleOther]) - } - - func test_remove_element_by_id_not_present_returns_nil() { - var sut: SUT = [.sampleOther] - XCTAssertNil(sut.remove(SUTElement.sample.id)) - XCTAssertEqual(sut, [.sampleOther]) - } - - func test_remove_by_element() { - var sut: SUT = [.sample, .sampleOther] - let removed = sut.remove(element: .sample) - XCTAssertEqual(removed, SUTElement.sample) - XCTAssertEqual( - sut, - [.sampleOther] - ) - } - - func test_remove_element_by_element_not_present_returns_nil() { - var sut: SUT = [.sampleOther] - XCTAssertNil(sut.remove(element: SUTElement.sample)) - XCTAssertEqual(sut, [.sampleOther]) - } - - func test_subscript_id_get() { - let sut: SUT = [.sample, .sampleOther] - XCTAssertEqual(sut[id: SUTElement.sample.id], SUTElement.sample) - } - - func test_remove_by_id_subscript() { - var sut: SUT = [.sample, .sampleOther] - sut[id: SUTElement.sample.id] = nil - XCTAssertEqual( - sut, - [.sampleOther] - ) - } - - func test_add_by_id_subscript() { - var sut: SUT = [.sample] - sut[id: SUTElement.sampleOther.id] = SUTElement.sampleOther - XCTAssertEqual( - sut, - [.sample, .sampleOther] - ) - } -} - - - - - - - - - - - - - - - - - - - - diff --git a/apple/Tests/Utils/Collection/NeverEmptyIdentifiedCollectionTest.swift b/apple/Tests/Utils/Collection/NeverEmptyIdentifiedCollectionTest.swift deleted file mode 100644 index 667a26625..000000000 --- a/apple/Tests/Utils/Collection/NeverEmptyIdentifiedCollectionTest.swift +++ /dev/null @@ -1,56 +0,0 @@ -import CustomDump -import Foundation -import Sargon -import SargonUniFFI -import XCTest - -class NeverEmptyIdentifiedCollectionTest: BaseCollectionTest { - - func test_cannot_be_empty() { - XCTAssertThrowsError(try SUT([])) - } - - func test_removing_element_by_id() throws { - let sut = try SUT([.sample, .sampleOther]) - XCTAssertEqual( - try sut.removing(SUTElement.sample.id), - try SUT([.sampleOther]) - ) - } - - func test_removing_by_element() throws { - let sut = try SUT([.sample, .sampleOther]) - XCTAssertEqual( - try sut.removing(element: SUTElement.sample), - try SUT([.sampleOther]) - ) - } - - func test_removing_element_by_id_throws_if_single_element() throws { - let sut = try SUT([.sample]) - XCTAssertThrowsError(try sut.removing(SUTElement.sample.id)) - } - - func test_removing_by_element_throws_if_single_element() throws { - let sut = try SUT([.sample]) - XCTAssertThrowsError(try sut.removing(element: SUTElement.sample)) - } - - func test_remove_element_by_id() throws { - var sut = try SUT([.sample, .sampleOther]) - try sut.remove(SUTElement.sample.id) - XCTAssertEqual( - sut, - try SUT([.sampleOther]) - ) - } - - func test_remove_by_element() throws { - var sut = try SUT([.sample, .sampleOther]) - try sut.remove(element: .sample) - XCTAssertEqual( - sut, - try SUT([.sampleOther]) - ) - } -} diff --git a/apple/Tests/Utils/CollectionTest.swift b/apple/Tests/Utils/CollectionTest.swift new file mode 100644 index 000000000..56596466a --- /dev/null +++ b/apple/Tests/Utils/CollectionTest.swift @@ -0,0 +1,37 @@ +import CustomDump +import Foundation +import Sargon +import SargonUniFFI +import XCTest + +class CollectionTest: TestCase { + typealias SUT = [Element] + + class func sample() -> SUT { + fatalError("override me") + } + class func sampleOther() -> SUT { + fatalError("override me") + } + + func test_equality() { + XCTAssertNoDifference(Self.sample(), Self.sample()) + } + + func test_inequality() { + XCTAssertNotEqual(Self.sample(), Self.sampleOther()) + } + + func test_ids_are_unique() { + func doTest(_ sut: SUT) { + XCTAssertEqual( + Set(sut.map(\.id)).count, + Set(sut).count + ) + } + doTest(Self.sample()) + doTest(Self.sampleOther()) + } + +} + diff --git a/apple/Tests/Utils/FactorSourceTest.swift b/apple/Tests/Utils/FactorSourceTest.swift index ce54b5983..4e54042c1 100644 --- a/apple/Tests/Utils/FactorSourceTest.swift +++ b/apple/Tests/Utils/FactorSourceTest.swift @@ -4,18 +4,6 @@ import Sargon import SargonUniFFI import XCTest -class SpecificFactorSourceTest: FactorSourceTest { - - func test_extract() throws { - func doTest(_ sut: SUT) throws { - let embedded = sut.asGeneral - let extracted: SUT = try embedded.extract() - XCTAssertEqual(extracted, sut) - } - try SUT.sampleValues.forEach(doTest) - } -} - class FactorSourceTest: Test { func test_as_general_factorSourceID() { diff --git a/apple/Tests/Utils/SpecificFactorSourceTest.swift b/apple/Tests/Utils/SpecificFactorSourceTest.swift new file mode 100644 index 000000000..1cb58ed11 --- /dev/null +++ b/apple/Tests/Utils/SpecificFactorSourceTest.swift @@ -0,0 +1,17 @@ +import CustomDump +import Foundation +import Sargon +import SargonUniFFI +import XCTest + +class SpecificFactorSourceTest: FactorSourceTest { + + func test_extract() throws { + func doTest(_ sut: SUT) throws { + let embedded = sut.asGeneral + let extracted: SUT = try embedded.extract() + XCTAssertEqual(extracted, sut) + } + try SUT.sampleValues.forEach(doTest) + } +} diff --git a/examples/android/src/main/java/com/radixdlt/sargon/android/MainActivity.kt b/examples/android/src/main/java/com/radixdlt/sargon/android/MainActivity.kt index 68232b459..574d4cca5 100644 --- a/examples/android/src/main/java/com/radixdlt/sargon/android/MainActivity.kt +++ b/examples/android/src/main/java/com/radixdlt/sargon/android/MainActivity.kt @@ -18,8 +18,6 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.Button import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextField @@ -43,8 +41,6 @@ import com.radixdlt.sargon.Wallet import com.radixdlt.sargon.WalletClientModel import com.radixdlt.sargon.android.ui.theme.SargonAndroidTheme import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.string import com.radixdlt.sargon.extensions.toBagOfBytes import com.radixdlt.sargon.samples.sample import kotlin.random.Random @@ -71,7 +67,9 @@ fun WalletContent(modifier: Modifier = Modifier, storage: SecureStorage) { bottomBar = { if (walletState == null) { Button( - modifier = Modifier.padding(16.dp).fillMaxWidth(), + modifier = Modifier + .padding(16.dp) + .fillMaxWidth(), onClick = { walletState = Wallet.with( @@ -81,7 +79,7 @@ fun WalletContent(modifier: Modifier = Modifier, storage: SecureStorage) { profile = walletState?.profile() } ) { Text(text = "Generate new Wallet") } - } else if (profile?.networks()?.isEmpty() == true) { + } else if (profile?.networks?.isEmpty() == true) { Column(modifier = Modifier.padding(16.dp)) { var accountName by remember { mutableStateOf("") } TextField( @@ -108,7 +106,7 @@ fun WalletContent(modifier: Modifier = Modifier, storage: SecureStorage) { } ) { padding -> LazyColumn(modifier = Modifier.padding(padding), contentPadding = PaddingValues(16.dp)) { - items(profile?.networks().orEmpty()) { + items(profile?.networks.orEmpty()) { Network( network = it, onAccountAdd = { newName -> @@ -127,9 +125,9 @@ fun WalletContent(modifier: Modifier = Modifier, storage: SecureStorage) { @Composable fun Network( - modifier: Modifier = Modifier, - network: ProfileNetwork, - onAccountAdd: (String) -> Unit + modifier: Modifier = Modifier, + network: ProfileNetwork, + onAccountAdd: (String) -> Unit ) { ElevatedCard(modifier = modifier.fillMaxWidth()) { Spacer(modifier = Modifier.height(16.dp)) @@ -190,5 +188,5 @@ fun Wallet.Companion.with( @Composable fun NetworkPreview() { val profile = Profile.sample() - Network(network = profile.networks().first(), onAccountAdd = {}) + Network(network = profile.networks.first(), onAccountAdd = {}) } diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Accounts.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Accounts.kt index fb6f605eb..47bbd441e 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Accounts.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Accounts.kt @@ -2,46 +2,18 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.Account import com.radixdlt.sargon.AccountAddress -import com.radixdlt.sargon.Accounts -import com.radixdlt.sargon.accountsElementCount -import com.radixdlt.sargon.accountsGetAccountById -import com.radixdlt.sargon.accountsGetElements -import com.radixdlt.sargon.newAccounts -import com.radixdlt.sargon.newAccountsByAppending -import com.radixdlt.sargon.newAccountsByUpdatingOrAppending -import com.radixdlt.sargon.newAccountsByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newAccountsRemovedById -import com.radixdlt.sargon.newAccountsRemovedElement -fun Accounts.Companion.init(vararg account: Account): Accounts = - newAccounts(accounts = account.asList()) +class Accounts private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { -fun Accounts.Companion.init(accounts: List): Accounts = newAccounts(accounts = accounts) + constructor(accounts: List) : this( + IdentifiedArrayImpl( + elements = accounts, + identifier = { it.address } + ) + ) -operator fun Accounts.invoke() = accountsGetElements(accounts = this) - -operator fun Accounts.get(index: Int) = invoke().get(index = index) - -operator fun Accounts.contains(element: Account) = invoke().contains(element = element) - -val Accounts.size: Int - get() = accountsElementCount(accounts = this).toInt() - -fun Accounts.append(account: Account): Accounts = - newAccountsByAppending(account = account, to = this) - -fun Accounts.updateOrInsert(account: Account, index: Int): Accounts = - newAccountsByUpdatingOrInsertingAtIndex(account = account, to = this, index = index.toULong()) - -fun Accounts.updateOrAppend(account: Account): Accounts = - newAccountsByUpdatingOrAppending(account = account, to = this) - -fun Accounts.removeByAddress(address: AccountAddress): Accounts = - newAccountsRemovedById(idOfAccount = address, from = this) - -fun Accounts.remove(account: Account): Accounts = - newAccountsRemovedElement(account = account, from = this) - -fun Accounts.getBy(address: AccountAddress): Account? = - accountsGetAccountById(accounts = this, id = address) + constructor(vararg account: Account) : this(accounts = account.asList()) +} diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AssetsExceptionList.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AssetsExceptionList.kt index f6535d8bf..2f9c222f8 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AssetsExceptionList.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AssetsExceptionList.kt @@ -1,55 +1,20 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.AssetException -import com.radixdlt.sargon.AssetsExceptionList import com.radixdlt.sargon.ResourceAddress -import com.radixdlt.sargon.assetsExceptionListElementCount -import com.radixdlt.sargon.assetsExceptionListGetAssetExceptionById -import com.radixdlt.sargon.assetsExceptionListGetElements -import com.radixdlt.sargon.newAssetsExceptionList -import com.radixdlt.sargon.newAssetsExceptionListByAppending -import com.radixdlt.sargon.newAssetsExceptionListByUpdatingOrAppending -import com.radixdlt.sargon.newAssetsExceptionListByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newAssetsExceptionListRemovedById -import com.radixdlt.sargon.newAssetsExceptionListRemovedElement -fun AssetsExceptionList.Companion.init(vararg assetException: AssetException): AssetsExceptionList = - init(assetsExceptions = assetException.asList()) - -fun AssetsExceptionList.Companion.init(assetsExceptions: List): AssetsExceptionList = - newAssetsExceptionList(assetsExceptionList = assetsExceptions) - -operator fun AssetsExceptionList.invoke() = - assetsExceptionListGetElements(assetsExceptionList = this) - -operator fun AssetsExceptionList.get(index: Int) = invoke().get(index = index) - -operator fun AssetsExceptionList.contains(element: AssetException) = - invoke().contains(element = element) - -val AssetsExceptionList.size: Int - get() = assetsExceptionListElementCount(assetsExceptionList = this).toInt() - -fun AssetsExceptionList.append(assetException: AssetException): AssetsExceptionList = - newAssetsExceptionListByAppending(assetException = assetException, to = this) - -fun AssetsExceptionList.updateOrInsert( - assetException: AssetException, - index: Int -): AssetsExceptionList = newAssetsExceptionListByUpdatingOrInsertingAtIndex( - assetException = assetException, - to = this, - index = index.toULong() -) - -fun AssetsExceptionList.updateOrAppend(assetException: AssetException): AssetsExceptionList = - newAssetsExceptionListByUpdatingOrAppending(assetException = assetException, to = this) - -fun AssetsExceptionList.removeByAddress(address: ResourceAddress): AssetsExceptionList = - newAssetsExceptionListRemovedById(idOfAssetException = address, from = this) - -fun AssetsExceptionList.remove(assetException: AssetException): AssetsExceptionList = - newAssetsExceptionListRemovedElement(assetException = assetException, from = this) - -fun AssetsExceptionList.getBy(address: ResourceAddress): AssetException? = - assetsExceptionListGetAssetExceptionById(assetsExceptionList = this, id = address) \ No newline at end of file +class AssetsExceptionList private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { + + constructor(assetExceptions: List) : this( + IdentifiedArrayImpl( + elements = assetExceptions, + identifier = { it.address } + ) + ) + + constructor( + vararg assetException: AssetException + ) : this(assetExceptions = assetException.asList()) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AuthorisedDapps.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AuthorisedDapps.kt deleted file mode 100644 index ea8b5553d..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AuthorisedDapps.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.radixdlt.sargon.extensions - -import com.radixdlt.sargon.AccountAddress -import com.radixdlt.sargon.AuthorizedDapp -import com.radixdlt.sargon.AuthorizedDapps -import com.radixdlt.sargon.authorizedDappsGetAuthorizedDappById -import com.radixdlt.sargon.authorizedDappsGetElements -import com.radixdlt.sargon.newAccountsByUpdatingOrAppending -import com.radixdlt.sargon.newAuthorizedDapps -import com.radixdlt.sargon.newAuthorizedDappsByAppending -import com.radixdlt.sargon.newAuthorizedDappsByUpdatingOrAppending -import com.radixdlt.sargon.newAuthorizedDappsByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newAuthorizedDappsRemovedById -import com.radixdlt.sargon.newAuthorizedDappsRemovedElement - -@Throws(SargonException::class) -fun AuthorizedDapps.Companion.init(vararg authorisedDapp: AuthorizedDapp): AuthorizedDapps = - newAuthorizedDapps(authorizedDapps = authorisedDapp.asList()) - -@Throws(SargonException::class) -fun AuthorizedDapps.Companion.init(authorisedDapps: List): AuthorizedDapps = - newAuthorizedDapps(authorizedDapps = authorisedDapps) - -operator fun AuthorizedDapps.invoke() = authorizedDappsGetElements(authorizedDapps = this) - -operator fun AuthorizedDapps.get(index: Int) = invoke().get(index = index) - -operator fun AuthorizedDapps.contains(element: AuthorizedDapp) = - invoke().contains(element = element) - -val AuthorizedDapps.size: Int - get() = invoke().size - -fun AuthorizedDapps.append(authorizedDApp: AuthorizedDapp): AuthorizedDapps = - newAuthorizedDappsByAppending(authorizedDapp = authorizedDApp, to = this) - -fun AuthorizedDapps.updateOrInsert(authorizedDApp: AuthorizedDapp, index: Int): AuthorizedDapps = - newAuthorizedDappsByUpdatingOrInsertingAtIndex( - authorizedDapp = authorizedDApp, - to = this, - index = index.toULong() - ) - -fun AuthorizedDapps.updateOrAppend(authorizedDApp: AuthorizedDapp): AuthorizedDapps = - newAuthorizedDappsByUpdatingOrAppending(authorizedDapp = authorizedDApp, to = this) - -fun AuthorizedDapps.removeByAddress(address: AccountAddress): AuthorizedDapps = - newAuthorizedDappsRemovedById(idOfAuthorizedDapp = address, from = this) - -fun AuthorizedDapps.remove(authorizedDApp: AuthorizedDapp): AuthorizedDapps = - newAuthorizedDappsRemovedElement(authorizedDapp = authorizedDApp, from = this) - -fun AuthorizedDapps.getBy(address: AccountAddress): AuthorizedDapp? = - authorizedDappsGetAuthorizedDappById(authorizedDapps = this, id = address) \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AuthorizedDapps.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AuthorizedDapps.kt new file mode 100644 index 000000000..b84c91889 --- /dev/null +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/AuthorizedDapps.kt @@ -0,0 +1,20 @@ +package com.radixdlt.sargon.extensions + +import com.radixdlt.sargon.AccountAddress +import com.radixdlt.sargon.AuthorizedDapp + +class AuthorizedDapps private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { + + constructor(authorizedDapps: List) : this( + IdentifiedArrayImpl( + elements = authorizedDapps, + identifier = { it.dappDefinitionAddress } + ) + ) + + constructor( + vararg authorizedDapp: AuthorizedDapp + ) : this(authorizedDapps = authorizedDapp.asList()) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/DepositorsAllowList.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/DepositorsAllowList.kt index 0c73a3665..aed084e76 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/DepositorsAllowList.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/DepositorsAllowList.kt @@ -1,62 +1,19 @@ package com.radixdlt.sargon.extensions -import com.radixdlt.sargon.DepositorsAllowList import com.radixdlt.sargon.ResourceOrNonFungible -import com.radixdlt.sargon.depositorsAllowListElementCount -import com.radixdlt.sargon.depositorsAllowListGetElements -import com.radixdlt.sargon.depositorsAllowListGetResourceOrNonFungibleById -import com.radixdlt.sargon.newDepositorsAllowList -import com.radixdlt.sargon.newDepositorsAllowListByAppending -import com.radixdlt.sargon.newDepositorsAllowListByUpdatingOrAppending -import com.radixdlt.sargon.newDepositorsAllowListByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newDepositorsAllowListRemovedElement -fun DepositorsAllowList.Companion.init(vararg resourceOrNonFungible: ResourceOrNonFungible): DepositorsAllowList = - init(depositorsAllowList = resourceOrNonFungible.asList()) - -fun DepositorsAllowList.Companion.init(depositorsAllowList: List): DepositorsAllowList = - newDepositorsAllowList(depositorsAllowList = depositorsAllowList) - -operator fun DepositorsAllowList.invoke() = - depositorsAllowListGetElements(depositorsAllowList = this) - -operator fun DepositorsAllowList.get(index: Int) = invoke().get(index = index) - -operator fun DepositorsAllowList.contains(element: ResourceOrNonFungible) = - invoke().contains(element = element) - -val DepositorsAllowList.size: Int - get() = depositorsAllowListElementCount(depositorsAllowList = this).toInt() - -fun DepositorsAllowList.append(resourceOrNonFungible: ResourceOrNonFungible): DepositorsAllowList = - newDepositorsAllowListByAppending(resourceOrNonFungible = resourceOrNonFungible, to = this) - -fun DepositorsAllowList.updateOrInsert( - resourceOrNonFungible: ResourceOrNonFungible, - index: Int -): DepositorsAllowList = newDepositorsAllowListByUpdatingOrInsertingAtIndex( - resourceOrNonFungible = resourceOrNonFungible, - to = this, - index = index.toULong() -) - -fun DepositorsAllowList.updateOrAppend( - resourceOrNonFungible: ResourceOrNonFungible -): DepositorsAllowList = newDepositorsAllowListByUpdatingOrAppending( - resourceOrNonFungible = resourceOrNonFungible, - to = this -) - -fun DepositorsAllowList.remove( - resourceOrNonFungible: ResourceOrNonFungible -): DepositorsAllowList = newDepositorsAllowListRemovedElement( - resourceOrNonFungible = resourceOrNonFungible, - from = this -) - -fun DepositorsAllowList.getBy( - resourceOrNonFungible: ResourceOrNonFungible -): ResourceOrNonFungible? = depositorsAllowListGetResourceOrNonFungibleById( - depositorsAllowList = this, - id = resourceOrNonFungible -) \ No newline at end of file +class DepositorsAllowList private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { + + constructor(resourcesOrNonFungibles: List) : this( + IdentifiedArrayImpl( + elements = resourcesOrNonFungibles, + identifier = { it } + ) + ) + + constructor(vararg resourceOrNonFungible: ResourceOrNonFungible) : this( + resourcesOrNonFungibles = resourceOrNonFungible.asList() + ) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/EntityFlags.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/EntityFlags.kt index 1b87df155..9e16f98e8 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/EntityFlags.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/EntityFlags.kt @@ -1,52 +1,19 @@ package com.radixdlt.sargon.extensions -import com.radixdlt.sargon.AuthorizedDapp -import com.radixdlt.sargon.AuthorizedDapps import com.radixdlt.sargon.EntityFlag -import com.radixdlt.sargon.EntityFlags -import com.radixdlt.sargon.entityFlagsElementCount -import com.radixdlt.sargon.entityFlagsGetElements -import com.radixdlt.sargon.entityFlagsGetEntityFlagById -import com.radixdlt.sargon.newAuthorizedDappsByUpdatingOrAppending -import com.radixdlt.sargon.newAuthorizedDappsByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newEntityFlags -import com.radixdlt.sargon.newEntityFlagsByAppending -import com.radixdlt.sargon.newEntityFlagsByUpdatingOrAppending -import com.radixdlt.sargon.newEntityFlagsByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newEntityFlagsRemovedElement -@Throws(SargonException::class) -fun EntityFlags.Companion.init(vararg entityFlag: EntityFlag): EntityFlags = - init(entityFlags = entityFlag.asList()) +class EntityFlags private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { -@Throws(SargonException::class) -fun EntityFlags.Companion.init(entityFlags: List): EntityFlags = - newEntityFlags(entityFlags = entityFlags) - -operator fun EntityFlags.invoke() = entityFlagsGetElements(entityFlags = this) - -operator fun EntityFlags.get(index: Int) = invoke().get(index = index) - -operator fun EntityFlags.contains(element: EntityFlag) = invoke().contains(element = element) - -val EntityFlags.size: Int - get() = entityFlagsElementCount(entityFlags = this).toInt() - -fun EntityFlags.append(entityFlag: EntityFlag): EntityFlags = - newEntityFlagsByAppending(entityFlag = entityFlag, to = this) - -fun EntityFlags.updateOrInsert(entityFlag: EntityFlag, index: Int): EntityFlags = - newEntityFlagsByUpdatingOrInsertingAtIndex( - entityFlag = entityFlag, - to = this, - index = index.toULong() + constructor(entityFlags: List) : this( + IdentifiedArrayImpl( + elements = entityFlags, + identifier = { it } + ) ) -fun EntityFlags.updateOrAppend(entityFlag: EntityFlag): EntityFlags = - newEntityFlagsByUpdatingOrAppending(entityFlag = entityFlag, to = this) - -fun EntityFlags.remove(entityFlag: EntityFlag): EntityFlags = - newEntityFlagsRemovedElement(entityFlag = entityFlag, from = this) + constructor(vararg entityFlag: EntityFlag) : this(entityFlags = entityFlag.asList()) -fun EntityFlags.get(entityFlag: EntityFlag): EntityFlag? = - entityFlagsGetEntityFlagById(entityFlags = this, id = entityFlag) \ No newline at end of file + companion object +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt index 4af4f6ba2..258ac6fae 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSource.kt @@ -25,6 +25,9 @@ val FactorSource.kind: FactorSourceKind is FactorSource.Ledger -> value.kind } +fun DeviceFactorSource.asGeneral() = FactorSource.Device(value = this) +fun LedgerHardwareWalletFactorSource.asGeneral() = FactorSource.Ledger(value = this) + fun FactorSource.Device.Companion.olympia( mnemonicWithPassphrase: MnemonicWithPassphrase ) = newDeviceFactorSourceOlympia( diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSources.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSources.kt index 513f2dd10..9e28ff11f 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSources.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/FactorSources.kt @@ -1,73 +1,21 @@ package com.radixdlt.sargon.extensions -import com.radixdlt.sargon.DeviceFactorSource -import com.radixdlt.sargon.EntityFlag -import com.radixdlt.sargon.EntityFlags import com.radixdlt.sargon.FactorSource import com.radixdlt.sargon.FactorSourceId -import com.radixdlt.sargon.FactorSources -import com.radixdlt.sargon.LedgerHardwareWalletFactorSource -import com.radixdlt.sargon.factorSourcesElementCount -import com.radixdlt.sargon.factorSourcesGetElements -import com.radixdlt.sargon.factorSourcesGetFactorSourceById -import com.radixdlt.sargon.newEntityFlagsByUpdatingOrAppending -import com.radixdlt.sargon.newEntityFlagsByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newFactorSources -import com.radixdlt.sargon.newFactorSourcesByAppending -import com.radixdlt.sargon.newFactorSourcesByUpdatingOrAppending -import com.radixdlt.sargon.newFactorSourcesByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newFactorSourcesRemovedById -import com.radixdlt.sargon.newFactorSourcesRemovedElement -@Throws(SargonException::class) -fun FactorSources.Companion.init(vararg factorSource: FactorSource): FactorSources = - init(factorSources = factorSource.asList()) +class FactorSources private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { -@Throws(SargonException::class) -fun FactorSources.Companion.init(factorSources: List): FactorSources = - newFactorSources(factorSources = factorSources) - -operator fun FactorSources.invoke() = factorSourcesGetElements(factorSources = this) - -operator fun FactorSources.get(index: Int) = invoke().get(index = index) - -operator fun FactorSources.contains(element: FactorSource) = invoke().contains(element = element) - -val FactorSources.size: Int - get() = factorSourcesElementCount(factorSources = this).toInt() - -fun FactorSources.append(factorSource: FactorSource): FactorSources = - newFactorSourcesByAppending(factorSource = factorSource, to = this) - -fun FactorSources.updateOrInsert(factorSource: FactorSource, index: Int): FactorSources = - newFactorSourcesByUpdatingOrInsertingAtIndex( - factorSource = factorSource, - to = this, - index = index.toULong() + constructor(factorSources: List) : this( + IdentifiedArrayImpl( + elements = factorSources, + identifier = { it.id } + ) ) -fun FactorSources.updateOrAppend(factorSource: FactorSource): FactorSources = - newFactorSourcesByUpdatingOrAppending(factorSource = factorSource, to = this) - -/** - * FactorSources is NonEmpty, so this throws if the resulting collection would be empty when - * removing the element would result in an empty copy. - */ -@Throws(SargonException::class) -fun FactorSources.remove(factorSource: FactorSource): FactorSources = - newFactorSourcesRemovedElement(factorSource = factorSource, from = this) - -/** - * FactorSources is NonEmpty, so this throws if the resulting collection would be empty when - * removing the element by id would result in an empty copy. - */ -@Throws(SargonException::class) -fun FactorSources.removeById(id: FactorSourceId): FactorSources = - newFactorSourcesRemovedById(idOfFactorSource = id, from = this) - -fun FactorSources.get(id: FactorSourceId): FactorSource? = - factorSourcesGetFactorSourceById(factorSources = this, id = id) - -fun DeviceFactorSource.asGeneral() = FactorSource.Device(this) -fun LedgerHardwareWalletFactorSource.asGeneral() = FactorSource.Ledger(this) + constructor(vararg factorSource: FactorSource) : this( + factorSources = factorSource.asList() + ) +} diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateway.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateway.kt index c3e8a765b..da511ee99 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateway.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateway.kt @@ -1,7 +1,6 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.Gateway -import com.radixdlt.sargon.Gateways import com.radixdlt.sargon.NetworkId import com.radixdlt.sargon.gatewayIsWellknown import com.radixdlt.sargon.gatewayMainnet @@ -18,7 +17,7 @@ val Gateway.Companion.stokenet: Gateway get() = gatewayStokenet() val Gateway.Companion.wellKnown: Gateways - get() = gatewayWellknownGateways() + get() = Gateways(gatewayWellknownGateways()) @Throws(SargonException::class) fun Gateway.Companion.init(url: String, networkId: NetworkId): Gateway = diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateways.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateways.kt index 8eece9dac..1a1fcc982 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateways.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Gateways.kt @@ -1,52 +1,18 @@ -@file:JvmName("GatewaysKt") - package com.radixdlt.sargon.extensions import com.radixdlt.sargon.Gateway -import com.radixdlt.sargon.Gateways import com.radixdlt.sargon.Url -import com.radixdlt.sargon.gatewaysElementCount -import com.radixdlt.sargon.gatewaysGetElements -import com.radixdlt.sargon.gatewaysGetGatewayById -import com.radixdlt.sargon.newGateways -import com.radixdlt.sargon.newGatewaysByAppending -import com.radixdlt.sargon.newGatewaysByUpdatingOrAppending -import com.radixdlt.sargon.newGatewaysByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newGatewaysRemovedById -import com.radixdlt.sargon.newGatewaysRemovedElement - -fun Gateways.Companion.init(vararg gateway: Gateway): Gateways = - init(gateway.asList()) - -fun Gateways.Companion.init(gateways: List): Gateways = - newGateways(gateways = gateways) - -operator fun Gateways.invoke() = gatewaysGetElements(gateways = this) - -operator fun Gateways.get(index: Int) = invoke().get(index = index) -operator fun Gateways.contains(element: Gateway) = invoke().contains(element = element) +class Gateways private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { -val Gateways.size: Int - get() = gatewaysElementCount(gateways = this).toInt() - -fun Gateways.append(gateway: Gateway): Gateways = - newGatewaysByAppending(gateway = gateway, to = this) - -fun Gateways.updateOrInsert(gateway: Gateway, index: Int): Gateways = - newGatewaysByUpdatingOrInsertingAtIndex( - gateway = gateway, - to = this, - index = index.toULong() + constructor(gateways: List) : this( + IdentifiedArrayImpl( + elements = gateways, + identifier = { it.url } + ) ) -fun Gateways.updateOrAppend(gateway: Gateway): Gateways = - newGatewaysByUpdatingOrAppending(gateway = gateway, to = this) - -fun Gateways.removeByUrl(url: Url): Gateways = - newGatewaysRemovedById(idOfGateway = url, from = this) - -fun Gateways.remove(gateway: Gateway): Gateways = - newGatewaysRemovedElement(gateway = gateway, from = this) - -fun Gateways.getBy(url: Url): Gateway? = gatewaysGetGatewayById(gateways = this, id = url) + constructor(vararg gateway: Gateway) : this(gateways = gateway.asList()) +} diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/IdentifiedArray.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/IdentifiedArray.kt new file mode 100644 index 000000000..efff20421 --- /dev/null +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/IdentifiedArray.kt @@ -0,0 +1,85 @@ +package com.radixdlt.sargon.extensions + +internal interface IdentifiedArray { + val size: Int + + fun asList(): List + + fun append(element: Element): IdentifiedArray + + fun updateOrAppend(element: Element): IdentifiedArray + + fun updateOrInsert(element: Element, index: Int): IdentifiedArray + + fun remove(element: Element): IdentifiedArray + + fun getBy(identifier: Identifier): Element? + + operator fun get(index: Int): Element + + fun removeBy(identifier: Identifier): IdentifiedArray +} + + +internal class IdentifiedArrayImpl( + elements: List, + private val identifier: (Element) -> Identifier +) : IdentifiedArray { + + private val inner: LinkedHashMap = + LinkedHashMap().apply { + elements.forEach { + this[identifier(it)] = it + } + } + + override val size: Int + get() = inner.size + + override fun asList(): List = inner + .values + .toList() + + override fun get(index: Int): Element = inner.values.elementAt(index) + + override fun append(element: Element) = apply { + val identifier = identifier(element) + if (!inner.contains(identifier)) { + inner[identifier] = element + } + } + + override fun updateOrAppend(element: Element) = apply { + inner[identifier(element)] = element + } + + override fun updateOrInsert( + element: Element, + index: Int + ): IdentifiedArray { + val id = identifier(element) + + return if (inner.contains(id)) { + inner[id] = element + + this + } else { + val list = inner.values.toMutableList() + list.add(index, element) + + IdentifiedArrayImpl(elements = list.toList(), identifier = identifier) + } + } + + override fun remove(element: Element) = apply { + val key = identifier(element) + + inner.remove(key) + } + + override fun getBy(identifier: Identifier) = inner[identifier] + + override fun removeBy(identifier: Identifier) = apply { + inner.remove(identifier) + } +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Networks.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Networks.kt deleted file mode 100644 index e6b5be8ad..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Networks.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.radixdlt.sargon.extensions - -import com.radixdlt.sargon.NetworkId -import com.radixdlt.sargon.Persona -import com.radixdlt.sargon.Personas -import com.radixdlt.sargon.ProfileNetwork -import com.radixdlt.sargon.ProfileNetworks -import com.radixdlt.sargon.newPersonasByUpdatingOrAppending -import com.radixdlt.sargon.newPersonasByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newProfileNetworks -import com.radixdlt.sargon.newProfileNetworksByAppending -import com.radixdlt.sargon.newProfileNetworksByUpdatingOrAppending -import com.radixdlt.sargon.newProfileNetworksByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newProfileNetworksRemovedById -import com.radixdlt.sargon.newProfileNetworksRemovedElement -import com.radixdlt.sargon.profileNetworksElementCount -import com.radixdlt.sargon.profileNetworksGetElements -import com.radixdlt.sargon.profileNetworksGetProfileNetworkById - -fun ProfileNetworks.Companion.init(vararg network: ProfileNetwork): ProfileNetworks = - init(networks = network.asList()) - -fun ProfileNetworks.Companion.init(networks: List): ProfileNetworks = - newProfileNetworks(profileNetworks = networks) - -operator fun ProfileNetworks.invoke() = profileNetworksGetElements(profileNetworks = this) - -operator fun ProfileNetworks.get(index: Int) = invoke().get(index = index) - -operator fun ProfileNetworks.contains(element: ProfileNetwork) = - invoke().contains(element = element) - -val ProfileNetworks.size: Int - get() = profileNetworksElementCount(profileNetworks = this).toInt() - -fun ProfileNetworks.append(network: ProfileNetwork): ProfileNetworks = - newProfileNetworksByAppending(profileNetwork = network, to = this) - -fun ProfileNetworks.updateOrInsert(network: ProfileNetwork, index: Int): ProfileNetworks = - newProfileNetworksByUpdatingOrInsertingAtIndex( - profileNetwork = network, - to = this, - index = index.toULong() - ) - -fun ProfileNetworks.updateOrAppend(network: ProfileNetwork): ProfileNetworks = - newProfileNetworksByUpdatingOrAppending(profileNetwork = network, to = this) - -@Throws(SargonException::class) -fun ProfileNetworks.removeByNetworkId(networkId: NetworkId): ProfileNetworks = - newProfileNetworksRemovedById(idOfProfileNetwork = networkId, from = this) - -@Throws(SargonException::class) -fun ProfileNetworks.remove(network: ProfileNetwork): ProfileNetworks = - newProfileNetworksRemovedElement(profileNetwork = network, from = this) - -fun ProfileNetworks.getBy(networkId: NetworkId): ProfileNetwork? = - profileNetworksGetProfileNetworkById(profileNetworks = this, id = networkId) \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/P2PLinks.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/P2PLinks.kt index 436430c5d..24a93dd89 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/P2PLinks.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/P2PLinks.kt @@ -2,49 +2,17 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.Hash import com.radixdlt.sargon.P2pLink -import com.radixdlt.sargon.P2pLinks -import com.radixdlt.sargon.newP2PLinks -import com.radixdlt.sargon.newP2PLinksByAppending -import com.radixdlt.sargon.newP2PLinksByUpdatingOrAppending -import com.radixdlt.sargon.newP2PLinksByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newP2PLinksRemovedById -import com.radixdlt.sargon.newP2PLinksRemovedElement -import com.radixdlt.sargon.p2PLinksElementCount -import com.radixdlt.sargon.p2PLinksGetElements -import com.radixdlt.sargon.p2PLinksGetP2PLinkById -fun P2pLinks.Companion.init(vararg p2pLink: P2pLink): P2pLinks = - init(p2pLinks = p2pLink.asList()) +class P2pLinks private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { -fun P2pLinks.Companion.init(p2pLinks: List): P2pLinks = newP2PLinks(p2PLinks = p2pLinks) - -operator fun P2pLinks.invoke() = p2PLinksGetElements(p2PLinks = this) - -operator fun P2pLinks.get(index: Int) = invoke().get(index = index) - -operator fun P2pLinks.contains(element: P2pLink) = invoke().contains(element = element) - -val P2pLinks.size: Int - get() = p2PLinksElementCount(p2PLinks = this).toInt() - -fun P2pLinks.append(p2pLink: P2pLink): P2pLinks = - newP2PLinksByAppending(p2PLink = p2pLink, to = this) - -fun P2pLinks.updateOrInsert(p2pLink: P2pLink, index: Int): P2pLinks = - newP2PLinksByUpdatingOrInsertingAtIndex( - p2PLink = p2pLink, - to = this, - index = index.toULong() + constructor(p2pLinks: List) : this( + IdentifiedArrayImpl( + elements = p2pLinks, + identifier = { it.id } + ) ) -fun P2pLinks.updateOrAppend(p2pLink: P2pLink): P2pLinks = - newP2PLinksByUpdatingOrAppending(p2PLink = p2pLink, to = this) - -fun P2pLinks.removeById(hash: Hash): P2pLinks = - newP2PLinksRemovedById(idOfP2PLink = hash, from = this) - -fun P2pLinks.remove(p2pLink: P2pLink): P2pLinks = - newP2PLinksRemovedElement(p2PLink = p2pLink, from = this) - -fun P2pLinks.getBy(hash: Hash): P2pLink? = - p2PLinksGetP2PLinkById(p2PLinks = this, id = hash) \ No newline at end of file + constructor(vararg p2pLink: P2pLink) : this(p2pLinks = p2pLink.asList()) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Personas.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Personas.kt index 4c9ceb8c8..b1f7aa87f 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Personas.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/Personas.kt @@ -1,53 +1,18 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.IdentityAddress -import com.radixdlt.sargon.P2pLink -import com.radixdlt.sargon.P2pLinks import com.radixdlt.sargon.Persona -import com.radixdlt.sargon.Personas -import com.radixdlt.sargon.newP2PLinksByUpdatingOrAppending -import com.radixdlt.sargon.newP2PLinksByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newPersonas -import com.radixdlt.sargon.newPersonasByAppending -import com.radixdlt.sargon.newPersonasByUpdatingOrAppending -import com.radixdlt.sargon.newPersonasByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newPersonasRemovedById -import com.radixdlt.sargon.newPersonasRemovedElement -import com.radixdlt.sargon.personasElementCount -import com.radixdlt.sargon.personasGetElements -import com.radixdlt.sargon.personasGetPersonaById -fun Personas.Companion.init(vararg persona: Persona): Personas = init(personas = persona.asList()) +class Personas private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { -fun Personas.Companion.init(personas: List): Personas = newPersonas(personas = personas) - -operator fun Personas.invoke() = personasGetElements(personas = this) - -operator fun Personas.get(index: Int) = invoke().get(index = index) - -operator fun Personas.contains(element: Persona) = invoke().contains(element = element) - -val Personas.size: Int - get() = personasElementCount(personas = this).toInt() - -fun Personas.append(persona: Persona): Personas = - newPersonasByAppending(persona = persona, to = this) - -fun Personas.updateOrInsert(persona: Persona, index: Int): Personas = - newPersonasByUpdatingOrInsertingAtIndex( - persona = persona, - to = this, - index = index.toULong() + constructor(personas: List) : this( + IdentifiedArrayImpl( + elements = personas, + identifier = { it.address } + ) ) -fun Personas.updateOrAppend(persona: Persona): Personas = - newPersonasByUpdatingOrAppending(persona = persona, to = this) - -fun Personas.removeByAddress(address: IdentityAddress): Personas = - newPersonasRemovedById(idOfPersona = address, from = this) - -fun Personas.remove(persona: Persona): Personas = - newPersonasRemovedElement(persona = persona, from = this) - -fun Personas.getBy(address: IdentityAddress): Persona? = - personasGetPersonaById(personas = this, id = address) \ No newline at end of file + constructor(vararg persona: Persona) : this(personas = persona.asList()) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ProfileEntity.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ProfileEntity.kt index cf64a1951..498cfa344 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ProfileEntity.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ProfileEntity.kt @@ -3,7 +3,6 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.Account import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.AddressOfAccountOrPersona -import com.radixdlt.sargon.EntityFlags import com.radixdlt.sargon.EntitySecurityState import com.radixdlt.sargon.IdentityAddress import com.radixdlt.sargon.NetworkId @@ -25,7 +24,7 @@ sealed interface ProfileEntity { override val securityState: EntitySecurityState get() = account.securityState override val flags: EntityFlags - get() = account.flags + get() = EntityFlags(account.flags) val accountAddress: AccountAddress get() = account.address @@ -41,7 +40,7 @@ sealed interface ProfileEntity { override val securityState: EntitySecurityState get() = persona.securityState override val flags: EntityFlags - get() = persona.flags + get() = EntityFlags(persona.flags) val identityAddress: IdentityAddress get() = persona.address diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ProfileNetworks.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ProfileNetworks.kt new file mode 100644 index 000000000..da6c1a6ce --- /dev/null +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ProfileNetworks.kt @@ -0,0 +1,18 @@ +package com.radixdlt.sargon.extensions + +import com.radixdlt.sargon.NetworkId +import com.radixdlt.sargon.ProfileNetwork + +class ProfileNetworks private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { + + constructor(networks: List) : this( + IdentifiedArrayImpl( + elements = networks, + identifier = { it.id } + ) + ) + + constructor(vararg network: ProfileNetwork) : this(networks = network.asList()) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ReferencesToAuthorizedPersonas.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ReferencesToAuthorizedPersonas.kt index ba10306e9..f03517dd6 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ReferencesToAuthorizedPersonas.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/ReferencesToAuthorizedPersonas.kt @@ -1,87 +1,20 @@ package com.radixdlt.sargon.extensions -import com.radixdlt.sargon.AccountAddress import com.radixdlt.sargon.AuthorizedPersonaSimple import com.radixdlt.sargon.IdentityAddress -import com.radixdlt.sargon.ReferencesToAuthorizedPersonas -import com.radixdlt.sargon.accountsElementCount -import com.radixdlt.sargon.accountsGetAccountById -import com.radixdlt.sargon.accountsGetElements -import com.radixdlt.sargon.newAccountsByAppending -import com.radixdlt.sargon.newAccountsByUpdatingOrAppending -import com.radixdlt.sargon.newAccountsByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newAccountsRemovedById -import com.radixdlt.sargon.newAccountsRemovedElement -import com.radixdlt.sargon.newReferencesToAuthorizedPersonas -import com.radixdlt.sargon.newReferencesToAuthorizedPersonasByAppending -import com.radixdlt.sargon.newReferencesToAuthorizedPersonasByUpdatingOrAppending -import com.radixdlt.sargon.newReferencesToAuthorizedPersonasByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newReferencesToAuthorizedPersonasRemovedById -import com.radixdlt.sargon.newReferencesToAuthorizedPersonasRemovedElement -import com.radixdlt.sargon.referencesToAuthorizedPersonasElementCount -import com.radixdlt.sargon.referencesToAuthorizedPersonasGetAuthorizedPersonaSimpleById -import com.radixdlt.sargon.referencesToAuthorizedPersonasGetElements -fun ReferencesToAuthorizedPersonas.Companion.init(vararg authorizedPersonaSimple: AuthorizedPersonaSimple): ReferencesToAuthorizedPersonas = - init(referencesToAuthorizedPersonas = authorizedPersonaSimple.asList()) - -fun ReferencesToAuthorizedPersonas.Companion.init(referencesToAuthorizedPersonas: List): ReferencesToAuthorizedPersonas = - newReferencesToAuthorizedPersonas(referencesToAuthorizedPersonas = referencesToAuthorizedPersonas) - -operator fun ReferencesToAuthorizedPersonas.invoke() = referencesToAuthorizedPersonasGetElements( - referencesToAuthorizedPersonas = this -) - -operator fun ReferencesToAuthorizedPersonas.get(index: Int) = invoke().get(index = index) - -operator fun ReferencesToAuthorizedPersonas.contains(element: AuthorizedPersonaSimple) = - invoke().contains(element = element) - -val ReferencesToAuthorizedPersonas.size: Int - get() = referencesToAuthorizedPersonasElementCount( - referencesToAuthorizedPersonas = this - ).toInt() - -fun ReferencesToAuthorizedPersonas.append( - authorizedPersonaSimple: AuthorizedPersonaSimple -): ReferencesToAuthorizedPersonas = newReferencesToAuthorizedPersonasByAppending( - authorizedPersonaSimple = authorizedPersonaSimple, - to = this -) - -fun ReferencesToAuthorizedPersonas.updateOrInsert( - authorizedPersonaSimple: AuthorizedPersonaSimple, - index: Int -): ReferencesToAuthorizedPersonas = newReferencesToAuthorizedPersonasByUpdatingOrInsertingAtIndex( - authorizedPersonaSimple = authorizedPersonaSimple, - to = this, - index = index.toULong() -) - -fun ReferencesToAuthorizedPersonas.updateOrAppend( - authorizedPersonaSimple: AuthorizedPersonaSimple -): ReferencesToAuthorizedPersonas = newReferencesToAuthorizedPersonasByUpdatingOrAppending( - authorizedPersonaSimple = authorizedPersonaSimple, - to = this -) - -fun ReferencesToAuthorizedPersonas.removeByAddress( - address: IdentityAddress -): ReferencesToAuthorizedPersonas = newReferencesToAuthorizedPersonasRemovedById( - idOfAuthorizedPersonaSimple = address, - from = this -) - -fun ReferencesToAuthorizedPersonas.remove( - authorizedPersonaSimple: AuthorizedPersonaSimple -): ReferencesToAuthorizedPersonas = newReferencesToAuthorizedPersonasRemovedElement( - authorizedPersonaSimple = authorizedPersonaSimple, - from = this -) - -fun ReferencesToAuthorizedPersonas.getBy( - address: IdentityAddress -): AuthorizedPersonaSimple? = referencesToAuthorizedPersonasGetAuthorizedPersonaSimpleById( - referencesToAuthorizedPersonas = this, - id = address -) \ No newline at end of file +class ReferencesToAuthorizedPersonas private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { + + constructor(authorizedPersonasSimple: List) : this( + IdentifiedArrayImpl( + elements = authorizedPersonasSimple, + identifier = { it.identityAddress } + ) + ) + + constructor(vararg authorizedPersonaSimple: AuthorizedPersonaSimple) : this( + authorizedPersonasSimple = authorizedPersonaSimple.asList() + ) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SavedGateways.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SavedGateways.kt index 419c3e1f8..34c7d02c4 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SavedGateways.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SavedGateways.kt @@ -1,7 +1,6 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.Gateway -import com.radixdlt.sargon.Gateways import com.radixdlt.sargon.SavedGateways import com.radixdlt.sargon.newSavedGateways import com.radixdlt.sargon.newSavedGatewaysChangingCurrent diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SupportedCurves.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SupportedCurves.kt index 5495bf6d1..18aad8799 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SupportedCurves.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SupportedCurves.kt @@ -1,44 +1,17 @@ package com.radixdlt.sargon.extensions import com.radixdlt.sargon.Slip10Curve -import com.radixdlt.sargon.SupportedCurves -import com.radixdlt.sargon.newSupportedCurves -import com.radixdlt.sargon.newSupportedCurvesByAppending -import com.radixdlt.sargon.newSupportedCurvesByUpdatingOrAppending -import com.radixdlt.sargon.newSupportedCurvesByUpdatingOrInsertingAtIndex -import com.radixdlt.sargon.newSupportedCurvesRemovedElement -import com.radixdlt.sargon.supportedCurvesElementCount -import com.radixdlt.sargon.supportedCurvesGetElements -fun SupportedCurves.Companion.init(vararg curve: Slip10Curve): SupportedCurves = - init(curves = curve.asList()) +class SupportedCurves private constructor( + array: IdentifiedArray +) : IdentifiedArray by array { -fun SupportedCurves.Companion.init(curves: List): SupportedCurves = - newSupportedCurves(supportedCurves = curves) + constructor(curves: List) : this( + IdentifiedArrayImpl( + elements = curves, + identifier = { it } + ) + ) -operator fun SupportedCurves.invoke() = supportedCurvesGetElements(supportedCurves = this) - -operator fun SupportedCurves.get(index: Int) = invoke().get(index = index) - -operator fun SupportedCurves.contains(element: Slip10Curve) = invoke().contains(element = element) - -val SupportedCurves.size: Int - get() = supportedCurvesElementCount(supportedCurves = this).toInt() - -fun SupportedCurves.append(curve: Slip10Curve): SupportedCurves = - newSupportedCurvesByAppending(sLIP10Curve = curve, to = this) - -fun SupportedCurves.updateOrInsert( - curve: Slip10Curve, - index: Int -): SupportedCurves = newSupportedCurvesByUpdatingOrInsertingAtIndex( - sLIP10Curve = curve, - to = this, - index = index.toULong() -) - -fun SupportedCurves.updateOrAppend(curve: Slip10Curve): SupportedCurves = - newSupportedCurvesByUpdatingOrAppending(sLIP10Curve = curve, to = this) - -fun SupportedCurves.remove(curve: Slip10Curve): SupportedCurves = - newSupportedCurvesRemovedElement(sLIP10Curve = curve, from = this) \ No newline at end of file + constructor(vararg curve: Slip10Curve) : this(curves = curve.asList()) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AccountsSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AccountsSample.kt deleted file mode 100644 index 71d26bd30..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AccountsSample.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.Account -import com.radixdlt.sargon.Accounts -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.init - -@UsesSampleValues -val Accounts.Companion.sampleMainnet: Sample - get() = object : Sample { - override fun invoke(): Accounts = Accounts.init( - listOf( - Account.sampleMainnet.alice, - Account.sampleMainnet.bob - ) - ) - - override fun other(): Accounts = Accounts.init( - listOf(Account.sampleMainnet.carol) - ) - } - -@UsesSampleValues -val Accounts.Companion.sampleStokenet: Sample - get() = object : Sample { - override fun invoke(): Accounts = Accounts.init( - listOf( - Account.sampleStokenet.nadia, - Account.sampleStokenet.olivia - ) - ) - - override fun other(): Accounts = Accounts.init( - listOf(Account.sampleStokenet.paige) - ) - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AssetsExceptionListSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AssetsExceptionListSample.kt deleted file mode 100644 index 978a05093..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AssetsExceptionListSample.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.AssetsExceptionList -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.newAssetsExceptionListSample -import com.radixdlt.sargon.newAssetsExceptionListSampleOther - -@UsesSampleValues -val AssetsExceptionList.Companion.sample: Sample - get() = object : Sample { - override fun invoke(): AssetsExceptionList = newAssetsExceptionListSample() - - override fun other(): AssetsExceptionList = newAssetsExceptionListSampleOther() - - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AuthorisedDappsSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AuthorisedDappsSample.kt deleted file mode 100644 index c1529c743..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/AuthorisedDappsSample.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.AuthorizedDapp -import com.radixdlt.sargon.AuthorizedDapps -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.init - -@UsesSampleValues -val AuthorizedDapps.Companion.sampleMainnet: Sample - get() = object : Sample { - override fun invoke(): AuthorizedDapps = AuthorizedDapps.init( - listOf(AuthorizedDapp.sampleMainnet.dashboard, AuthorizedDapp.sampleMainnet.gumballClub) - ) - - override fun other(): AuthorizedDapps = AuthorizedDapps.init( - AuthorizedDapp.sampleMainnet.gumballClub - ) - - } - -@UsesSampleValues -val AuthorizedDapps.Companion.sampleStokenet: Sample - get() = object : Sample { - override fun invoke(): AuthorizedDapps = AuthorizedDapps.init( - listOf(AuthorizedDapp.sampleStokenet.devConsole, AuthorizedDapp.sampleStokenet.sandbox) - ) - - override fun other(): AuthorizedDapps = AuthorizedDapps.init( - AuthorizedDapp.sampleStokenet.sandbox - ) - - } diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/DepositorsAllowListSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/DepositorsAllowListSample.kt deleted file mode 100644 index fbdd1f113..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/DepositorsAllowListSample.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.DepositorsAllowList -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.newDepositorsAllowListSample -import com.radixdlt.sargon.newDepositorsAllowListSampleOther - -@UsesSampleValues -val DepositorsAllowList.Companion.sample: Sample - get() = object : Sample { - override fun invoke(): DepositorsAllowList = newDepositorsAllowListSample() - - override fun other(): DepositorsAllowList = newDepositorsAllowListSampleOther() - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/EntityFlagSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/EntityFlagSample.kt new file mode 100644 index 000000000..76e2fb08a --- /dev/null +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/EntityFlagSample.kt @@ -0,0 +1,13 @@ +package com.radixdlt.sargon.samples + +import com.radixdlt.sargon.EntityFlag +import com.radixdlt.sargon.annotation.UsesSampleValues + +@UsesSampleValues +val EntityFlag.Companion.sample: Sample + get() = object: Sample { + override fun invoke(): EntityFlag = EntityFlag.DELETED_BY_USER + + override fun other(): EntityFlag = EntityFlag.PLACEHOLDER_SAMPLE_VALUE_FLAG + + } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/EntityFlagsSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/EntityFlagsSample.kt deleted file mode 100644 index 3f441040b..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/EntityFlagsSample.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.EntityFlag -import com.radixdlt.sargon.EntityFlags -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.init - -@UsesSampleValues -val EntityFlags.Companion.sample: Sample - get() = object: Sample { - override fun invoke(): EntityFlags = EntityFlags.init(EntityFlag.DELETED_BY_USER) - - override fun other(): EntityFlags = EntityFlags.init( - EntityFlag.DELETED_BY_USER, - EntityFlag.PLACEHOLDER_SAMPLE_VALUE_FLAG - ) - - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/FactorSourceSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/FactorSourceSample.kt index 4f7f017de..81e2d3129 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/FactorSourceSample.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/FactorSourceSample.kt @@ -1,12 +1,9 @@ package com.radixdlt.sargon.samples import com.radixdlt.sargon.FactorSource -import com.radixdlt.sargon.FactorSources import com.radixdlt.sargon.annotation.UsesSampleValues import com.radixdlt.sargon.newFactorSourceSample import com.radixdlt.sargon.newFactorSourceSampleOther -import com.radixdlt.sargon.newFactorSourcesSample -import com.radixdlt.sargon.newFactorSourcesSampleOther @UsesSampleValues val FactorSource.Companion.sample: Sample diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/FactorSourcesSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/FactorSourcesSample.kt deleted file mode 100644 index 58b6257e1..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/FactorSourcesSample.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.FactorSource -import com.radixdlt.sargon.FactorSources -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.init - -@UsesSampleValues -val FactorSources.Companion.sample: Sample - get() = object : Sample { - override fun invoke(): FactorSources = FactorSources.init( - listOf(FactorSource.sample(), FactorSource.sample.other()) - ) - - override fun other(): FactorSources = FactorSources.init( - FactorSource.sample.other() - ) - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/OtherGatewaysSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/OtherGatewaysSample.kt deleted file mode 100644 index d4e86c7ae..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/OtherGatewaysSample.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.Gateways -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.newGatewaysSample -import com.radixdlt.sargon.newGatewaysSampleOther - -@UsesSampleValues -val Gateways.Companion.sample: Sample - get() = object : Sample { - override fun invoke(): Gateways = newGatewaysSample() - - override fun other(): Gateways = newGatewaysSampleOther() - } diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/P2PLinksSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/P2PLinksSample.kt deleted file mode 100644 index df309e90f..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/P2PLinksSample.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.P2pLink -import com.radixdlt.sargon.P2pLinks -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.init - -@UsesSampleValues -val P2pLinks.Companion.sample: Sample - get() = object : Sample { - - override fun invoke(): P2pLinks = P2pLinks.init( - P2pLink.sample(), - P2pLink.sample.other(), - ) - - override fun other(): P2pLinks = P2pLinks.init(P2pLink.sample()) - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/PersonasSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/PersonasSample.kt deleted file mode 100644 index 69ea04ddb..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/PersonasSample.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.Persona -import com.radixdlt.sargon.Personas -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.init - -@UsesSampleValues -val Personas.Companion.sampleMainnet: Sample - get() = object : Sample { - override fun invoke(): Personas = Personas.init( - listOf( - Persona.sampleMainnet.batman, - Persona.sampleMainnet.satoshi - ) - ) - - override fun other(): Personas = Personas.init(Persona.sampleMainnet.satoshi) - - } - -@UsesSampleValues -val Personas.Companion.sampleStokenet: Sample - get() = object : Sample { - override fun invoke(): Personas = Personas.init( - listOf( - Persona.sampleStokenet.leiaSkywalker, - Persona.sampleStokenet.hermione - ) - ) - - override fun other(): Personas = Personas.init(Persona.sampleStokenet.hermione) - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ProfileNetworkSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ProfileNetworkSample.kt index 79152d87e..9e44df781 100644 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ProfileNetworkSample.kt +++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ProfileNetworkSample.kt @@ -1,27 +1,42 @@ package com.radixdlt.sargon.samples -import com.radixdlt.sargon.Accounts -import com.radixdlt.sargon.AuthorizedDapps +import com.radixdlt.sargon.Account +import com.radixdlt.sargon.AuthorizedDapp import com.radixdlt.sargon.NetworkId -import com.radixdlt.sargon.Personas +import com.radixdlt.sargon.Persona import com.radixdlt.sargon.ProfileNetwork import com.radixdlt.sargon.annotation.UsesSampleValues +import com.radixdlt.sargon.extensions.Accounts +import com.radixdlt.sargon.extensions.AuthorizedDapps +import com.radixdlt.sargon.extensions.Personas @UsesSampleValues val ProfileNetwork.Companion.sampleMainnet: Sample get() = object : Sample { override fun invoke(): ProfileNetwork = ProfileNetwork( id = NetworkId.MAINNET, - accounts = Accounts.sampleMainnet(), - personas = Personas.sampleMainnet(), - authorizedDapps = AuthorizedDapps.sampleMainnet() + accounts = Accounts( + Account.sampleMainnet(), + ).asList(), + personas = Personas( + Persona.sampleMainnet() + ).asList(), + authorizedDapps = AuthorizedDapps( + AuthorizedDapp.sampleMainnet() + ).asList() ) override fun other(): ProfileNetwork = ProfileNetwork( id = NetworkId.MAINNET, - accounts = Accounts.sampleMainnet.other(), - personas = Personas.sampleMainnet.other(), - authorizedDapps = AuthorizedDapps.sampleMainnet.other() + accounts = Accounts( + Account.sampleMainnet.other(), + ).asList(), + personas = Personas( + Persona.sampleMainnet.other() + ).asList(), + authorizedDapps = AuthorizedDapps( + AuthorizedDapp.sampleMainnet.other() + ).asList() ) } @@ -30,15 +45,27 @@ val ProfileNetwork.Companion.sampleStokenet: Sample get() = object : Sample { override fun invoke(): ProfileNetwork = ProfileNetwork( id = NetworkId.STOKENET, - accounts = Accounts.sampleStokenet(), - personas = Personas.sampleStokenet(), - authorizedDapps = AuthorizedDapps.sampleStokenet() + accounts = Accounts( + Account.sampleStokenet(), + ).asList(), + personas = Personas( + Persona.sampleStokenet() + ).asList(), + authorizedDapps = AuthorizedDapps( + AuthorizedDapp.sampleStokenet() + ).asList() ) override fun other(): ProfileNetwork = ProfileNetwork( id = NetworkId.STOKENET, - accounts = Accounts.sampleStokenet.other(), - personas = Personas.sampleStokenet.other(), - authorizedDapps = AuthorizedDapps.sampleStokenet.other() + accounts = Accounts( + Account.sampleStokenet.other(), + ).asList(), + personas = Personas( + Persona.sampleStokenet.other() + ).asList(), + authorizedDapps = AuthorizedDapps( + AuthorizedDapp.sampleStokenet.other() + ).asList() ) - } + } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ProfileNetworksSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ProfileNetworksSample.kt deleted file mode 100644 index fa355c791..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ProfileNetworksSample.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.ProfileNetwork -import com.radixdlt.sargon.ProfileNetworks -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.extensions.init - -@UsesSampleValues -val ProfileNetworks.Companion.sampleMainnet: Sample - get() = object : Sample { - override fun invoke(): ProfileNetworks = ProfileNetworks.init( - ProfileNetwork.sampleMainnet(), ProfileNetwork.sampleMainnet.other() - ) - - override fun other(): ProfileNetworks = ProfileNetworks.init( - ProfileNetwork.sampleMainnet() - ) - } - -@UsesSampleValues -val ProfileNetworks.Companion.sampleStokenet: Sample - get() = object : Sample { - override fun invoke(): ProfileNetworks = ProfileNetworks.init( - ProfileNetwork.sampleStokenet(), ProfileNetwork.sampleStokenet.other() - ) - - override fun other(): ProfileNetworks = ProfileNetworks.init( - ProfileNetwork.sampleStokenet() - ) - } diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ReferencesToAuthorizedPersonasSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ReferencesToAuthorizedPersonasSample.kt deleted file mode 100644 index e0d7273ef..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/ReferencesToAuthorizedPersonasSample.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.ReferencesToAuthorizedPersonas -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.newReferencesToAuthorizedPersonasSample -import com.radixdlt.sargon.newReferencesToAuthorizedPersonasSampleOther - -@UsesSampleValues -val ReferencesToAuthorizedPersonas.Companion.sample: Sample - get() = object : Sample { - override fun invoke(): ReferencesToAuthorizedPersonas = newReferencesToAuthorizedPersonasSample() - - override fun other(): ReferencesToAuthorizedPersonas = - newReferencesToAuthorizedPersonasSampleOther() - - } \ No newline at end of file diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/SupportedCurvesSample.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/SupportedCurvesSample.kt deleted file mode 100644 index 7d41f31cd..000000000 --- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/samples/SupportedCurvesSample.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.radixdlt.sargon.samples - -import com.radixdlt.sargon.SupportedCurves -import com.radixdlt.sargon.annotation.UsesSampleValues -import com.radixdlt.sargon.newSupportedCurvesSample -import com.radixdlt.sargon.newSupportedCurvesSampleOther - -@UsesSampleValues -val SupportedCurves.Companion.sample: Sample - get() = object : Sample { - override fun invoke(): SupportedCurves = newSupportedCurvesSample() - - override fun other(): SupportedCurves = newSupportedCurvesSampleOther() - - } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AccountsTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AccountsTest.kt index 423810649..be93b740f 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AccountsTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AccountsTest.kt @@ -1,56 +1,16 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByAddress -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample +import com.radixdlt.sargon.extensions.Accounts import com.radixdlt.sargon.samples.sampleMainnet -import com.radixdlt.sargon.samples.sampleStokenet -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -class AccountsTest: SampleTestable { - override val samples: List> - get() = listOf(Accounts.sampleMainnet, Accounts.sampleStokenet) +internal class AccountsTest: IdentifiedArrayTest() { - @Test - fun testListMethods() { - val sample = Account.sampleMainnet() - val sampleOther = Account.sampleMainnet.other() + override fun element(): Account = Account.sampleMainnet() - var list = Accounts.init(sample) + override fun elementWithDifferentId(): Account = Account.sampleMainnet.other() - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) + override fun identifier(element: Account): AccountAddress = element.address - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) + override fun init(element: Account): Accounts = Accounts(element) - list = list.remove(sampleOther) - assertFalse(sampleOther in list) - assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[0]) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - list = list.remove(sampleOther) - - assertEquals(sample, list.getBy(sample.address)) - assertTrue(list.removeByAddress(sample.address).size == 0) - } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AppPreferencesTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AppPreferencesTest.kt index 324ea89b6..edd694710 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AppPreferencesTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AppPreferencesTest.kt @@ -22,7 +22,7 @@ class AppPreferencesTest: SampleTestable { fiatCurrencyPriceTarget = FiatCurrency.USD ), gateways = SavedGateways.default, - p2pLinks = P2pLinks.init(), + p2pLinks = listOf(), security = Security( isCloudProfileSyncEnabled = true, isDeveloperModeEnabled = false, diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AssetsExceptionListTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AssetsExceptionListTest.kt index f81d15445..36935b5a3 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AssetsExceptionListTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AssetsExceptionListTest.kt @@ -1,53 +1,16 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByAddress -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample +import com.radixdlt.sargon.extensions.AssetsExceptionList import com.radixdlt.sargon.samples.sample -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test -class AssetsExceptionListTest : SampleTestable { - override val samples: List> - get() = listOf(AssetsExceptionList.sample) +internal class AssetsExceptionListTest : + IdentifiedArrayTest() { + override fun element(): AssetException = AssetException.sample() - @Test - fun testListMethods() { - val sample = AssetException.sample() - val sampleOther = AssetException.sample.other() + override fun elementWithDifferentId(): AssetException = AssetException.sample.other() - var list = AssetsExceptionList.init(sample) + override fun identifier(element: AssetException): ResourceAddress = element.address - Assertions.assertTrue(sample in list) - Assertions.assertEquals(1, list.size) - Assertions.assertEquals(sample, list[0]) + override fun init(element: AssetException): AssetsExceptionList = AssetsExceptionList(element) - list = list.append(sampleOther) - Assertions.assertTrue(sampleOther in list) - Assertions.assertEquals(2, list.size) - Assertions.assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - Assertions.assertFalse(sampleOther in list) - Assertions.assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - Assertions.assertEquals(sampleOther, list()[0]) - Assertions.assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - Assertions.assertTrue(list.size == 2) - list = list.remove(sampleOther) - - Assertions.assertEquals(sample, list.getBy(sample.address)) - Assertions.assertTrue(list.removeByAddress(sample.address).size == 0) - } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AuthorizedDappsTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AuthorizedDappsTest.kt index 8a6adc97f..a1f7306bb 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AuthorizedDappsTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/AuthorizedDappsTest.kt @@ -1,56 +1,15 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByAddress -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample +import com.radixdlt.sargon.extensions.AuthorizedDapps import com.radixdlt.sargon.samples.sampleMainnet -import com.radixdlt.sargon.samples.sampleStokenet -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -class AuthorizedDappsTest: SampleTestable { - override val samples: List> - get() = listOf(AuthorizedDapps.sampleMainnet, AuthorizedDapps.sampleStokenet) +internal class AuthorizedDappsTest: IdentifiedArrayTest() { + override fun element(): AuthorizedDapp = AuthorizedDapp.sampleMainnet() - @Test - fun testListMethods() { - val sample = AuthorizedDapp.sampleMainnet() - val sampleOther = AuthorizedDapp.sampleMainnet.other() + override fun elementWithDifferentId(): AuthorizedDapp = AuthorizedDapp.sampleMainnet.other() - var list = AuthorizedDapps.init(sample) + override fun identifier(element: AuthorizedDapp): AccountAddress = element.dappDefinitionAddress - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) + override fun init(element: AuthorizedDapp): AuthorizedDapps = AuthorizedDapps(element) - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - Assertions.assertFalse(sampleOther in list) - assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[0]) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - list = list.remove(sampleOther) - - assertEquals(sample, list.getBy(sample.dappDefinitionAddress)) - assertTrue(list.removeByAddress(sample.dappDefinitionAddress).size == 0) - } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/DepositorsAllowListTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/DepositorsAllowListTest.kt index d24c1fd19..e81eb1c65 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/DepositorsAllowListTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/DepositorsAllowListTest.kt @@ -1,53 +1,17 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByAddress -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample +import com.radixdlt.sargon.extensions.DepositorsAllowList import com.radixdlt.sargon.samples.sample -import com.radixdlt.sargon.samples.sampleMainnet -import com.radixdlt.sargon.samples.sampleStokenet -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -class DepositorsAllowListTest: SampleTestable { - override val samples: List> - get() = listOf(DepositorsAllowList.sample) +internal class DepositorsAllowListTest : + IdentifiedArrayTest() { + override fun element(): ResourceOrNonFungible = ResourceOrNonFungible.sample() - @Test - fun testListMethods() { - val sample = ResourceOrNonFungible.sample() - val sampleOther = ResourceOrNonFungible.sample.other() + override fun elementWithDifferentId(): ResourceOrNonFungible = ResourceOrNonFungible.sample.other() - var list = DepositorsAllowList.init(sample) + override fun identifier(element: ResourceOrNonFungible): ResourceOrNonFungible = element - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) + override fun init(element: ResourceOrNonFungible): DepositorsAllowList = + DepositorsAllowList(element) - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - assertFalse(sampleOther in list) - assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list.getBy(sampleOther)) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/EntityFlagsTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/EntityFlagsTest.kt index 736df94ce..06ad4139c 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/EntityFlagsTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/EntityFlagsTest.kt @@ -1,50 +1,15 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample +import com.radixdlt.sargon.extensions.EntityFlags import com.radixdlt.sargon.samples.sample -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -class EntityFlagsTest: SampleTestable { - override val samples: List> - get() = listOf(EntityFlags.sample) +internal class EntityFlagsTest: IdentifiedArrayTest() { + override fun element(): EntityFlag = EntityFlag.sample() - @Test - fun testListMethods() { - val sample = EntityFlag.DELETED_BY_USER - val sampleOther = EntityFlag.PLACEHOLDER_SAMPLE_VALUE_FLAG + override fun elementWithDifferentId(): EntityFlag = EntityFlag.sample.other() - var list = EntityFlags.init(sample) + override fun identifier(element: EntityFlag): EntityFlag = element - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) + override fun init(element: EntityFlag): EntityFlags = EntityFlags(element) - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list.get(sampleOther)) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[1]) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - list = list.remove(sampleOther) - - list = list.remove(sampleOther) - assertFalse(sampleOther in list) - assertEquals(1, list.size) - } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourcesTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourcesTest.kt index 80d8bc8d5..1099ff3a1 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourcesTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/FactorSourcesTest.kt @@ -1,69 +1,24 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append +import com.radixdlt.sargon.extensions.FactorSources +import com.radixdlt.sargon.extensions.SupportedCurves import com.radixdlt.sargon.extensions.asGeneral -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get import com.radixdlt.sargon.extensions.id import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke import com.radixdlt.sargon.extensions.randomBagOfBytes -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeById -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample import com.radixdlt.sargon.samples.sample -import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -class FactorSourcesTest : SampleTestable { +internal class FactorSourcesTest : IdentifiedArrayTest() { - override val samples: List> - get() = listOf(FactorSources.sample) + override fun element(): FactorSource = FactorSource.sample() - @Test - fun testListMethods() { - val sample = FactorSource.sample() - assertEquals(sample.id, FactorSource.sample().id) - val sampleOther = FactorSource.sample.other() - - var list = FactorSources.init(sample) - - Assertions.assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) - - list = list.append(sampleOther) - Assertions.assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - Assertions.assertFalse(sampleOther in list) - assertEquals(1, list.size) + override fun elementWithDifferentId(): FactorSource = FactorSource.sample.other() - list = list.append(sampleOther) - assertEquals(sampleOther, list.get(sampleOther.id)) - list = list.removeById(sampleOther.id) - Assertions.assertTrue(list.size == 1) + override fun identifier(element: FactorSource): FactorSourceId = element.id - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[0]) - Assertions.assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - Assertions.assertTrue(list.size == 2) - } - - @Test - fun testEmptyFactorSourcesFails() { - assertThrows { - FactorSources.init() - } - } + override fun init(element: FactorSource): FactorSources = FactorSources(element) @Test fun testDeviceFactorSourceAsGeneral() { @@ -74,7 +29,7 @@ class FactorSourcesTest : SampleTestable { ), common = FactorSourceCommon( cryptoParameters = FactorSourceCryptoParameters( - supportedCurves = SupportedCurves.init(Slip10Curve.CURVE25519), + supportedCurves = SupportedCurves(Slip10Curve.CURVE25519).asList(), supportedDerivationPathSchemes = listOf(DerivationPathScheme.CAP26) ), addedOn = Timestamp.now(), @@ -103,7 +58,7 @@ class FactorSourcesTest : SampleTestable { ), common = FactorSourceCommon( cryptoParameters = FactorSourceCryptoParameters( - supportedCurves = SupportedCurves.init(Slip10Curve.CURVE25519), + supportedCurves = SupportedCurves(Slip10Curve.CURVE25519).asList(), supportedDerivationPathSchemes = listOf(DerivationPathScheme.CAP26) ), addedOn = Timestamp.now(), diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewayTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewayTest.kt index 1e46b6b86..320a6eb7d 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewayTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewayTest.kt @@ -2,7 +2,6 @@ package com.radixdlt.sargon import com.radixdlt.sargon.extensions.forNetwork import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke import com.radixdlt.sargon.extensions.isWellKnown import com.radixdlt.sargon.extensions.mainnet import com.radixdlt.sargon.extensions.stokenet @@ -23,7 +22,7 @@ class GatewayTest { assertEquals( listOf(Gateway.mainnet, Gateway.stokenet), - Gateway.wellKnown() + Gateway.wellKnown.asList() ) } diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewaysTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewaysTest.kt index 59d5e0c15..862a9ee15 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewaysTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/GatewaysTest.kt @@ -1,57 +1,44 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.mainnet -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByUrl -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.stokenet -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample -import com.radixdlt.sargon.samples.sample +import com.radixdlt.sargon.extensions.Gateways +import com.radixdlt.sargon.samples.sampleMainnet +import com.radixdlt.sargon.samples.sampleStokenet +import okhttp3.HttpUrl.Companion.toHttpUrl import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test -class GatewaysTest: SampleTestable { - override val samples: List> - get() = listOf(Gateways.sample) +internal class GatewaysTest: IdentifiedArrayTest() { + override fun element(): Gateway = Gateway.sampleMainnet() + + override fun elementWithDifferentId(): Gateway = Gateway.sampleStokenet() + + override fun identifier(element: Gateway): Url = element.url + + override fun init(element: Gateway): Gateways = Gateways(element) @Test - fun testListMethods() { - val sample = Gateway.mainnet - val sampleOther = Gateway.stokenet - - var list = Gateways.init(sample) - - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) - - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - assertFalse(sampleOther in list) - assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[0]) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - list = list.remove(sampleOther) - - assertEquals(sample, list.getBy(sample.url)) - assertTrue(list.removeByUrl(sample.url).size == 0) + fun similarUrlsTest() { + val mainnet = Gateway( + network = NetworkDefinition( + logicalName = "mainnet", + id = NetworkId.MAINNET, + displayDescription = "mainnet" + ), + url = "https://mainnet.radixdlt.com".toHttpUrl() + ) + + val mainnetWithSlash = mainnet.copy( + url = "https://mainnet.radixdlt.com/".toHttpUrl() + ) + + val otherMainnet = mainnet.copy( + url = "https://mainnet-other.radixdlt.com/".toHttpUrl() + ) + + assertEquals( + listOf(mainnet, otherMainnet), + Gateways(mainnet, mainnetWithSlash, otherMainnet).asList() + ) } + } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/IdentifiedArrayTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/IdentifiedArrayTest.kt new file mode 100644 index 000000000..fb520ca5b --- /dev/null +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/IdentifiedArrayTest.kt @@ -0,0 +1,50 @@ +package com.radixdlt.sargon + +import com.radixdlt.sargon.extensions.IdentifiedArray +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +internal abstract class IdentifiedArrayTest where A : IdentifiedArray { + + abstract fun element(): Element + + abstract fun elementWithDifferentId(): Element + + abstract fun init(element: Element): A + + abstract fun identifier(element: Element): Identifier + + @Test + fun testOperations() { + val element = element() + val elementWithDifferentId = elementWithDifferentId() + + var collection: IdentifiedArray = init(element) + + assertEquals(1, collection.size) + assertEquals(element, collection[0]) + + collection = collection.append(elementWithDifferentId) + assertEquals(2, collection.size) + assertEquals(elementWithDifferentId, collection[1]) + + collection = collection.remove(elementWithDifferentId) + assertEquals(1, collection.size) + + collection = collection.updateOrInsert(elementWithDifferentId, 1) + assertEquals(elementWithDifferentId, collection[1]) + assertTrue(collection.size == 2) + + collection = collection.updateOrInsert(elementWithDifferentId, 0) + assertEquals(elementWithDifferentId, collection[1]) // The item remains in previous position + assertTrue(collection.size == 2) + + collection = collection.updateOrAppend(elementWithDifferentId) + assertTrue(collection.size == 2) + collection = collection.remove(elementWithDifferentId) + + assertEquals(element, collection.getBy(identifier(element))) + assertTrue(collection.removeBy(identifier(element)).size == 0) + } +} \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/NetworksTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/NetworksTest.kt deleted file mode 100644 index 2946b2f13..000000000 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/NetworksTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.radixdlt.sargon - -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByNetworkId -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.sampleMainnet -import com.radixdlt.sargon.samples.sampleStokenet -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - -class NetworksTest { - - @Test - fun testListMethods() { - val sample = ProfileNetwork.sampleMainnet() - val sampleOther = ProfileNetwork.sampleStokenet() - - var list = ProfileNetworks.init(sample) - - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) - - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) - - list = list.remove(list.getBy(sampleOther.id)!!) - assertFalse(sampleOther in list) - assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[0]) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - list = list.remove(sampleOther) - - list = list.append(sampleOther) - list = list.removeByNetworkId(sampleOther.id) - assertFalse(sampleOther in list) - assertEquals(1, list.size) - } -} \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/OnLedgerSettingsTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/OnLedgerSettingsTest.kt index 60cfb2d17..e31cb82e3 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/OnLedgerSettingsTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/OnLedgerSettingsTest.kt @@ -3,8 +3,6 @@ package com.radixdlt.sargon import com.radixdlt.sargon.extensions.default import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import com.radixdlt.sargon.newAssetsExceptionList -import com.radixdlt.sargon.newDepositorsAllowList class OnLedgerSettingsTest { @@ -13,8 +11,8 @@ class OnLedgerSettingsTest { assertEquals( OnLedgerSettings(thirdPartyDeposits = ThirdPartyDeposits( depositRule = DepositRule.ACCEPT_ALL, - assetsExceptionList = newAssetsExceptionList(assetsExceptionList = emptyList()), - depositorsAllowList = newDepositorsAllowList(depositorsAllowList = emptyList()) + assetsExceptionList = emptyList(), + depositorsAllowList = emptyList() )), OnLedgerSettings.default() ) diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/P2PLinksTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/P2PLinksTest.kt index c1ce5aa76..58abfdece 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/P2PLinksTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/P2PLinksTest.kt @@ -1,53 +1,15 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy +import com.radixdlt.sargon.extensions.P2pLinks import com.radixdlt.sargon.extensions.id -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeById -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert import com.radixdlt.sargon.samples.sample -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -class P2PLinksTest { +internal class P2PLinksTest: IdentifiedArrayTest() { + override fun element(): P2pLink = P2pLink.sample() - @Test - fun testListMethods() { - val sample = P2pLink.sample() - val sampleOther = P2pLink.sample.other() + override fun elementWithDifferentId(): P2pLink = P2pLink.sample.other() - var list = P2pLinks.init(sample) + override fun identifier(element: P2pLink): Hash = element.id - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) - - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - assertFalse(sampleOther in list) - assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[0]) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - list = list.remove(sampleOther) - - assertEquals(sample, list.getBy(sample.id)) - assertTrue(list.removeById(sample.id).size == 0) - } + override fun init(element: P2pLink): P2pLinks = P2pLinks(element) } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/PersonasTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/PersonasTest.kt index 4558428c5..acc9587b1 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/PersonasTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/PersonasTest.kt @@ -1,58 +1,15 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.id -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByAddress -import com.radixdlt.sargon.extensions.removeById -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample +import com.radixdlt.sargon.extensions.Personas import com.radixdlt.sargon.samples.sampleMainnet -import com.radixdlt.sargon.samples.sampleStokenet -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -class PersonasTest: SampleTestable { - override val samples: List> - get() = listOf(Personas.sampleMainnet, Personas.sampleStokenet) +internal class PersonasTest: IdentifiedArrayTest() { + override fun element(): Persona = Persona.sampleMainnet() - @Test - fun testListMethods() { - val sample = Persona.sampleMainnet() - val sampleOther = Persona.sampleMainnet.other() + override fun elementWithDifferentId(): Persona = Persona.sampleMainnet.other() - var list = Personas.init(sample) + override fun identifier(element: Persona): IdentityAddress = element.address - assertTrue(sample in list) - assertEquals(1, list.size) - assertEquals(sample, list[0]) + override fun init(element: Persona): Personas = Personas(element) - list = list.append(sampleOther) - assertTrue(sampleOther in list) - assertEquals(2, list.size) - assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - Assertions.assertFalse(sampleOther in list) - assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - assertEquals(sampleOther, list()[0]) - assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - assertTrue(list.size == 2) - list = list.remove(sampleOther) - - assertEquals(sample, list.getBy(sample.address)) - assertTrue(list.removeByAddress(sample.address).size == 0) - } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileEntityTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileEntityTest.kt index 64587d75c..4acaa72b8 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileEntityTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileEntityTest.kt @@ -33,7 +33,7 @@ class ProfileEntityTest { assertEquals( Account.sampleMainnet().flags, - sut.flags + sut.flags.asList() ) } @@ -63,7 +63,7 @@ class ProfileEntityTest { assertEquals( Persona.sampleMainnet().flags, - sut.flags + sut.flags.asList() ) } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileNetworksTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileNetworksTest.kt new file mode 100644 index 000000000..42f9a244c --- /dev/null +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ProfileNetworksTest.kt @@ -0,0 +1,15 @@ +package com.radixdlt.sargon + +import com.radixdlt.sargon.extensions.ProfileNetworks +import com.radixdlt.sargon.samples.sampleMainnet +import com.radixdlt.sargon.samples.sampleStokenet + +internal class ProfileNetworksTest: IdentifiedArrayTest() { + override fun element(): ProfileNetwork = ProfileNetwork.sampleMainnet() + + override fun elementWithDifferentId(): ProfileNetwork = ProfileNetwork.sampleStokenet() + + override fun identifier(element: ProfileNetwork): NetworkId = element.id + + override fun init(element: ProfileNetwork): ProfileNetworks = ProfileNetworks(element) +} \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ReferencesToAuthorizedPersonasTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ReferencesToAuthorizedPersonasTest.kt index 0bbffee06..50c0f46b5 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ReferencesToAuthorizedPersonasTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ReferencesToAuthorizedPersonasTest.kt @@ -1,54 +1,18 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.getBy -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.removeByAddress -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import com.radixdlt.sargon.samples.Sample -import com.radixdlt.sargon.samples.sample +import com.radixdlt.sargon.extensions.ReferencesToAuthorizedPersonas import com.radixdlt.sargon.samples.sampleMainnet -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test -class ReferencesToAuthorizedPersonasTest: SampleTestable { - override val samples: List> - get() = listOf(ReferencesToAuthorizedPersonas.sample) +internal class ReferencesToAuthorizedPersonasTest : + IdentifiedArrayTest() { + override fun element(): AuthorizedPersonaSimple = AuthorizedPersonaSimple.sampleMainnet() - @Test - fun testListMethods() { - val sample = AuthorizedPersonaSimple.sampleMainnet() - val sampleOther = AuthorizedPersonaSimple.sampleMainnet.other() + override fun elementWithDifferentId(): AuthorizedPersonaSimple = AuthorizedPersonaSimple.sampleMainnet.other() - var list = ReferencesToAuthorizedPersonas.init(sample) + override fun identifier(element: AuthorizedPersonaSimple): IdentityAddress = + element.identityAddress - Assertions.assertTrue(sample in list) - Assertions.assertEquals(1, list.size) - Assertions.assertEquals(sample, list[0]) + override fun init(element: AuthorizedPersonaSimple): ReferencesToAuthorizedPersonas = + ReferencesToAuthorizedPersonas(element) - list = list.append(sampleOther) - Assertions.assertTrue(sampleOther in list) - Assertions.assertEquals(2, list.size) - Assertions.assertEquals(sampleOther, list[1]) - - list = list.remove(sampleOther) - Assertions.assertFalse(sampleOther in list) - Assertions.assertEquals(1, list.size) - - list = list.updateOrInsert(sampleOther, 0) - Assertions.assertEquals(sampleOther, list()[0]) - Assertions.assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - Assertions.assertTrue(list.size == 2) - list = list.remove(sampleOther) - - Assertions.assertEquals(sample, list.getBy(sample.identityAddress)) - Assertions.assertTrue(list.removeByAddress(sample.identityAddress).size == 0) - } } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SavedGatewaysTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SavedGatewaysTest.kt index 95a2afc9a..848f5e756 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SavedGatewaysTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SavedGatewaysTest.kt @@ -1,5 +1,6 @@ package com.radixdlt.sargon +import com.radixdlt.sargon.extensions.Gateways import com.radixdlt.sargon.extensions.all import com.radixdlt.sargon.extensions.changeCurrent import com.radixdlt.sargon.extensions.default @@ -30,7 +31,7 @@ class SavedGatewaysTest: SampleTestable { assertEquals( SavedGateways( current = Gateway.mainnet, - other = Gateways.init(Gateway.stokenet) + other = Gateways(Gateway.stokenet).asList() ), SavedGateways.default ) @@ -47,7 +48,7 @@ class SavedGatewaysTest: SampleTestable { assertEquals( SavedGateways( current = newGateway, - other = Gateways.init(Gateway.stokenet, Gateway.mainnet) + other = Gateways(Gateway.stokenet, Gateway.mainnet).asList() ), gateways ) diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SupportedCurvesTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SupportedCurvesTest.kt index 160b43d60..f50554a96 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SupportedCurvesTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/SupportedCurvesTest.kt @@ -1,44 +1,15 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.append -import com.radixdlt.sargon.extensions.contains -import com.radixdlt.sargon.extensions.get -import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.remove -import com.radixdlt.sargon.extensions.size -import com.radixdlt.sargon.extensions.updateOrAppend -import com.radixdlt.sargon.extensions.updateOrInsert -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test +import com.radixdlt.sargon.extensions.SupportedCurves +import com.radixdlt.sargon.samples.sample -class SupportedCurvesTest { +internal class SupportedCurvesTest: IdentifiedArrayTest() { - @Test - fun testListMethods() { - val sample = Slip10Curve.CURVE25519 - val sampleOther = Slip10Curve.SECP256K1 + override fun element(): Slip10Curve = Slip10Curve.sample() - var list = SupportedCurves.init(sample) + override fun elementWithDifferentId(): Slip10Curve = Slip10Curve.sample.other() - Assertions.assertTrue(sample in list) - Assertions.assertEquals(1, list.size) - Assertions.assertEquals(sample, list[0]) + override fun identifier(element: Slip10Curve): Slip10Curve = element - list = list.append(sampleOther) - Assertions.assertTrue(sampleOther in list) - Assertions.assertEquals(2, list.size) - Assertions.assertEquals(sampleOther, list[1]) - - list = list.updateOrInsert(sampleOther, 0) - Assertions.assertEquals(sampleOther, list()[1]) - Assertions.assertTrue(list.size == 2) - list = list.updateOrAppend(sampleOther) - Assertions.assertTrue(list.size == 2) - list = list.remove(sampleOther) - - list = list.remove(sampleOther) - Assertions.assertFalse(sampleOther in list) - Assertions.assertEquals(1, list.size) - } + override fun init(element: Slip10Curve): SupportedCurves = SupportedCurves(element) } \ No newline at end of file diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ThirdPartyDepositsTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ThirdPartyDepositsTest.kt index 7bf2bd450..a743feebb 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ThirdPartyDepositsTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/ThirdPartyDepositsTest.kt @@ -1,8 +1,9 @@ package com.radixdlt.sargon +import com.radixdlt.sargon.extensions.AssetsExceptionList +import com.radixdlt.sargon.extensions.DepositorsAllowList import com.radixdlt.sargon.extensions.accountRecoveryScanned import com.radixdlt.sargon.extensions.default -import com.radixdlt.sargon.extensions.init import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test @@ -13,8 +14,8 @@ class ThirdPartyDepositsTest { assertEquals( ThirdPartyDeposits( depositRule = DepositRule.ACCEPT_ALL, - assetsExceptionList = AssetsExceptionList.init(), - depositorsAllowList = DepositorsAllowList.init() + assetsExceptionList = AssetsExceptionList().asList(), + depositorsAllowList = DepositorsAllowList().asList() ), ThirdPartyDeposits.default() ) diff --git a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/WalletTest.kt b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/WalletTest.kt index c33bf606b..3a3233246 100644 --- a/jvm/sargon-android/src/test/java/com/radixdlt/sargon/WalletTest.kt +++ b/jvm/sargon-android/src/test/java/com/radixdlt/sargon/WalletTest.kt @@ -1,9 +1,6 @@ package com.radixdlt.sargon -import com.radixdlt.sargon.extensions.get import com.radixdlt.sargon.extensions.init -import com.radixdlt.sargon.extensions.invoke -import com.radixdlt.sargon.extensions.size import com.radixdlt.sargon.extensions.toBagOfBytes import com.radixdlt.sargon.samples.sample import org.junit.jupiter.api.Assertions.assertEquals @@ -37,7 +34,7 @@ class WalletTest { val initialNameOfFirstAccount = "Alice" // Not created any account yet... assertFalse(storage.contains(value = initialNameOfFirstAccount)) - assertTrue(wallet.profile().networks().isEmpty()) + assertTrue(wallet.profile().networks.isEmpty()) var main0 = wallet.createAndSaveNewAccount( networkId = NetworkId.MAINNET, name = DisplayName.init(validating = initialNameOfFirstAccount) @@ -90,7 +87,7 @@ class WalletTest { assertNotEquals(main0.address, main1.address) assertEquals(main0.networkId, main1.networkId) assertEquals(1, wallet.profile().networks.size) - assertEquals(listOf(main0, main1), wallet.profile().networks[0].accounts()) + assertEquals(listOf(main0, main1), wallet.profile().networks[0].accounts) println("🔮 Creating first testnet account") val testnetAccountName = "Hello Radix Account!" @@ -99,7 +96,7 @@ class WalletTest { name = DisplayName.init(validating = testnetAccountName) ) assertEquals(2, wallet.profile().networks.size) - assertEquals(listOf(test0), wallet.profile().networks[1].accounts()) + assertEquals(listOf(test0), wallet.profile().networks[1].accounts) assertEquals(testnetAccountName, wallet.profile().networks[1].accounts[0].displayName.value) assertEquals(NetworkId.STOKENET, wallet.profile().networks[1].accounts[0].networkId) assertTrue(storage.contains(value = testnetAccountName)) diff --git a/src/core/error/common_error.rs b/src/core/error/common_error.rs index 433ebe8a3..d0218f3f3 100644 --- a/src/core/error/common_error.rs +++ b/src/core/error/common_error.rs @@ -482,6 +482,12 @@ pub enum CommonError { #[error("AuthorizedDapp references field id that does not exist")] AuthorizedDappReferencesFieldIDThatDoesNotExist = 10134, + + #[error("Item identified by ID {id} does not exist")] + ElementDoesNotExist { id: String } = 10135, + + #[error("Item identified by ID {id} already exist")] + ElementAlreadyExist { id: String } = 10136, } #[uniffi::export] diff --git a/src/core/types/identified_vec_of/identifiable.rs b/src/core/types/identified_vec_of/identifiable.rs new file mode 100644 index 000000000..a1de612d5 --- /dev/null +++ b/src/core/types/identified_vec_of/identifiable.rs @@ -0,0 +1,17 @@ +use crate::prelude::*; + +/// The `Identifiable` trait allows you to use the +/// `IdentifiedVecOf instead of the more verbose +/// `IdentifiedVec` but also allows you to +/// skip the `id_of_element: fn(&Element) -> ID` closure when +/// initializing a new identified vec. +pub trait Identifiable { + /// The type that your `Element` will use as its globally unique and stable ID, + /// must impl `Hash` since it is used as a key in `IdentifiedVecOf`'s internal + /// `HashMap`. Must impl `Clone` since we need to be able to clone it as a key + type ID: Eq + StdHash + Clone + Debug; + + /// Return `Element`'s globally unique and stable ID, used to uniquely identify + /// the `Element` in the `IdentifiedVecOf` collection of elements. + fn id(&self) -> Self::ID; +} diff --git a/src/core/types/identified_vec_of/identified_vec_of.rs b/src/core/types/identified_vec_of/identified_vec_of.rs new file mode 100644 index 000000000..49152bf70 --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of.rs @@ -0,0 +1,98 @@ +use indexmap::{IndexMap, IndexSet}; + +use crate::prelude::*; + +use std::{ + any::TypeId, + fmt::{Debug, Display, Formatter}, + hash::Hasher, + ops::Index, +}; +use std::{hash::Hash, ops::DerefMut}; + +/// A collection which **retains the insertion order** of its **unique** [`Identifiable`] +/// items, with **constant time** look up of an item by its `id` - a stable key +/// which instances of the `Item` itself can calculate. +/// +/// The implementation is +#[derive(Clone, PartialEq, Eq)] +pub struct IdentifiedVecOf( + pub(super) IndexMap<::ID, V>, +); + +impl IdentifiedVecOf { + /// Creates a new empty `IdentifiedVecOf`. + pub fn new() -> Self { + Self::from(IndexMap::new()) + } + + /// Creates a new `IdentifiedVecOf` with one single item. + pub fn just(item: V) -> Self { + Self::from_iter([item]) + } +} + +impl Default + for IdentifiedVecOf +{ + fn default() -> Self { + Self::new() + } +} + +impl Hash for IdentifiedVecOf +where + V: Debug + PartialEq + Eq + Clone + Identifiable + Hash, +{ + fn hash(&self, state: &mut H) { + for key in self.0.values() { + key.hash(state); + } + } +} + +impl Index + for IdentifiedVecOf +{ + type Output = V; + + fn index(&self, index: usize) -> &Self::Output { + self.0.index(index) + } +} + +impl + From::ID, V>> for IdentifiedVecOf +{ + fn from(value: IndexMap<::ID, V>) -> Self { + Self(value) + } +} + +#[cfg(test)] +mod tests { + + use super::super::User; + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentifiedVecOf; + + #[test] + fn equality() { + assert_eq!(SUT::sample(), SUT::sample()); + assert_eq!(SUT::sample_other(), SUT::sample_other()); + } + + #[test] + fn inequality() { + assert_ne!(SUT::sample(), SUT::sample_other()); + } + + #[test] + fn index() { + let sut = SUT::sample(); + assert_eq!(sut[0], User::alice()); + assert_eq!(sut[1], User::carol()); + } +} diff --git a/src/core/types/identified_vec_of/identified_vec_of_display_debug.rs b/src/core/types/identified_vec_of/identified_vec_of_display_debug.rs new file mode 100644 index 000000000..b38c9d30c --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of_display_debug.rs @@ -0,0 +1,83 @@ +use crate::prelude::*; + +// =============== +// where V: Display +// =============== +impl Display for IdentifiedVecOf +where + V: Debug + PartialEq + Eq + Clone + Identifiable + Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.description())?; + Ok(()) + } +} + +impl IdentifiedVecOf +where + V: Debug + PartialEq + Eq + Clone + Identifiable + Display, +{ + fn description(&self) -> String { + [ + "[".to_owned(), + self.clone() + .into_iter() + .map(|e| format!("{}", e)) + .join(", "), + "]".to_owned(), + ] + .join("") + } +} + +// =============== +// where V: Debug +// =============== +impl Debug for IdentifiedVecOf +where + V: Debug + PartialEq + Eq + Clone + Identifiable, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.debug_description())?; + Ok(()) + } +} + +impl IdentifiedVecOf +where + V: Debug + PartialEq + Eq + Clone + Identifiable, +{ + fn debug_description(&self) -> String { + [ + "[".to_owned(), + self.clone() + .into_iter() + .map(|e| format!("{:?}", e)) + .join(", "), + "]".to_owned(), + ] + .join("") + } +} + +#[cfg(test)] +mod tests { + + use super::super::User; + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentifiedVecOf; + + #[test] + fn display() { + let sut = SUT::sample_other(); + assert_eq!(format!("{}", sut), "[Bob, David, Frank]") + } + + #[test] + fn debug() { + let sut = SUT::sample_other(); + assert_eq!(format!("{:?}", sut), "[(1: Bob), (3: David), (5: Frank)]") + } +} diff --git a/src/core/types/identified_vec_of/identified_vec_of_iterator.rs b/src/core/types/identified_vec_of/identified_vec_of_iterator.rs new file mode 100644 index 000000000..a1dbf0e5f --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of_iterator.rs @@ -0,0 +1,91 @@ +use indexmap::IndexMap; + +use crate::prelude::*; + +impl IdentifiedVecOf { + #[inline] + pub fn iter(&self) -> IdentifiedVecOfIterator { + IdentifiedVecOfIterator { + ordered_map: self, + index: 0, + } + } +} + +impl FromIterator + for IdentifiedVecOf +{ + fn from_iter>(iter: T) -> Self { + let mut map = IndexMap::<::ID, V>::new(); + for item in iter { + let _ = map.insert(item.id(), item); + } + Self::from(map) + } +} + +impl<'a, V: Debug + PartialEq + Eq + Clone + Identifiable> IntoIterator + for &'a IdentifiedVecOf +{ + type Item = V; + type IntoIter = IdentifiedVecOfIterator<'a, V>; + + fn into_iter(self) -> Self::IntoIter { + IdentifiedVecOfIterator { + ordered_map: self, + index: 0, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct IdentifiedVecOfIterator< + 'a, + V: Debug + PartialEq + Eq + Clone + Identifiable, +> { + ordered_map: &'a IdentifiedVecOf, + index: usize, +} + +impl<'a, V: Debug + PartialEq + Eq + Clone + Identifiable> Iterator + for IdentifiedVecOfIterator<'a, V> +{ + type Item = V; + + fn next(&mut self) -> Option { + if self.index < self.ordered_map.len() { + let elem = self.ordered_map.0.get_index(self.index); + self.index += 1; + elem.map(|pair| pair.1.clone()) + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + + use super::super::User; + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentifiedVecOf; + + #[test] + fn into_from_iter() { + let sut = SUT::sample(); + let iter = sut.into_iter(); + let from_iter = SUT::from_iter(iter); + assert_eq!(from_iter, sut) + } + + #[test] + fn iter() { + let sut = SUT::sample_other(); + assert_eq!( + sut.into_iter().collect_vec(), + vec![User::bob(), User::david(), User::frank()] + ) + } +} diff --git a/src/core/types/identified_vec_of/identified_vec_of_modify.rs b/src/core/types/identified_vec_of/identified_vec_of_modify.rs new file mode 100644 index 000000000..637f52024 --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of_modify.rs @@ -0,0 +1,304 @@ +use crate::prelude::*; + +impl IdentifiedVecOf { + /// Insert an item in the map **unconditionally**, using `id()` on item as key. + /// + /// If an equivalent key already exists in the map: the key remains and + /// retains in its place in the order, its corresponding value is updated + /// with `value` and the older value is returned inside `Some(_)`. + /// + /// If no equivalent key existed in the map: the new key-value pair is + /// inserted, last in order, and `None` is returned. + /// + /// Computes in **O(1)** time (amortized average). + /// + /// See also [`entry`](#method.entry) if you you want to insert *or* modify + /// or if you need to get the index of the corresponding key-value pair. + pub fn insert(&mut self, item: V) -> Option { + self.0.insert(item.id(), item) + } + + /// Insert the `item` **if and only if** no item with the same ID already + /// exists, if exists, an error is thrown. + pub fn try_insert_unique(&mut self, item: V) -> Result<()> { + if self.contains_by_id(&item) { + return Err(CommonError::ElementAlreadyExist { + id: format!("{:?}", item.id()), + }); + } + assert!(self.insert(item).is_none()); + Ok(()) + } + + /// Inserts `item` at `index`, if it already exists then the item remains + /// but **is moved to the new position** in the collection, and the item is + /// updated with value, and the older value is returned inside `Some(_)`. + /// + /// If no equivalent items existed: the new item is inserted at the given index, + /// and `None` is returned. + /// + /// #Panic + /// Panics if index is out of bounds. + pub fn insert_at(&mut self, item: V, index: usize) -> Option { + self.0.shift_insert(index, item.id(), item) + } + + /// Append a new member to the end of the `IdentifiedVecOf`, if the `IdentifiedVecOf` doesn't already contain it. + /// + /// - Parameter item: The element to add to the `IdentifiedVecOf`. + /// - Returns: A pair `(inserted, index)`, where `inserted` is a Boolean value indicating whether + /// the operation added a new element, and `index` is the index of `item` in the resulting + /// `IdentifiedVecOf`. + /// - Complexity: The operation is expected to perform O(1) copy, hash, and compare operations on + /// the `ID` type, if it implements high-quality hashing. + #[cfg(not(tarpaulin_include))] // false negative + pub fn append(&mut self, item: V) -> (bool, usize) { + if let Some(existing) = self.0.get_full(&item.id()) { + return (false, existing.0); + } + assert!(self.insert(item).is_none()); + (true, self.len() - 1) + } + + /// Remove and return the item with the `id`. + /// + /// Like `Vec::remove``, the item is removed by shifting all of the elements + /// that follow it, preserving their relative order. + /// **This perturbs the index of all of those elements!**. + /// + /// Return `None` if no item with `id` is in the collection. + /// + /// Computes in `O(n)` time (average). + pub fn remove_id(&mut self, id: &V::ID) -> Option { + self.0.shift_remove_entry(id).map(|pair| pair.1) + } + + /// Returns `false` if no element of `id` was found, otherwise if found, this + /// existing element gets updated by `mutate` closure and this function returns + /// `true`. + #[cfg(not(tarpaulin_include))] // false negative + #[inline] + pub fn update_with(&mut self, id: &V::ID, mut mutate: F) -> bool + where + F: FnMut(&mut V), + { + let Some(existing) = self.0.get_mut(id) else { + return false; + }; + mutate(existing); + true + } + + /// Tries to mutate the value identified by `id`, if no such value exists + /// an error is returned, the mutation is failable, if your return an `Err` + /// in `mutate`, this method propagates that error. + #[cfg(not(tarpaulin_include))] // false negative + #[inline] + pub fn try_try_update_with( + &mut self, + id: &V::ID, + mut mutate: F, + ) -> Result<()> + where + F: FnMut(&mut V) -> Result<()>, + { + let Some(existing) = self.0.get_mut(id) else { + return Err(CommonError::ElementDoesNotExist { + id: format!("{:?}", id), + }); + }; + mutate(existing)?; + Ok(()) + } + + /// Tries to mutate the value identified by `id`, if no such value exists + /// an error is returned, the mutation is failable, if your return an `Err` + /// in `mutate`, this method propagates that error. + #[cfg(not(tarpaulin_include))] // false negative + #[inline] + pub fn try_update_with( + &mut self, + id: &V::ID, + mut mutate: F, + ) -> Result<()> + where + F: FnMut(&mut V), + { + let Some(existing) = self.0.get_mut(id) else { + return Err(CommonError::ElementDoesNotExist { + id: format!("{:?}", id), + }); + }; + mutate(existing); + Ok(()) + } + + /// Tries to mutate the value identified by `id`, if no such value exists + /// then `Ok(false)` is returned, false meaning "no, not found", the mutation + /// is failable, if your return an `Err` in `mutate`, this method propagates that error. + #[inline] + pub fn maybe_update_with( + &mut self, + id: &V::ID, + mut mutate: F, + ) -> Result + where + F: FnMut(&mut V) -> Result, + { + let Some(existing) = self.0.get_mut(id) else { + return Ok(false); + }; + let mutated = mutate(existing)?; + *existing = mutated; + Ok(true) + } +} + +#[cfg(test)] +mod tests { + + use super::super::User; + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentifiedVecOf; + + #[test] + fn append_existing_is_noop() { + let mut sut = SUT::sample(); + assert_eq!(sut.append(User::grace()), (false, 3)) + } + + #[test] + fn append_existing_id_different_content_is_noop() { + let mut sut = SUT::sample(); + assert_eq!(sut.append(User::new(User::grace().id, "Gemma")), (false, 3)) + } + + #[test] + fn append_new() { + let mut sut = SUT::sample_other(); + assert_eq!(sut.append(User::carol()), (true, 3)); + assert_eq!(sut.to_string(), "[Bob, David, Frank, Carol]"); + } + + #[test] + fn insert_by_id_new() { + let mut sut = SUT::sample_other(); + assert_eq!(sut.insert(User::carol()), None); + assert_eq!(sut.to_string(), "[Bob, David, Frank, Carol]"); + } + + #[test] + fn insert_by_id_existing_is_updated() { + let mut sut = SUT::sample_other(); + assert_eq!( + sut.insert(User::new(User::bob().id, "Barry")), + Some(User::bob()) + ); + assert_eq!(sut.to_string(), "[Barry, David, Frank]"); + } + + #[test] + #[should_panic] + fn insert_at_out_of_bounds() { + let mut sut = SUT::sample(); + let _ = sut.insert_at(User::bob(), 999); + } + + #[test] + fn insert_existing_new_index() { + let mut sut = SUT::sample_other(); + let _ = sut.insert_at(User::bob(), 2); + assert_eq!(sut.to_string(), "[David, Frank, Bob]"); + } + + #[test] + fn insert_at_index_0_new() { + let mut sut = SUT::sample_other(); + let _ = sut.insert_at(User::alice(), 0); + assert_eq!(sut.to_string(), "[Alice, Bob, David, Frank]"); + } + + #[test] + fn insert_at_index_1_new() { + let mut sut = SUT::sample_other(); + let _ = sut.insert_at(User::alice(), 1); + assert_eq!(sut.to_string(), "[Bob, Alice, David, Frank]"); + } + + #[test] + fn insert_at_index_last_new() { + let mut sut = SUT::sample_other(); + let _ = sut.insert_at(User::alice(), 3); + assert_eq!(sut.to_string(), "[Bob, David, Frank, Alice]"); + } + + #[test] + fn try_inserting_unique_duplicate() { + let mut sut = SUT::sample(); + assert_eq!( + sut.try_insert_unique(User::grace()), + Err(CommonError::ElementAlreadyExist { id: "6".to_owned() }) + ); + } + + #[test] + fn update_with_for_existing() { + let foobar = User::new(0, "Foobar"); + let mut sut = SUT::sample(); + assert_eq!(sut.get_id(&0), Some(&User::alice())); + assert!(sut.update_with(&0, |u| { *u = foobar.clone() })); + assert_eq!(sut.get_id(&0), Some(&foobar)); + } + + #[test] + fn update_with_not_exists() { + let mut sut = SUT::sample(); + assert!(!sut.update_with(&1, |u| { *u = User::bob() })); + } + + #[test] + fn test_try_try_update_with_succeeds() { + let foobar = User::new(0, "Foobar"); + let mut sut = SUT::sample(); + assert_eq!(sut.get_id(&0), Some(&User::alice())); + assert!(sut + .try_try_update_with(&0, |u| { + *u = foobar.clone(); + Ok(()) + }) + .is_ok()); + assert_eq!(sut.get_id(&0), Some(&foobar)); + } + + #[test] + fn test_try_try_update_with_not_exists() { + let mut sut = SUT::sample(); + assert_eq!( + sut.try_try_update_with(&1, |u| { + *u = User::bob(); + Ok(()) + }), + Err(CommonError::ElementDoesNotExist { id: "1".to_owned() }) + ); + } + + #[test] + fn test_try_update_with_success() { + let foobar = User::new(0, "Foobar"); + let mut sut = SUT::sample(); + assert_eq!(sut.get_id(&0), Some(&User::alice())); + assert!(sut.try_update_with(&0, |u| { *u = foobar.clone() }).is_ok()); + assert_eq!(sut.get_id(&0), Some(&foobar)); + } + + #[test] + fn test_try_update_with_not_exists() { + let mut sut = SUT::sample(); + assert_eq!( + sut.try_update_with(&1, |u| { *u = User::bob() }), + Err(CommonError::ElementDoesNotExist { id: "1".to_owned() }) + ); + } +} diff --git a/src/core/types/identified_vec_of/identified_vec_of_query.rs b/src/core/types/identified_vec_of/identified_vec_of_query.rs new file mode 100644 index 000000000..219c920e5 --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of_query.rs @@ -0,0 +1,131 @@ +use indexmap::IndexSet; + +use crate::prelude::*; + +impl IdentifiedVecOf { + /// The number of items in this collection. + pub fn len(&self) -> usize { + self.0.len() + } + + /// If this collection is empty or not + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Returns the ids of the items. + pub fn ids(&self) -> IndexSet<&::ID> { + IndexSet::from_iter(self.0.keys()) + } + + /// Check if the `item` exists in this map by calculating the ID of the item + /// and checking if any other item with the same ID exists. + pub fn contains_by_id(&self, item: &V) -> bool { + self.contains_id(&item.id()) + } + + /// Return `true`` if an item with `id` exists in the collection. + pub fn contains_id(&self, id: &V::ID) -> bool { + self.0.contains_key(id) + } + + /// Get an item by index + /// + /// Valid indices are `0 <= index < self.len()`` + /// + /// Computes in **O(1)** time. + pub fn get_at_index(&self, index: usize) -> Option<&V> { + self.0.get_index(index).map(|pair| pair.1) + } + + /// Return a reference to the item, if it is present, else `None``. + /// + /// Computes in **O(1)** time (average). + pub fn get_id(&self, id: &V::ID) -> Option<&V> { + self.0.get(id) + } + + /// Return a Vec of references to the items of the collection, in their order. + pub fn get_all(&self) -> Vec<&V> { + self.0.values().collect_vec() + } + + /// Returns the item at index 0 in this [`IdentifiedVecOf`] if any exists. + pub fn first(&self) -> Option<&V> { + self.get_at_index(0) + } + + /// Return a Vec with items of the collection, in their order. + pub fn items(&self) -> Vec { + self.into_iter().collect_vec() + } +} + +#[cfg(test)] +mod tests { + + use super::super::User; + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentifiedVecOf; + + #[test] + fn get_id() { + let sut = SUT::sample(); + assert_eq!(sut.get_id(&0), Some(&User::alice())); + assert_eq!(sut.get_id(&2), Some(&User::carol())); + assert_eq!(sut.get_id(&200), None); + } + + #[test] + fn get_index() { + let sut = SUT::sample(); + assert_eq!(sut.get_at_index(0), Some(&User::alice())); + assert_eq!(sut.get_at_index(1), Some(&User::carol())); + assert_eq!(sut.get_at_index(999), None); + } + + #[test] + fn len() { + assert_eq!(SUT::sample().len(), 4); + assert_eq!(SUT::sample_other().len(), 3); + assert_eq!(SUT::new().len(), 0); + } + + #[test] + fn is_empty() { + assert!(!SUT::sample().is_empty()); + assert!(!SUT::sample_other().is_empty()); + assert!(SUT::new().is_empty()); + } + + #[test] + fn contains_id() { + let sut = SUT::sample(); + assert!(sut.contains_id(&0)); + assert!(!sut.contains_id(&200)); + } + + #[test] + fn contains_by_id() { + let sut = SUT::sample(); + assert!(sut.contains_by_id(&User::alice())); + assert!(!sut.contains_by_id(&User::frank())); + } + + #[test] + fn items() { + let sut = SUT::sample_other(); + assert_eq!(sut.items(), vec![User::bob(), User::david(), User::frank()]) + } + + #[test] + fn get_all() { + let sut = SUT::sample_other(); + assert_eq!( + sut.get_all(), + vec![&User::bob(), &User::david(), &User::frank()] + ) + } +} diff --git a/src/core/types/identified_vec_of/identified_vec_of_serde.rs b/src/core/types/identified_vec_of/identified_vec_of_serde.rs new file mode 100644 index 000000000..47412cdf8 --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of_serde.rs @@ -0,0 +1,102 @@ +use std::any::TypeId; + +use crate::prelude::*; + +use super::{export_identified_vec_of, import_identified_vec_of_from}; + +impl Serialize + for IdentifiedVecOf +where + V: Serialize, +{ + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + export_identified_vec_of(self) + .map_err(serde::ser::Error::custom) + .and_then(|v| serializer.collect_seq(v)) + } +} + +impl<'de, V: Debug + PartialEq + Eq + Clone + Identifiable + 'static> + Deserialize<'de> for IdentifiedVecOf +where + V: Deserialize<'de>, +{ + #[inline] + fn deserialize>( + deserializer: D, + ) -> Result { + let items = Vec::::deserialize(deserializer)?; + import_identified_vec_of_from(items).map_err(de::Error::custom) + } +} + +#[cfg(test)] +mod tests { + + use super::super::User; + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentifiedVecOf; + + #[test] + fn json_roundtrip_sample() { + let sut = SUT::sample(); + assert_eq_after_json_roundtrip( + &sut, + r#" + [ + { + "id": 0, + "name": "Alice" + }, + { + "id": 2, + "name": "Carol" + }, + { + "id": 4, + "name": "Erin" + }, + { + "id": 6, + "name": "Grace" + } + ] + "#, + ); + } + + #[test] + fn duplicates_in_json_throws() { + let json = r#" + [ + { + "id": 0, + "name": "Alice" + }, + { + "id": 0, + "name": "Alice" + }, + { + "id": 2, + "name": "Carol" + }, + { + "id": 4, + "name": "Erin" + }, + { + "id": 6, + "name": "Grace" + } + ] + "#; + assert!(serde_json::from_str::(json).is_err()); + } +} diff --git a/src/core/types/identified_vec_of/identified_vec_of_uniffi_converter.rs b/src/core/types/identified_vec_of/identified_vec_of_uniffi_converter.rs new file mode 100644 index 000000000..10db34bca --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of_uniffi_converter.rs @@ -0,0 +1,131 @@ +use crate::prelude::*; +use indexmap::IndexMap; +use std::any::TypeId; +use uniffi::{ + check_remaining, + deps::bytes::{Buf, BufMut}, + metadata, Lift, Lower, LowerReturn, MetadataBuffer, RustBuffer, +}; + +use super::import_identified_vec_of_from; + +// We turn an `[Rust] IndexMap -> Array/List [FFI]`` + +unsafe impl> Lower + for IdentifiedVecOf +{ + type FfiType = RustBuffer; + + fn write(obj: Self, buf: &mut Vec) { + let len = i32::try_from(obj.len()).unwrap(); + buf.put_i32(len); // We limit arrays to i32::MAX items + for value in &obj { + >::write(value, buf); + } + } + + fn lower(obj: Self) -> RustBuffer { + Self::lower_into_rust_buffer(obj) + } + + const TYPE_ID_META: MetadataBuffer = + MetadataBuffer::from_code(metadata::codes::TYPE_VEC) + .concat(V::TYPE_ID_META); +} + +unsafe impl> + LowerReturn for IdentifiedVecOf +{ + type ReturnType = >::FfiType; + + fn lower_return(obj: Self) -> uniffi::Result { + Ok(>::lower(obj)) + } + + const TYPE_ID_META: MetadataBuffer = >::TYPE_ID_META; +} +unsafe impl + 'static> + Lift for IdentifiedVecOf +{ + type FfiType = RustBuffer; + + fn try_read(buf: &mut &[u8]) -> uniffi::Result { + check_remaining(buf, 4)?; + let len = usize::try_from(buf.get_i32())?; + let mut vec = Vec::with_capacity(len); + for _ in 0..len { + vec.push(>::try_read(buf)?) + } + import_identified_vec_of_from(vec).map_err(|e| e.into()) + } + + fn try_lift(buf: RustBuffer) -> uniffi::Result { + Self::try_lift_from_rust_buffer(buf) + } + + const TYPE_ID_META: MetadataBuffer = + MetadataBuffer::from_code(metadata::codes::TYPE_VEC) + .concat(V::TYPE_ID_META); +} + +#[cfg(test)] +mod tests { + + use super::super::User; + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentifiedVecOf; + + #[test] + fn manual_perform_uniffi_conversion_successful() { + let test_expected = |from: SUT, to: SUT| { + let ffi_side = + >::lower(from.clone()); + let from_ffi = + >::try_lift(ffi_side).unwrap(); + assert_eq!(from_ffi, to.clone()); + + let ffi_side_lower_return = + >::lower_return(from) + .unwrap(); + let from_ffi_lower_return = + >::try_lift( + ffi_side_lower_return, + ) + .unwrap(); + assert_eq!(from_ffi_lower_return, to); + }; + let test = |sut: SUT| test_expected(sut.clone(), sut); + + test(SUT::new()); + test(SUT::sample()); + test(SUT::sample_other()); + } + + #[test] + fn manual_perform_uniffi_if_duplicates_throw() { + // This is some advanced techniques... + let mut bad_value_from_ffi_vec = Vec::new(); + bad_value_from_ffi_vec.put_i32(2); // duplicates + >::write( + User::alice(), + &mut bad_value_from_ffi_vec, + ); + >::write( + User::alice(), + &mut bad_value_from_ffi_vec, + ); // duplicate! + let bad_value_from_ffi = RustBuffer::from_vec(bad_value_from_ffi_vec); + assert!( + >::try_lift(bad_value_from_ffi) + .is_err() + ); + } + + #[test] + fn manual_perform_uniffi_conversion_fail() { + assert!(>::try_lift(RustBuffer::new()) + .is_err()); + } +} diff --git a/src/core/types/identified_vec_of/identified_vec_of_validation_import_export.rs b/src/core/types/identified_vec_of/identified_vec_of_validation_import_export.rs new file mode 100644 index 000000000..99757f254 --- /dev/null +++ b/src/core/types/identified_vec_of/identified_vec_of_validation_import_export.rs @@ -0,0 +1,37 @@ +use std::any::TypeId; + +use crate::prelude::*; + +pub(super) fn import_identified_vec_of_from( + iter: impl IntoIterator, +) -> Result> +where + V: Debug + Eq + Clone + Identifiable + 'static, +{ + let mut id_vec = IdentifiedVecOf::new(); + + for item in iter { + id_vec.try_insert_unique(item)?; + } + + export_identified_vec_of(&id_vec)?; + Ok(id_vec) +} + +pub(super) fn export_identified_vec_of( + id_vec: &IdentifiedVecOf, +) -> Result<&IdentifiedVecOf> +where + V: Debug + Eq + Clone + Identifiable + 'static, +{ + if id_vec.is_empty() { + if TypeId::of::() == TypeId::of::() { + return Err(CommonError::FactorSourcesMustNotBeEmpty); + } + if TypeId::of::() == TypeId::of::() { + return Err(CommonError::SupportedCurvesMustNotBeEmpty); + } + } + + Ok(id_vec) +} diff --git a/src/core/types/identified_vec_of/mod.rs b/src/core/types/identified_vec_of/mod.rs new file mode 100644 index 000000000..fa2f877f5 --- /dev/null +++ b/src/core/types/identified_vec_of/mod.rs @@ -0,0 +1,25 @@ +mod identifiable; +mod identified_vec_of; +mod identified_vec_of_display_debug; +mod identified_vec_of_iterator; +mod identified_vec_of_modify; +mod identified_vec_of_query; +mod identified_vec_of_serde; +mod identified_vec_of_uniffi_converter; +mod identified_vec_of_validation_import_export; + +#[cfg(test)] +mod user; + +#[cfg(test)] +use user::*; + +pub use identifiable::*; +pub use identified_vec_of::*; +pub use identified_vec_of_display_debug::*; +pub use identified_vec_of_iterator::*; +pub use identified_vec_of_modify::*; +pub use identified_vec_of_query::*; +pub use identified_vec_of_serde::*; +pub use identified_vec_of_uniffi_converter::*; +use identified_vec_of_validation_import_export::*; diff --git a/src/core/types/identified_vec_of/user.rs b/src/core/types/identified_vec_of/user.rs new file mode 100644 index 000000000..f3471d36e --- /dev/null +++ b/src/core/types/identified_vec_of/user.rs @@ -0,0 +1,94 @@ +use crate::prelude::*; + +#[cfg(test)] +#[derive( + Clone, + PartialEq, + Eq, + Hash, + serde::Serialize, + serde::Deserialize, + derive_more::Display, + derive_more::Debug, + uniffi::Record, +)] +#[debug("({}: {})", id, name)] +#[display("{}", name)] +pub(super) struct User { + pub(super) id: u8, + pub(super) name: String, +} + +#[cfg(test)] +impl User { + pub(super) fn new(id: u8, name: impl AsRef) -> Self { + Self { + id, + name: name.as_ref().to_owned(), + } + } +} + +#[cfg(test)] +impl Identifiable for User { + type ID = u8; + fn id(&self) -> Self::ID { + self.id + } +} + +#[cfg(test)] +impl User { + /// id 0 + pub(super) fn alice() -> Self { + Self::new(0, "Alice") + } + + /// id 1 + pub(super) fn bob() -> Self { + Self::new(1, "Bob") + } + + /// id 2 + pub(super) fn carol() -> Self { + Self::new(2, "Carol") + } + + /// id 3 + pub(super) fn david() -> Self { + Self::new(3, "David") + } + + /// id 4 + pub(super) fn erin() -> Self { + Self::new(4, "Erin") + } + + /// id 5 + pub(super) fn frank() -> Self { + Self::new(5, "Frank") + } + + /// id 6 + pub(super) fn grace() -> Self { + Self::new(6, "Grace") + } +} + +#[cfg(test)] +impl crate::HasSampleValues for IdentifiedVecOf { + /// Alice(0), Carol(2), Erin(4), Grace(6) + fn sample() -> Self { + Self::from_iter([ + User::alice(), + User::carol(), + User::erin(), + User::grace(), + ]) + } + + /// Bob(1), David(3), Frank(5) + fn sample_other() -> Self { + Self::from_iter([User::bob(), User::david(), User::frank()]) + } +} diff --git a/src/core/types/identified_vec_via.rs b/src/core/types/identified_vec_via.rs deleted file mode 100644 index 10d0d8f56..000000000 --- a/src/core/types/identified_vec_via.rs +++ /dev/null @@ -1,313 +0,0 @@ -use identified_vec::{ - identified_vec_into_iterator::IdentifiedVecIntoIterator, Identifiable, - IdentifiedVecOf, IsIdentifiableVecOfVia, IsIdentifiedVec, - IsIdentifiedVecOf, ViaMarker, -}; -use itertools::Itertools; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::{ - fmt::{Debug, Display, Formatter}, - ops::Index, -}; -use uniffi::{ - check_remaining, - deps::bytes::{Buf, BufMut}, - metadata, Lift, Lower, LowerReturn, MetadataBuffer, RustBuffer, -}; - -#[derive(Clone, Eq, PartialEq, Hash, derive_more::Debug)] -#[debug("{}", self.debug_string())] -pub struct IdentifiedVecVia { - id_vec: IdentifiedVecOf, -} - -impl std::iter::FromIterator - for IdentifiedVecVia -{ - fn from_iter>(iter: T) -> Self { - Self::from_identified_vec_of(IdentifiedVecOf::from_iter(iter)) - } -} - -impl Default - for IdentifiedVecVia -{ - fn default() -> Self { - Self::new() - } -} - -impl IdentifiedVecVia { - pub fn new() -> Self { - Self::from_identified_vec_of(IdentifiedVecOf::new()) - } - - pub fn len(&self) -> usize { - self.id_vec.len() - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - pub fn first(&self) -> Option { - self.get_at_index(0).cloned() - } -} - -impl Index - for IdentifiedVecVia -{ - type Output = Element; - - fn index(&self, index: usize) -> &Self::Output { - self.get_at_index(index).expect("Element at index: {index}") - } -} - -impl ViaMarker - for IdentifiedVecVia -{ -} - -impl IsIdentifiableVecOfVia - for IdentifiedVecVia -{ - #[cfg(not(tarpaulin_include))] // false negative - fn via_mut(&mut self) -> &mut IdentifiedVecOf { - &mut self.id_vec - } - - #[cfg(not(tarpaulin_include))] // false negative - fn via(&self) -> &IdentifiedVecOf { - &self.id_vec - } - - fn from_identified_vec_of( - identified_vec_of: IdentifiedVecOf, - ) -> Self { - Self { - id_vec: identified_vec_of, - } - } -} - -impl Display - for IdentifiedVecVia -{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.description())?; - Ok(()) - } -} - -impl - IdentifiedVecVia -{ - fn description(&self) -> String { - [ - "[".to_owned(), - self.clone() - .into_iter() - .map(|e| format!("{}", e)) - .join(", "), - "]".to_owned(), - ] - .join("") - } -} - -#[allow(unused)] // false, it is used by `derive_more::Debug` macro above -impl IdentifiedVecVia { - fn debug_string(&self) -> String { - [ - "[".to_owned(), - self.clone() - .into_iter() - .map(|e| format!("{:?}", e)) - .join(", "), - "]".to_owned(), - ] - .join("") - } -} - -impl IntoIterator - for IdentifiedVecVia -{ - type Item = Element; - type IntoIter = - IdentifiedVecIntoIterator<::ID, Element>; - - fn into_iter(self) -> Self::IntoIter { - Self::IntoIter::new(self.id_vec) - } -} - -impl Serialize - for IdentifiedVecVia -where - Element: Serialize + Identifiable + Debug + Clone, -{ - fn serialize( - &self, - serializer: S, - ) -> Result<::Ok, ::Error> - where - S: Serializer, - { - IdentifiedVecOf::serialize(&self.id_vec, serializer) - } -} - -impl<'de, Element: Identifiable + Debug + Clone> Deserialize<'de> - for IdentifiedVecVia -where - Element: Deserialize<'de> + Identifiable + Debug + Clone, -{ - #[cfg(not(tarpaulin_include))] // false negative - fn deserialize>( - deserializer: D, - ) -> Result { - let id_vec_of = IdentifiedVecOf::::deserialize(deserializer)?; - Ok(Self::from_identified_vec_of(id_vec_of)) - } -} - -#[cfg(not(tarpaulin_include))] // Tested in binding tests (e.g. test*.swift files) -unsafe impl> Lower - for IdentifiedVecVia -{ - type FfiType = RustBuffer; - - fn write(obj: IdentifiedVecVia, buf: &mut Vec) { - let len = i32::try_from(obj.len()).unwrap(); - buf.put_i32(len); // We limit arrays to i32::MAX items - for item in obj { - >::write(item, buf); - } - } - - fn lower(obj: IdentifiedVecVia) -> RustBuffer { - Self::lower_into_rust_buffer(obj) - } - - const TYPE_ID_META: MetadataBuffer = - MetadataBuffer::from_code(metadata::codes::TYPE_VEC) - .concat(T::TYPE_ID_META); -} - -#[cfg(not(tarpaulin_include))] // Tested in binding tests (e.g. test*.swift files) -unsafe impl> LowerReturn - for IdentifiedVecVia -{ - type ReturnType = >::FfiType; - - fn lower_return(obj: Self) -> uniffi::Result { - Ok(>::lower(obj)) - } - - const TYPE_ID_META: MetadataBuffer = >::TYPE_ID_META; -} - -#[cfg(not(tarpaulin_include))] // Tested in binding tests (e.g. test*.swift files) -unsafe impl> Lift - for IdentifiedVecVia -{ - type FfiType = RustBuffer; - - fn try_read(buf: &mut &[u8]) -> uniffi::Result> { - check_remaining(buf, 4)?; - let len = usize::try_from(buf.get_i32())?; - let mut vec = Vec::with_capacity(len); - for _ in 0..len { - vec.push(>::try_read(buf)?) - } - Ok( as FromIterator>::from_iter(vec)) - } - - fn try_lift(buf: RustBuffer) -> uniffi::Result> { - Self::try_lift_from_rust_buffer(buf) - } - - const TYPE_ID_META: MetadataBuffer = - MetadataBuffer::from_code(metadata::codes::TYPE_VEC) - .concat(T::TYPE_ID_META); -} - -#[cfg(test)] -mod tests { - use identified_vec::{ - IsIdentifiableVecOfVia, IsIdentifiedVec, ItemsCloned, - }; - use itertools::Itertools; - - use super::IdentifiedVecVia; - - #[allow(clippy::upper_case_acronyms)] - type SUT = IdentifiedVecVia; - - #[test] - fn first() { - let sut = SUT::from_iter([1337, 42, 237]); - assert_eq!(sut.first(), Some(1337)); - } - - #[test] - fn is_empty() { - let sut = SUT::from_iter([1337, 42, 237]); - assert!(!sut.is_empty()); - assert!(SUT::new().is_empty()); - } - - #[test] - fn default_is_new() { - assert_eq!(SUT::new(), SUT::default()); - } - - #[test] - fn len() { - let sut = SUT::from_iter([1337, 42, 237]); - assert_eq!(sut.len(), 3); - assert_eq!(SUT::new().len(), 0); - } - - #[test] - fn into_iter() { - let sut = SUT::from_iter([1337, 42, 237]); - assert_eq!(sut.into_iter().collect_vec(), [1337, 42, 237]); - } - - #[test] - fn display() { - let sut = SUT::from_iter([1337, 42, 237]); - assert_eq!(format!("{}", sut), "[1337, 42, 237]"); - } - - #[test] - fn via() { - let sut = SUT::from_iter([1337, 42, 237]); - assert_eq!( - sut.via().clone().into_iter().collect_vec(), - [1337, 42, 237] - ); - } - - #[test] - fn via_mut_read() { - let mut sut = SUT::from_iter([1337, 42, 237]); - assert_eq!( - sut.via_mut().clone().into_iter().collect_vec(), - [1337, 42, 237] - ); - } - - #[test] - fn via_mut_write() { - let mut sut = SUT::from_iter([1337, 42]); - sut.via_mut().append(237); - assert_eq!(sut.items(), [1337, 42, 237]); - sut.via_mut().remove_by_id(&42); - assert_eq!(sut.items(), [1337, 237]); - } -} diff --git a/src/core/types/mod.rs b/src/core/types/mod.rs index a52b048ae..ed2ad0775 100644 --- a/src/core/types/mod.rs +++ b/src/core/types/mod.rs @@ -7,7 +7,7 @@ mod decimal192_uniffi_fn; mod entity_kind; mod epoch; mod exactly_n_bytes; -mod identified_vec_via; +mod identified_vec_of; mod keys; mod locale_config; mod logged_result; @@ -31,7 +31,7 @@ pub use decimal192_uniffi_fn::*; pub use entity_kind::*; pub use epoch::*; pub use exactly_n_bytes::*; -pub use identified_vec_via::*; +pub use identified_vec_of::*; pub use keys::*; pub use locale_config::*; pub use logged_result::*; diff --git a/src/lib.rs b/src/lib.rs index 8489f0143..ee5104ac5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,11 +22,6 @@ pub mod prelude { pub(crate) use std::collections::{BTreeSet, HashMap, HashSet}; - pub(crate) use ::identified_vec::{ - Identifiable, IdentifiedVec, IdentifiedVecOf, IsIdentifiedVec, - ItemsCloned, - }; - pub(crate) use ::hex::decode as hex_decode; pub(crate) use ::hex::encode as hex_encode; pub(crate) use iso8601_timestamp::Timestamp; @@ -44,7 +39,9 @@ pub mod prelude { pub use radix_engine_common::math::traits::CheckedMul as ScryptoCheckedMul; pub(crate) use std::cmp::Ordering; pub(crate) use std::collections::BTreeMap; + pub(crate) use std::fmt::{Debug, Display, Formatter}; pub(crate) use std::fs; + pub(crate) use std::hash::Hash as StdHash; pub use std::ops::{Add, AddAssign, Deref, Div, Mul, Neg, Sub}; pub(crate) use std::str::FromStr; pub(crate) use std::sync::Arc; @@ -64,7 +61,6 @@ pub mod prelude { VersionedTransactionReceipt as ScryptoVersionedTransactionReceipt, }, types::{ - indexmap::{IndexMap, IndexSet}, node_modules::{ metadata::ToMetadataEntry as ScryptoToMetadataEntry, ModuleConfig as ScryptoModuleConfig, diff --git a/src/profile/logic/persona/persona_data_ids.rs b/src/profile/logic/persona/persona_data_ids.rs index cc25a8019..3479e5df5 100644 --- a/src/profile/logic/persona/persona_data_ids.rs +++ b/src/profile/logic/persona/persona_data_ids.rs @@ -1,3 +1,5 @@ +use indexmap::IndexSet; + use crate::prelude::*; impl PersonaData { diff --git a/src/profile/logic/persona/shared_persona_data_ids.rs b/src/profile/logic/persona/shared_persona_data_ids.rs index 3093facfc..841ad6eba 100644 --- a/src/profile/logic/persona/shared_persona_data_ids.rs +++ b/src/profile/logic/persona/shared_persona_data_ids.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use indexmap::IndexSet; impl SharedPersonaData { pub fn ids_of_entries(&self) -> IndexSet { @@ -7,10 +8,10 @@ impl SharedPersonaData { let _ = full_ids.insert(*name); }; if let Some(email_addresses) = &self.email_addresses { - full_ids.extend(email_addresses.clone().ids); + full_ids.extend(&email_addresses.ids); } if let Some(phone_numbers) = &self.phone_numbers { - full_ids.extend(phone_numbers.clone().ids); + full_ids.extend(&phone_numbers.ids); } full_ids } diff --git a/src/profile/logic/profile_network/profile_network_details.rs b/src/profile/logic/profile_network/profile_network_details.rs index 6ac3a04f7..8d5072d3c 100644 --- a/src/profile/logic/profile_network/profile_network_details.rs +++ b/src/profile/logic/profile_network/profile_network_details.rs @@ -12,7 +12,7 @@ impl AuthorizedPersonaSimple { .iter() .map(|account_address| { let Some(account) = non_hidden_accounts - .iter().find(|x| x.address == *account_address) + .iter().find(|x| x.address == account_address) else { // This is a sign that Profile is in a bad state somehow... warn!("Discrepancy! AuthorizedDapp references account which does not exist {}", account_address); @@ -260,9 +260,9 @@ mod tests { #[test] fn details_ok() { let sut = SUT::sample(); - let dapp = sut.authorized_dapps.first().clone().unwrap(); + let dapp = sut.authorized_dapps.first().unwrap(); - let details = sut.details_for_authorized_dapp(&dapp).unwrap(); + let details = sut.details_for_authorized_dapp(dapp).unwrap(); assert_eq!( &details.dapp_definition_address, &dapp.dapp_definition_address diff --git a/src/profile/logic/profile_next_derivation.rs b/src/profile/logic/profile_next_derivation.rs index 558678e8e..2c183aaf0 100644 --- a/src/profile/logic/profile_next_derivation.rs +++ b/src/profile/logic/profile_next_derivation.rs @@ -11,7 +11,7 @@ impl Profile { { let id = id.into(); self.factor_sources - .get(&id) + .get_id(&id) .ok_or(CommonError::ProfileDoesNotContainFactorSourceWithID { bad_value: id.clone(), }) @@ -36,7 +36,6 @@ impl Profile { let device_factor_source = self .factor_sources .iter() - .cloned() .filter_map(|f| f.as_device().cloned()) .collect_vec(); @@ -75,7 +74,7 @@ impl Profile { }; let index = self .networks - .get(&network_id) + .get_id(&network_id) .map(|n| { n.accounts .items() @@ -114,7 +113,7 @@ impl Profile { header.content_hint = networks.content_hint(); Self::with( header, - FactorSources::from_iter([FactorSource::sample_ledger()]).unwrap(), + FactorSources::from_iter([FactorSource::sample_ledger()]), AppPreferences::sample(), networks, ) @@ -128,8 +127,7 @@ impl Profile { header, FactorSources::from_iter([ DeviceFactorSource::sample_olympia().into() - ]) - .unwrap(), + ]), AppPreferences::sample(), networks, ) @@ -142,7 +140,7 @@ impl Profile { .factor_sources .iter() .filter_map(|f| f.as_device().cloned()) - .filter(|df| df.common.flags.contains(&FactorSourceFlag::Main)) + .filter(|df| df.common.flags.contains_id(&FactorSourceFlag::Main)) .map(|f| f.factor_source_id()) .collect_vec(); @@ -153,7 +151,7 @@ impl Profile { .unwrap() .common .flags - .remove(&FactorSourceFlag::Main) + .remove_id(&FactorSourceFlag::Main) }) }); diff --git a/src/profile/supporting_types/accounts_for_display.rs b/src/profile/supporting_types/accounts_for_display.rs index 5f1d0b2d1..72165079c 100644 --- a/src/profile/supporting_types/accounts_for_display.rs +++ b/src/profile/supporting_types/accounts_for_display.rs @@ -1,6 +1,10 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!(AccountsForDisplay, AccountForDisplay); +decl_identified_vec_of!( + /// An ordered collection of unique [`AccountForDisplay`]s. + AccountsForDisplay, + AccountForDisplay +); impl HasSampleValues for AccountsForDisplay { fn sample() -> Self { diff --git a/src/profile/supporting_types/accounts_or_personas.rs b/src/profile/supporting_types/accounts_or_personas.rs index f9d8d17c7..a91b399a7 100644 --- a/src/profile/supporting_types/accounts_or_personas.rs +++ b/src/profile/supporting_types/accounts_or_personas.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// An ordered set of entities of mixed type, either [`Account`] or [`Persona`]. AccountsOrPersonas, AccountOrPersona diff --git a/src/profile/supporting_types/decl_identified_vec_of_with_samples.rs b/src/profile/supporting_types/decl_identified_vec_of_with_samples.rs new file mode 100644 index 000000000..1bbae0a0e --- /dev/null +++ b/src/profile/supporting_types/decl_identified_vec_of_with_samples.rs @@ -0,0 +1,95 @@ +use crate::prelude::*; + +macro_rules! decl_identified_vec_of { + ( + $( + #[doc = $expr: expr] + )* + $collection_type: ident, + $element_type: ident + ) => { + paste! { + $( + #[doc = $expr] + )* + pub type $collection_type = IdentifiedVecOf<$element_type>; + + #[uniffi::export] + pub fn [< new_ $collection_type:snake _sample >]() -> $collection_type { + $collection_type::sample() + } + + #[uniffi::export] + pub fn [< new_ $collection_type:snake _sample_other >]() -> $collection_type { + $collection_type::sample_other() + } + + #[cfg(test)] + mod [< $collection_type:snake _tests >] { + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = $collection_type; + + #[test] + fn test_ids() { + assert_eq!(SUT::sample().ids().into_iter().cloned().collect_vec(), SUT::sample().get_all().into_iter().map(|i| i.id()).collect_vec()); + } + } + + #[cfg(test)] + mod [< $collection_type:snake _uniffi_tests >] { + use super::*; + + #[allow(clippy::upper_case_acronyms)] + type SUT = $collection_type; + + #[test] + fn hash_of_samples() { + assert_eq!( + HashSet::::from_iter([ + [< new_ $collection_type:snake _sample >](), + [< new_ $collection_type:snake _sample_other >](), + // duplicates should get removed + [< new_ $collection_type:snake _sample >](), + [< new_ $collection_type:snake _sample_other >]() + ]) + .len(), + 2 + ); + } + + #[test] + fn manual_perform_uniffi_conversion_successful() { + let test = |sut: SUT| { + let ffi_side = >::lower(sut.clone()); + let from_ffi = + >::try_lift(ffi_side).unwrap(); + assert_eq!(from_ffi, sut); + }; + + test(SUT::sample()); + test(SUT::sample_other()); + } + } + } + }; + ( + $( + #[doc = $expr: expr] + )* + $element_type: ident + ) => { + paste! { + decl_identified_vec_of!( + $( + #[doc = $expr] + )* + [< $element_type s>], + $element_type + ); + } + }; +} + +pub(crate) use decl_identified_vec_of; diff --git a/src/profile/supporting_types/detailed_authorized_personas.rs b/src/profile/supporting_types/detailed_authorized_personas.rs index 7cdc65076..9428c7ccb 100644 --- a/src/profile/supporting_types/detailed_authorized_personas.rs +++ b/src/profile/supporting_types/detailed_authorized_personas.rs @@ -1,9 +1,6 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( - DetailedAuthorizedPersonas, - AuthorizedPersonaDetailed -); +decl_identified_vec_of!(DetailedAuthorizedPersonas, AuthorizedPersonaDetailed); impl HasSampleValues for DetailedAuthorizedPersonas { fn sample() -> Self { diff --git a/src/profile/supporting_types/mod.rs b/src/profile/supporting_types/mod.rs index bda118df3..523308db8 100644 --- a/src/profile/supporting_types/mod.rs +++ b/src/profile/supporting_types/mod.rs @@ -8,6 +8,7 @@ mod authorized_dapp_detailed; mod authorized_dapp_detailed_uniffi_fn; mod authorized_persona_detailed; mod authorized_persona_detailed_uniffi_fn; +mod decl_identified_vec_of_with_samples; mod detailed_authorized_personas; pub use account_for_display::*; @@ -20,4 +21,5 @@ pub use authorized_dapp_detailed::*; pub use authorized_dapp_detailed_uniffi_fn::*; pub use authorized_persona_detailed::*; pub use authorized_persona_detailed_uniffi_fn::*; +pub use decl_identified_vec_of_with_samples::*; pub use detailed_authorized_personas::*; diff --git a/src/profile/v100/app_preferences/gateways/gateway.rs b/src/profile/v100/app_preferences/gateways/gateway.rs index b22dc5869..a99610ff9 100644 --- a/src/profile/v100/app_preferences/gateways/gateway.rs +++ b/src/profile/v100/app_preferences/gateways/gateway.rs @@ -142,7 +142,7 @@ impl Gateway { } pub fn is_wellknown(&self) -> bool { - Self::wellknown().contains(self) + Self::wellknown().contains_by_id(self) } } diff --git a/src/profile/v100/app_preferences/gateways/saved_gateways.rs b/src/profile/v100/app_preferences/gateways/saved_gateways.rs index 6284e0335..eead0c3da 100644 --- a/src/profile/v100/app_preferences/gateways/saved_gateways.rs +++ b/src/profile/v100/app_preferences/gateways/saved_gateways.rs @@ -1,10 +1,9 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( - /// Other by user added or predefined Gateways the user can switch to. +decl_identified_vec_of!( + /// An ordered collection of unique [`Gateway`]s. /// It might be Gateways with different URLs on the SAME network, or /// other networks, the identifier of a Gateway is the URL. - Gateways, Gateway ); @@ -74,7 +73,7 @@ impl<'de> Deserialize<'de> for SavedGateways { .saved .iter() .find(|g| g.id() == wrapped.url) - .cloned() + .clone() .ok_or({ CommonError::InvalidGatewaysJSONCurrentNotFoundAmongstSaved }) @@ -82,7 +81,7 @@ impl<'de> Deserialize<'de> for SavedGateways { let mut other = wrapped.saved.clone(); - other.remove(¤t); + other.remove_id(¤t.id()); SavedGateways::new_with_other(current, other.items()) .map_err(de::Error::custom) @@ -102,7 +101,7 @@ impl SavedGateways { I: IntoIterator, { let other = Gateways::from_iter(other); - if other.contains(¤t) { + if other.contains_by_id(¤t) { return Err( CommonError::GatewaysDiscrepancyOtherShouldNotContainCurrent, ); @@ -126,7 +125,7 @@ impl SavedGateways { CommonError::GatewaysDiscrepancyOtherShouldNotContainCurrent, ); } - self.other.remove_by_id(&to.id()); + self.other.remove_id(&to.id()); self.current = to; Ok(true) } @@ -137,11 +136,7 @@ impl SavedGateways { /// /// - Returns: `true` if it was added, `false` if it was already present (noop) pub fn append(&mut self, gateway: Gateway) -> bool { - if self.other.contains(&gateway) { - return false; - } - self.other.append(gateway); - true + self.other.append(gateway).0 } } @@ -201,6 +196,15 @@ mod tests { assert_eq!(sut.current.network.id, NetworkID::Stokenet); } + #[test] + fn append() { + let mut sut = SUT::sample(); + assert!(!sut.append(Gateway::mainnet())); + assert_eq!(sut, SUT::sample()); + assert!(sut.append(Gateway::kisharnet())); + assert_ne!(sut, SUT::sample()); + } + #[test] fn new_throw_gateways_discrepancy_other_should_not_contain_current() { assert_eq!( diff --git a/src/profile/v100/app_preferences/p2p_links/p2p_links.rs b/src/profile/v100/app_preferences/p2p_links/p2p_links.rs index ab6608754..57e234384 100644 --- a/src/profile/v100/app_preferences/p2p_links/p2p_links.rs +++ b/src/profile/v100/app_preferences/p2p_links/p2p_links.rs @@ -1,10 +1,9 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// Collection of clients user have connected P2P with, typically these /// are WebRTC connections with DApps, but might be Android or iPhone /// clients as well. - P2PLinks, P2PLink ); @@ -34,23 +33,6 @@ mod tests { assert_ne!(P2PLinks::sample(), P2PLinks::sample_other()); } - #[test] - fn display() { - let mut sut = P2PLinks::new(); - sut.append(P2PLink::sample_duckduckgo()); - assert_eq!( - format!("{}", sut), - "[P2PLink( name: 'DuckDuckGo on Mac Pro', password: )]" - ); - } - - #[test] - fn debug() { - let mut sut = P2PLinks::new(); - sut.append(P2PLink::sample_duckduckgo()); - assert_eq!(format!("{:?}", sut), "P2PLinks { secret_magic: P2PLinksSecretMagic([P2PLink { display_name: 'DuckDuckGo on Mac Pro', connection_password: 'deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead' }]) }"); - } - #[test] fn into_iter() { let mut sut = P2PLinks::new(); @@ -101,8 +83,8 @@ mod tests { let c = P2PLink::sample_chrome(); let d = P2PLink::sample_duckduckgo(); let mut sut = P2PLinks::from_iter([&a, &b, &c].into_iter().cloned()); - assert_eq!(sut.elements(), [&a, &b, &c]); - sut.insert(d.clone(), 1); - assert_eq!(sut.elements(), [&a, &d, &b, &c]); + assert_eq!(sut.get_all(), [&a, &b, &c]); + sut.insert_at(d.clone(), 1); + assert_eq!(sut.get_all(), [&a, &d, &b, &c]); } } diff --git a/src/profile/v100/app_preferences/security.rs b/src/profile/v100/app_preferences/security.rs index c9b29a2aa..ca3293430 100644 --- a/src/profile/v100/app_preferences/security.rs +++ b/src/profile/v100/app_preferences/security.rs @@ -4,6 +4,13 @@ use crate::prelude::*; // a field `structure_configuration_references` but no client can populate it yet, so the list will always // be empty, thus save to used a serializable trivial type such as `bool` as a sample for now. pub type SecurityStructureConfigurationReference = bool; +impl Identifiable for SecurityStructureConfigurationReference { + type ID = Self; + + fn id(&self) -> Self::ID { + *self + } +} /// Controls e.g. if Profile Snapshot gets synced to iCloud or not, and whether /// developer mode is enabled or not. In future (MFA) we will also save a list of @@ -29,7 +36,7 @@ pub struct Security { pub is_cloud_profile_sync_enabled: bool, pub is_developer_mode_enabled: bool, pub structure_configuration_references: - IdentifiedVecVia, + IdentifiedVecOf, } impl Security { @@ -37,7 +44,7 @@ impl Security { pub fn new( is_cloud_profile_sync_enabled: bool, is_developer_mode_enabled: bool, - structure_configuration_references: IdentifiedVecVia< + structure_configuration_references: IdentifiedVecOf< SecurityStructureConfigurationReference, >, ) -> Self { @@ -52,19 +59,19 @@ impl Security { impl Default for Security { /// By default we cloud profile sync is enabled and developer mode is disabled, with an empty `structure_configuration_references` list. fn default() -> Self { - Self::new(true, false, IdentifiedVecVia::new()) + Self::new(true, false, IdentifiedVecOf::new()) } } impl HasSampleValues for Security { /// A sample used to facilitate unit tests. fn sample() -> Self { - Self::new(true, true, IdentifiedVecVia::new()) + Self::new(true, true, IdentifiedVecOf::new()) } /// A sample used to facilitate unit tests. fn sample_other() -> Self { - Self::new(false, false, IdentifiedVecVia::new()) + Self::new(false, false, IdentifiedVecOf::new()) } } diff --git a/src/profile/v100/entity/account/account.rs b/src/profile/v100/entity/account/account.rs index fcd22b7a3..f45889d3d 100644 --- a/src/profile/v100/entity/account/account.rs +++ b/src/profile/v100/entity/account/account.rs @@ -190,7 +190,7 @@ impl Account { AppearanceID::try_from(index as u8).unwrap(), ); if is_hidden { - account.flags.insert_flag(EntityFlag::DeletedByUser); + account.flags.insert(EntityFlag::DeletedByUser); } account } diff --git a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/assets_exception_list.rs b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/assets_exception_list.rs index afded0f40..86b607cf3 100644 --- a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/assets_exception_list.rs +++ b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/assets_exception_list.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// Denies or allows third-party deposits of specific assets by ignoring the `depositMode` AssetsExceptionList, AssetException diff --git a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/depositors_allow_list.rs b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/depositors_allow_list.rs index 4551fc5eb..7eab56d0a 100644 --- a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/depositors_allow_list.rs +++ b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/depositors_allow_list.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// Allows certain third-party depositors to deposit assets freely. /// Note: There is no `deny` counterpart for this. DepositorsAllowList, diff --git a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/third_party_deposits.rs b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/third_party_deposits.rs index b1f3932ad..767c362fe 100644 --- a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/third_party_deposits.rs +++ b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/third_party_deposits.rs @@ -107,7 +107,7 @@ impl ThirdPartyDeposits { exception: &AssetException, ) -> bool { if let Some(mut list) = self.assets_exception_list.clone() { - let was_present = list.remove(exception).is_some(); + let was_present = list.remove_id(&exception.id()).is_some(); self.assets_exception_list = Some(list); was_present } else { @@ -142,7 +142,7 @@ impl ThirdPartyDeposits { depositor: &ResourceOrNonFungible, ) -> bool { if let Some(mut list) = self.depositors_allow_list.clone() { - let was_present = list.remove(depositor).is_some(); + let was_present = list.remove_id(&depositor.id()).is_some(); self.depositors_allow_list = Some(list); was_present } else { @@ -319,8 +319,10 @@ mod tests { depositors_allow_list: None, }; assert!(sut.add_asset_exception(AssetException::sample())); - assert!((*sut.assets_exception_list.unwrap()) - .contains(&AssetException::sample())); + assert!(sut + .assets_exception_list + .unwrap() + .contains_by_id(&AssetException::sample())); } #[test] @@ -331,8 +333,10 @@ mod tests { depositors_allow_list: None, }; assert!(sut.allow_depositor(ResourceOrNonFungible::sample())); - assert!((*sut.depositors_allow_list.unwrap()) - .contains(&ResourceOrNonFungible::sample())); + assert!(sut + .depositors_allow_list + .unwrap() + .contains_by_id(&ResourceOrNonFungible::sample())); } #[test] diff --git a/src/profile/v100/entity/entity_flags.rs b/src/profile/v100/entity/entity_flags.rs index 0abdd9a2c..36f45b6dc 100644 --- a/src/profile/v100/entity/entity_flags.rs +++ b/src/profile/v100/entity/entity_flags.rs @@ -1,10 +1,9 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// An order set of `EntityFlag`s used to describe certain Off-ledger /// user state about Accounts or Personas, such as if an entity is /// marked as hidden or not. - EntityFlags, EntityFlag ); @@ -28,7 +27,7 @@ impl EntityFlags { } pub fn remove_flag(&mut self, flag: &EntityFlag) -> Option { - self.remove(flag) + self.remove_id(&flag.id()) } } @@ -56,13 +55,13 @@ mod tests { #[test] fn default_does_not_contain_deleted_by_user() { - assert!(!SUT::default().contains(&EntityFlag::DeletedByUser)); + assert!(!SUT::default().contains_by_id(&EntityFlag::DeletedByUser)); } #[test] fn new_with_f_contains_f() { assert!(SUT::just(EntityFlag::DeletedByUser) - .contains(&EntityFlag::DeletedByUser)); + .contains_by_id(&EntityFlag::DeletedByUser)); } #[test] @@ -84,7 +83,7 @@ mod tests { #[test] fn new_with_duplicates_of_f_contains_only_f() { assert_eq!( - SUT::with_entity_flags(vec![ + SUT::from_iter([ EntityFlag::DeletedByUser, EntityFlag::DeletedByUser ]) @@ -97,7 +96,7 @@ mod tests { fn new_empty_insert_f_contains_f() { let mut sut = SUT::default(); sut.insert_flag(EntityFlag::DeletedByUser); - assert!(sut.contains(&EntityFlag::DeletedByUser)); + assert!(sut.contains_by_id(&EntityFlag::DeletedByUser)); } #[test] diff --git a/src/profile/v100/entity/persona/persona.rs b/src/profile/v100/entity/persona/persona.rs index eec8e578d..3b1d7d3e7 100644 --- a/src/profile/v100/entity/persona/persona.rs +++ b/src/profile/v100/entity/persona/persona.rs @@ -151,7 +151,7 @@ impl Persona { PersonaData::new(name, phone_numbers, email_addresses), ); if is_hidden { - persona.flags.insert_flag(EntityFlag::DeletedByUser); + persona.flags.insert(EntityFlag::DeletedByUser); } persona } @@ -394,7 +394,7 @@ impl PartialOrd for Persona { } } -/// Add conformance to Identifiable in order to use `identified_vec` +/// Add conformance to Identifiable in order to use `IdentifiedVecOf` impl Identifiable for Persona { type ID = IdentityAddress; diff --git a/src/profile/v100/entity/persona/persona_data/persona_data.rs b/src/profile/v100/entity/persona/persona_data/persona_data.rs index ab9879cc0..fc4380b4a 100644 --- a/src/profile/v100/entity/persona/persona_data/persona_data.rs +++ b/src/profile/v100/entity/persona/persona_data/persona_data.rs @@ -103,7 +103,6 @@ impl PersonaData { let phones = self .phone_numbers .iter() - .cloned() .map(|v| { if include_id { v.dbg_string() @@ -117,7 +116,6 @@ impl PersonaData { let emails = self .email_addresses .iter() - .cloned() .map(|v| { if include_id { v.dbg_string() diff --git a/src/profile/v100/entity/persona/persona_data/persona_data_identified_collection_types.rs b/src/profile/v100/entity/persona/persona_data/persona_data_identified_collection_types.rs index 802316e94..ab02ece40 100644 --- a/src/profile/v100/entity/persona/persona_data/persona_data_identified_collection_types.rs +++ b/src/profile/v100/entity/persona/persona_data/persona_data_identified_collection_types.rs @@ -34,7 +34,7 @@ macro_rules! declare_collection_of_identified_entry { #[display("{}", self.display_string())] #[serde(transparent)] pub struct $struct_name { - pub collection: IdentifiedVecVia<$id_ent_type>, + pub collection: IdentifiedVecOf<$id_ent_type>, } impl Default for $struct_name { @@ -44,7 +44,7 @@ macro_rules! declare_collection_of_identified_entry { } impl std::ops::Deref for $struct_name { - type Target = IdentifiedVecVia<$id_ent_type>; + type Target = IdentifiedVecOf<$id_ent_type>; fn deref(&self) -> &Self::Target { &self.collection } @@ -57,15 +57,15 @@ macro_rules! declare_collection_of_identified_entry { I: IntoIterator, { Self { - collection: IdentifiedVecVia::from_iter(values), + collection: IdentifiedVecOf::from_iter(values), } } } - impl IntoIterator for $struct_name { + impl<'a> IntoIterator for &'a $struct_name { type Item = $id_ent_type; type IntoIter = - identified_vec::identified_vec_into_iterator::IdentifiedVecIntoIterator<<$id_ent_type as Identifiable>::ID, $id_ent_type>; + IdentifiedVecOfIterator<'a, $id_ent_type>; fn into_iter(self) -> Self::IntoIter { self.collection.into_iter() diff --git a/src/profile/v100/factors/factor_source_common.rs b/src/profile/v100/factors/factor_source_common.rs index 7f14e791f..c68be852e 100644 --- a/src/profile/v100/factors/factor_source_common.rs +++ b/src/profile/v100/factors/factor_source_common.rs @@ -1,7 +1,7 @@ use crate::prelude::*; /// Flags which describe a certain state a FactorSource might be in, e.g. `Main` (BDFS). -pub type FactorSourceFlags = IdentifiedVecVia; +pub type FactorSourceFlags = IdentifiedVecOf; impl Identifiable for FactorSourceFlag { type ID = Self; @@ -98,7 +98,8 @@ impl FactorSourceCommon { /// Checks if its Main Babylon Device Factor Source (BDFS). pub fn is_main_bdfs(&self) -> bool { - self.supports_babylon() && self.flags.contains(&FactorSourceFlag::Main) + self.supports_babylon() + && self.flags.contains_by_id(&FactorSourceFlag::Main) } } @@ -228,7 +229,7 @@ mod tests { fn main_flag_present_if_main() { assert!(FactorSourceCommon::new_bdfs(true) .flags - .contains(&FactorSourceFlag::Main)); + .contains_by_id(&FactorSourceFlag::Main)); } #[test] diff --git a/src/profile/v100/factors/factor_source_crypto_parameters.rs b/src/profile/v100/factors/factor_source_crypto_parameters.rs index c5f60504b..93a84ea0a 100644 --- a/src/profile/v100/factors/factor_source_crypto_parameters.rs +++ b/src/profile/v100/factors/factor_source_crypto_parameters.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -decl_never_empty_identified_array_of!( +decl_identified_vec_of!( /// A collection of [`SLIP10Curve`]s that a factor source supports. /// MUST never be empty. SupportedCurves, @@ -30,7 +30,7 @@ pub struct FactorSourceCryptoParameters { /// /// Either BIP44 or CAP26 (SLIP10) pub supported_derivation_path_schemes: - IdentifiedVecVia, + IdentifiedVecOf, } impl FactorSourceCryptoParameters { @@ -40,9 +40,12 @@ impl FactorSourceCryptoParameters { I: IntoIterator, J: IntoIterator, { - let supported_curves = SupportedCurves::from_iter(curves).map_err(|_| CommonError::FactorSourceCryptoParametersSupportedCurvesInvalidSize)?; + let supported_curves = SupportedCurves::from_iter(curves); + if supported_curves.is_empty() { + return Err(CommonError::FactorSourceCryptoParametersSupportedCurvesInvalidSize); + } let supported_derivation_path_schemes = - IdentifiedVecVia::from_iter(schemes); + IdentifiedVecOf::from_iter(schemes); Ok(Self { supported_curves, @@ -75,17 +78,19 @@ impl FactorSourceCryptoParameters { } pub fn supports_olympia(&self) -> bool { - self.supported_curves.contains(&SLIP10Curve::Secp256k1) + self.supported_curves + .contains_by_id(&SLIP10Curve::Secp256k1) && self .supported_derivation_path_schemes - .contains(&DerivationPathScheme::Bip44Olympia) + .contains_by_id(&DerivationPathScheme::Bip44Olympia) } pub fn supports_babylon(&self) -> bool { - self.supported_curves.contains(&SLIP10Curve::Curve25519) + self.supported_curves + .contains_by_id(&SLIP10Curve::Curve25519) && self .supported_derivation_path_schemes - .contains(&DerivationPathScheme::Cap26) + .contains_by_id(&DerivationPathScheme::Cap26) } } @@ -115,14 +120,16 @@ impl HasSampleValues for SupportedCurves { SLIP10Curve::Curve25519, SLIP10Curve::Secp256k1, ]) - .unwrap() } } - #[cfg(test)] mod tests { - use super::*; + use uniffi::{ + check_remaining, + deps::bytes::{Buf, BufMut}, + metadata, Lift, Lower, LowerReturn, MetadataBuffer, RustBuffer, + }; #[allow(clippy::upper_case_acronyms)] type SUT = FactorSourceCryptoParameters; @@ -136,6 +143,19 @@ mod tests { ); } + #[test] + fn manual_uniffi_conversion_fails_if_supported_curves_empty() { + // This is some advanced techniques... + let mut bad_value_from_ffi_vec = Vec::new(); + bad_value_from_ffi_vec.put_i32(0); // empty, not allowed + let bad_value_from_ffi = RustBuffer::from_vec(bad_value_from_ffi_vec); + let res = + as Lift>::try_lift( + bad_value_from_ffi, + ); + assert!(res.is_err()); + } + #[test] fn inequality() { assert_ne!(SupportedCurves::sample(), SupportedCurves::sample_other()); @@ -159,7 +179,7 @@ mod tests { .supported_derivation_path_schemes .first() .unwrap(), - DerivationPathScheme::Cap26 + &DerivationPathScheme::Cap26 ); } @@ -170,7 +190,7 @@ mod tests { .supported_curves .first() .unwrap(), - SLIP10Curve::Curve25519 + &SLIP10Curve::Curve25519 ); } @@ -199,7 +219,7 @@ mod tests { .supported_derivation_path_schemes .first() .unwrap(), - DerivationPathScheme::Cap26 + &DerivationPathScheme::Cap26 ); } @@ -207,50 +227,62 @@ mod tests { fn babylon_does_not_support_secp256k1() { assert!(!SUT::babylon() .supported_curves - .contains(&SLIP10Curve::Secp256k1)); + .contains_by_id(&SLIP10Curve::Secp256k1)); } #[test] fn babylon_does_not_support_bip44() { assert!(!SUT::babylon() .supported_derivation_path_schemes - .contains(&DerivationPathScheme::Bip44Olympia)); + .contains_by_id(&DerivationPathScheme::Bip44Olympia)); } #[test] fn olympia_does_not_support_curve25519() { assert!(!SUT::olympia() .supported_curves - .contains(&SLIP10Curve::Curve25519)); + .contains_by_id(&SLIP10Curve::Curve25519)); } #[test] fn olympia_does_not_support_cap26() { assert!(!SUT::olympia() .supported_derivation_path_schemes - .contains(&DerivationPathScheme::Cap26)); + .contains_by_id(&DerivationPathScheme::Cap26)); } #[test] fn babylon_olympia_compat_has_supports_curve25519() { assert!(SUT::babylon_olympia_compatible() .supported_curves - .contains(&SLIP10Curve::Curve25519)); + .contains_by_id(&SLIP10Curve::Curve25519)); } #[test] fn babylon_olympia_compat_supports_cap26() { assert!(SUT::babylon_olympia_compatible() .supported_derivation_path_schemes - .contains(&DerivationPathScheme::Cap26)); + .contains_by_id(&DerivationPathScheme::Cap26)); } #[test] - fn curves_must_not_be_empty() { - assert_eq!( - SUT::new([], []), - Err(CommonError::FactorSourceCryptoParametersSupportedCurvesInvalidSize) - ); + fn json_serialize_supported_curves_empty_is_err() { + assert!(serde_json::to_value(SupportedCurves::new()).is_err()); + } + + #[test] + fn json_serialize_parameters_with_empty_curves_empty_is_err() { + let mut sut = SUT::sample(); + sut.supported_curves = SupportedCurves::new(); + assert!(serde_json::to_value(sut).is_err()); + } + + #[test] + fn json_deserialize_of_empty_supported_curves_is_err() { + assert!(serde_json::from_value::( + serde_json::Value::Array(Vec::new()) + ) + .is_err()); } #[test] diff --git a/src/profile/v100/factors/factor_sources/factor_sources.rs b/src/profile/v100/factors/factor_sources/factor_sources.rs index 80f4a0e65..75eed3844 100644 --- a/src/profile/v100/factors/factor_sources/factor_sources.rs +++ b/src/profile/v100/factors/factor_sources/factor_sources.rs @@ -1,9 +1,8 @@ use crate::prelude::*; -decl_never_empty_identified_array_of!( +decl_identified_vec_of!( /// A collection of [`FactorSource`]s generated by a wallet or manually added by user. /// MUST never be empty. - FactorSources, FactorSource ); @@ -22,7 +21,6 @@ impl HasSampleValues for FactorSources { FactorSource::sample_device(), FactorSource::sample_ledger(), ]) - .unwrap() } fn sample_other() -> Self { @@ -30,14 +28,17 @@ impl HasSampleValues for FactorSources { FactorSource::sample_device_olympia(), FactorSource::sample_device_babylon(), ]) - .unwrap() } } - #[cfg(test)] mod tests { use super::*; + use uniffi::{ + check_remaining, + deps::bytes::{Buf, BufMut}, + metadata, Lift, Lower, LowerReturn, MetadataBuffer, RustBuffer, + }; #[allow(clippy::upper_case_acronyms)] type SUT = FactorSources; @@ -50,34 +51,47 @@ mod tests { ) } + #[test] + fn factor_sources_sample_is_not_empty() { + assert_eq!(SUT::sample().len(), 2); + assert_eq!(SUT::sample().get_all().len(), 2); + assert_eq!(SUT::sample().ids().len(), 2); + assert!(!SUT::sample().is_empty()); + } + #[test] fn inequality() { assert_ne!(SUT::sample(), SUT::sample_other()); } + #[test] + fn manual_uniffi_conversion_fails_if_factor_sources_is_empty() { + // This is some advanced techniques... + let mut bad_value_from_ffi_vec = Vec::new(); + bad_value_from_ffi_vec.put_i32(0); // empty, not allowed + let bad_value_from_ffi = RustBuffer::from_vec(bad_value_from_ffi_vec); + let res = + as Lift>::try_lift( + bad_value_from_ffi, + ); + assert!(res.is_err()); + } + #[test] fn duplicates_are_prevented() { assert_eq!( SUT::from_iter( [FactorSource::sample(), FactorSource::sample()].into_iter() ) - .unwrap() .len(), 1 ) } #[test] - fn remove_returns_err_if_empty() { - let fs = FactorSource::sample(); - let sut = SUT::from_iter([fs.clone()]).unwrap(); - assert_eq!(sut.len(), 1); - assert_eq!( - new_factor_sources_removed_by_id(&fs.id(), &sut), - Err(CommonError::FactorSourcesMustNotBeEmpty) - ); + fn json_serialize_of_empty_factor_sources_is_err() { + assert!(serde_json::to_value(SUT::new()).is_err()); } - #[test] fn json_deserialize_of_empty_factor_sources_is_err() { assert!(serde_json::from_value::(serde_json::Value::Array( diff --git a/src/profile/v100/header/header.rs b/src/profile/v100/header/header.rs index 4932e39a6..934dfb872 100644 --- a/src/profile/v100/header/header.rs +++ b/src/profile/v100/header/header.rs @@ -240,7 +240,6 @@ mod uniffi_tests { #[test] fn header_identifiable() { - use identified_vec::Identifiable; let sut = SUT::sample(); assert_eq!(&sut.id(), &sut.id); } diff --git a/src/profile/v100/identified_elements.rs b/src/profile/v100/identified_elements.rs deleted file mode 100644 index 05981448c..000000000 --- a/src/profile/v100/identified_elements.rs +++ /dev/null @@ -1,714 +0,0 @@ -/// General rules for identified_array_of implementations -macro_rules! decl_identified_array_of { - ( - $( - #[doc = $expr: expr] - )* - $struct_type: ident, - $element_type: ty, - $collection_type: ty - ) => { - use std::ops::DerefMut; - use $crate::prelude::*; - - paste! { - $( - #[doc = $expr] - )* - #[derive(Clone, Eq, PartialEq, Hash, derive_more::Debug, derive_more::Display, uniffi::Record)] - pub struct $struct_type { - secret_magic: [< $struct_type SecretMagic >] - } - - #[derive(Clone, Eq, PartialEq, Hash, derive_more::Debug, derive_more::Display, Serialize, Deserialize)] - pub struct [< $struct_type SecretMagic>]($collection_type); - - uniffi::custom_type!([< $struct_type SecretMagic >], $collection_type); - - impl $crate::UniffiCustomTypeConverter for [< $struct_type SecretMagic >] { - type Builtin = $collection_type; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Ok(Self(val)) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.0 - } - } - - impl $struct_type { - /// Returns a reference to the element identified by `id`, if it exists. - pub fn [< get_ $element_type:snake _by_id>]( - &self, - id: &<[< $element_type >] as Identifiable>::ID, - ) -> Option<&[< $element_type >]> { - self.get(id) - } - - /// Returns a reference to the element by `index`, if it exists. - pub fn [< get_ $element_type:snake _at_index>]( - &self, - index: usize, - ) -> Option<&[< $element_type >]> { - self.get_at_index(index) - } - - /// Returns references to **all** $struct_type, including hidden ones. - pub fn get_all(&self) -> Vec<&[< $element_type >]> { - self.elements() - } - } - - #[uniffi::export] - pub fn [< new_ $struct_type:snake _with_ $element_type:snake >]([< $element_type:snake >]: $element_type) -> $struct_type { - $struct_type::just([< $element_type:snake >]) - } - - impl IntoIterator for $struct_type { - type Item = $element_type; - type IntoIter = - identified_vec::identified_vec_into_iterator::IdentifiedVecIntoIterator<<$element_type as Identifiable>::ID, $element_type>; - - fn into_iter(self) -> Self::IntoIter { - self.secret_magic.0.into_iter() - } - } - - impl Deref for $struct_type { - type Target = $collection_type; - - fn deref(&self) -> &Self::Target { - &self.secret_magic.0 - } - } - - impl DerefMut for $struct_type { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.secret_magic.0 - } - } - - #[uniffi::export] - pub fn [<$struct_type:snake _get_elements>]( - [< $struct_type:snake >]: $struct_type, - ) -> IdentifiedVecVia<$element_type> { - (*[< $struct_type:snake >]).clone() - } - - #[uniffi::export] - pub fn [< $struct_type:snake _get_ $element_type:snake _by_id>]( - [< $struct_type:snake >]: &$struct_type, - id: &<[< $element_type >] as Identifiable>::ID, - ) -> Option<[< $element_type >]> { - [< $struct_type:snake >].[< get_ $element_type:snake _by_id>](id).cloned() - } - - #[uniffi::export] - pub fn [< $struct_type:snake _get_ $element_type:snake _at_index>]( - [< $struct_type:snake >]: &$struct_type, - index: u64, - ) -> Option<[< $element_type >]> { - [< $struct_type:snake >].[< get_ $element_type:snake _at_index>](index as usize).cloned() - } - - #[uniffi::export] - pub fn [<$struct_type:snake _element_count>]( - [< $struct_type:snake >]: &$struct_type, - ) -> u64 { - (*[< $struct_type:snake >]).len() as u64 - } - - #[uniffi::export] - pub fn []( - [< $element_type:snake >]: $element_type, - to: &$struct_type, - ) -> $struct_type { - let mut copy = to.clone(); - let _ = (*copy).append([< $element_type:snake >]); - copy - } - - #[uniffi::export] - pub fn []( - [< $element_type:snake >]: $element_type, - to: &$struct_type, - ) -> $struct_type { - let mut copy = to.clone(); - let _ = (*copy).update_or_append([< $element_type:snake >]); - copy - } - - #[uniffi::export] - pub fn []( - [< $element_type:snake >]: $element_type, - to: &$struct_type, - index: u64, - ) -> $struct_type { - let mut copy = to.clone(); - let _ = (*copy).update_or_insert([< $element_type:snake >], index as usize); - copy - } - - #[uniffi::export] - pub fn [< new_ $struct_type:snake _sample >]() -> $struct_type { - $struct_type::sample() - } - - #[uniffi::export] - pub fn [< new_ $struct_type:snake _sample_other >]() -> $struct_type { - $struct_type::sample_other() - } - - #[cfg(test)] - mod [] { - use super::*; - - #[allow(clippy::upper_case_acronyms)] - type SUT = $struct_type; - - #[allow(clippy::upper_case_acronyms)] - type SUTSecretMagic = [< $struct_type SecretMagic >]; - - #[allow(clippy::upper_case_acronyms)] - type SUTElement = $element_type; - - #[test] - fn equality() { - assert_eq!(SUT::sample(), SUT::sample()); - assert_eq!(SUT::sample_other(), SUT::sample_other()); - } - - #[test] - fn inequality() { - assert_ne!(SUT::sample(), SUT::sample_other()); - } - - #[test] - fn manual_perform_uniffi_conversion() { - let sut = SUT::sample(); - let identified_array = (*sut).clone(); - let secret_magic = sut.secret_magic; - - let ffi_side = - ::from_custom(secret_magic.clone()); - assert_eq!(ffi_side, identified_array); - let from_ffi_side = - ::into_custom(ffi_side) - .unwrap(); - assert_eq!(secret_magic, from_ffi_side); - } - - #[test] - fn test_new_with_single_element() { - let sut_element = SUTElement::sample(); - let sut = $struct_type::just(sut_element.clone()); - assert_eq!(sut.items(), vec![sut_element]); - } - - #[test] - fn test_get_element_by_id() { - let sut_element = SUTElement::sample(); - let sut = $struct_type::just(sut_element.clone()); - assert_eq!( - sut.[< get_ $element_type:snake _by_id>](&sut_element.id()), - Some(&sut_element) - ); - } - - #[test] - fn test_length() { - let sut_element = SUTElement::sample(); - let mut sut = $struct_type::just(sut_element.clone()); - assert_eq!( - sut.len(), - 1 - ); - _ = (*sut).append(SUTElement::sample_other()); - assert_eq!( - sut.len(), - 2 - ); - } - - } - - #[cfg(test)] - mod [] { - use super::*; - - #[allow(clippy::upper_case_acronyms)] - type SUT = $struct_type; - - #[allow(clippy::upper_case_acronyms)] - type SUTElement = $element_type; - - #[test] - fn get_elements() { - let sut = SUT::sample(); - let elements = (*sut).clone(); - - assert_eq!( - elements, - [<$struct_type:snake _get_elements>](sut) - ); - } - - #[test] - fn test_get_at_index() { - let a = SUTElement::sample(); - let b = SUTElement::sample_other(); - let mut sut = SUT::just(a.clone()); - sut.append(b.clone()); - - assert_eq!( - [< $struct_type:snake _get_ $element_type:snake _at_index>](&sut, 0), - Some(a) - ); - assert_eq!( - [< $struct_type:snake _get_ $element_type:snake _at_index>](&sut, 1), - Some(b) - ); - assert_eq!( - [< $struct_type:snake _get_ $element_type:snake _at_index>](&sut, 2), - None - ); - } - - #[test] - fn test_new_with_single_element() { - let sut_element = SUTElement::sample(); - let sut = [< new_ $struct_type:snake _with_ $element_type:snake >](sut_element.clone()); - assert_eq!( - sut, - $struct_type::just(sut_element.clone()) - ) - } - - #[test] - fn test_get_element_by_id() { - let sut_element = SUTElement::sample(); - let sut = $struct_type::just(sut_element.clone()); - assert_eq!( - [< $struct_type:snake _get_ $element_type:snake _by_id>](&sut, &sut_element.id()), - Some(sut_element) - ); - } - - #[test] - fn test_new_appending_and_length() { - let sut_element = SUTElement::sample(); - let sut = $struct_type::just(sut_element.clone()); - assert_eq!( - [<$struct_type:snake _element_count>](&sut), - 1 - ); - let sut = [](SUTElement::sample_other(), &sut); - assert_eq!( - [<$struct_type:snake _element_count>](&sut), - 2 - ); - } - - #[test] - fn test_new_updating_or_appending() { - let sut_element = SUTElement::sample(); - let sut = $struct_type::just(sut_element.clone()); - assert_eq!( - [<$struct_type:snake _element_count>](&sut), - 1 - ); - let sut = [](SUTElement::sample_other(), &sut); - assert_eq!( - [<$struct_type:snake _element_count>](&sut), - 2 - ); - } - - #[test] - fn test_new_updating_or_inserting_at() { - let sut_element = SUTElement::sample(); - let sut = $struct_type::just(sut_element.clone()); - assert_eq!( - [<$struct_type:snake _element_count>](&sut), - 1 - ); - let sut = [](SUTElement::sample_other(), &sut, 0); - - assert_eq!( - vec![SUTElement::sample_other(), SUTElement::sample()], - [<$struct_type:snake _get_elements>](sut).items() - ); - } - } - } - }; -} - -/// Impl rules for identified_array_of implementations which can be empty -macro_rules! decl_can_be_empty_impl { - ( - $struct_type: ty, - $element_type: ty, - $secret_magic: ty - ) => { - paste! { - - impl FromIterator<$element_type> for $struct_type { - fn from_iter([< $struct_type:lower >]: I) -> Self - where - I: IntoIterator, - { - Self { - secret_magic: $secret_magic(IdentifiedVecVia::from_iter([< $struct_type:lower >])) - } - } - - } - - impl Serialize for $struct_type { - fn serialize( - &self, - serializer: S, - ) -> Result<::Ok, ::Error> - where - S: Serializer, - { - self.secret_magic.serialize(serializer) - } - } - - impl<'de> serde::Deserialize<'de> for $struct_type { - fn deserialize>( - d: D, - ) -> Result<$struct_type, D::Error> { - $secret_magic::deserialize(d).map(|secret_magic| { - $struct_type { - secret_magic - } - }) - .map_err(de::Error::custom) - } - } - - #[uniffi::export] - pub fn []( - [< id_of_ $element_type:snake >]: &<[< $element_type >] as Identifiable>::ID, - from: &$struct_type, - ) -> $struct_type { - let mut copy = from.clone(); - let _ = (*copy).remove_by_id([< id_of_ $element_type:snake >]); - copy - } - - #[uniffi::export] - pub fn []( - [< $element_type:snake >]: &$element_type, - from: &$struct_type, - ) -> $struct_type { - let mut copy = from.clone(); - let _ = (*copy).remove([< $element_type:snake >]); - copy - } - - impl $struct_type { - - /// Creates a new empty collection. - pub fn new() -> Self { - Self::from_iter([]) - } - - pub fn [< with_ $struct_type:snake >]([< $struct_type:snake >]: I) -> Self - where - I: IntoIterator, - { - Self::from_iter([< $struct_type:snake >]) - } - - pub fn just([< $element_type:snake >]: $element_type) -> Self { - Self::from_iter([[< $element_type:snake >]]) - } - } - - // Trait: Default - impl Default for $struct_type { - /// Instantiates a new empty collection. - fn default() -> Self { - Self::from_iter([]) - } - } - - #[uniffi::export] - pub fn []( - [< $struct_type:snake >]: IdentifiedVecVia<$element_type>, - ) -> $struct_type { - $struct_type::from_iter([< $struct_type:snake >]) - } - - #[cfg(test)] - mod [] { - use super::*; - - #[allow(clippy::upper_case_acronyms)] - type SUT = $struct_type; - - #[allow(clippy::upper_case_acronyms)] - type SUTElement = $element_type; - - #[test] - fn new_from_empty() { - let sut = [](IdentifiedVecVia::from_iter([])); - assert_eq!( - 0, - sut.len() - ); - } - - #[test] - fn new_from_value() { - let sut = []( IdentifiedVecVia::from_iter([SUTElement::sample()]) ); - assert_eq!( - 1, - sut.len() - ); - } - - #[test] - fn remove_by_id_to_empty() { - let sut_element = SUTElement::sample(); - let old = SUT::just(sut_element.clone()); - let new = [](&sut_element.id(), &old); - assert_eq!(old.len(), 1); - assert_eq!(new.len(), 0); - } - - #[test] - fn remove_by_element() { - let sut_element = SUTElement::sample(); - let old = SUT::just(sut_element.clone()); - let new = [](&sut_element, &old); - assert_eq!(old.len(), 1); - assert_eq!(new.len(), 0); - } - } - } - } -} - -/// Impl rules for identified_array_of implementations which must not be empty -macro_rules! decl_never_empty_impl { - ( - $struct_type: ty, - $element_type: ty, - $secret_magic: ty - ) => { - paste! { - - impl Serialize for $struct_type { - fn serialize( - &self, - serializer: S, - ) -> Result<::Ok, ::Error> - where - S: Serializer, - { - self.secret_magic.serialize(serializer) - } - } - - impl<'de> serde::Deserialize<'de> for $struct_type { - fn deserialize>( - d: D, - ) -> Result<$struct_type, D::Error> { - Vec::<$element_type>::deserialize(d) - .and_then(|vec| { - Self::from_iter(vec.into_iter()) - .map_err(de::Error::custom) - }) - .map_err(de::Error::custom) - } - } - - #[uniffi::export] - pub fn []( - [< id_of_ $element_type:snake >]: &<[< $element_type >] as Identifiable>::ID, - from: &$struct_type, - ) -> Result<$struct_type> { - let mut copy = from.clone(); - let _ = (*copy).remove_by_id([< id_of_ $element_type:snake >]); - if copy.is_empty() { - Err(CommonError::[< $struct_type MustNotBeEmpty >]) - } else { - Ok(copy) - } - } - - #[uniffi::export] - pub fn []( - [< $element_type:snake >]: &$element_type, - from: &$struct_type, - ) -> Result<$struct_type> { - let mut copy = from.clone(); - let _ = (*copy).remove([< $element_type:snake >]); - if copy.is_empty() { - Err(CommonError::[< $struct_type MustNotBeEmpty >]) - } else { - Ok(copy) - } - } - - impl $struct_type { - - #[allow(clippy::should_implement_trait)] - pub fn from_iter([< $struct_type:snake >]: I) -> Result - where - I: IntoIterator, - { - let vector = IdentifiedVecVia::from_iter([< $struct_type:snake >]); - if vector.is_empty() { - Err(CommonError::[< $struct_type MustNotBeEmpty >]) - } else { - Ok(Self { - secret_magic: $secret_magic(vector) - }) - } - } - - pub fn just([< $element_type:snake >]: $element_type) -> Self { - Self::from_iter([[< $element_type:snake >]]).unwrap() - } - } - - #[uniffi::export] - pub fn []( - [< $struct_type:snake >]: IdentifiedVecVia<$element_type>, - ) -> Result<$struct_type> { - $struct_type::from_iter([< $struct_type:snake >]) - } - - #[cfg(test)] - mod [] { - use super::*; - - - #[allow(clippy::upper_case_acronyms)] - type SUT = $struct_type; - - #[allow(clippy::upper_case_acronyms)] - type SUTElement = $element_type; - - - #[test] - #[should_panic] - fn new_from_empty_error() { - [](IdentifiedVecVia::from_iter([])).unwrap(); - } - - #[test] - fn new_from_value() { - let sut = []( IdentifiedVecVia::from_iter([[< $element_type >]::sample()]) ).unwrap(); - assert_eq!( - 1, - sut.len() - ); - } - - #[test] - fn remove_by_id_to_empty_throws() { - let sut_element = SUTElement::sample(); - let sut = SUT::just(sut_element.clone()); - assert!( - [](&sut_element.id(), &sut).is_err() - ); - } - - #[test] - fn remove_by_element_empty_throws() { - let sut_element = SUTElement::sample(); - let sut = SUT::just(sut_element.clone()); - assert!( - [](&sut_element, &sut).is_err() - ); - } - - #[test] - fn remove_by_id_from_two_elements_to_one_is_ok() { - let sut_element = SUTElement::sample(); - let old = SUT::from_iter([sut_element.clone(), SUTElement::sample_other()]).unwrap(); - let new = [](&sut_element.id(), &old).unwrap(); - assert_eq!(old.len(), 2); - assert_eq!(new.len(), 1); - } - - #[test] - fn remove_by_element_from_two_elements_to_one_is_ok() { - let sut_element = SUTElement::sample(); - let old = SUT::from_iter([sut_element.clone(), SUTElement::sample_other()]).unwrap(); - let new = [](&sut_element, &old).unwrap(); - assert_eq!(old.len(), 2); - assert_eq!(new.len(), 1); - } - } - } - } -} - -macro_rules! decl_can_be_empty_identified_array_of { - ( - $( - #[doc = $expr: expr] - )* - $struct_type: ty, - $element_type: ty - ) => { - paste! { - decl_identified_array_of!( - $( - #[doc = $expr] - )* - $struct_type, - $element_type, - IdentifiedVecVia<$element_type> - ); - - decl_can_be_empty_impl!( - $struct_type, - $element_type, - [< $struct_type SecretMagic >] - ); - } - }; -} - -macro_rules! decl_never_empty_identified_array_of { - ( - $( - #[doc = $expr: expr] - )* - $struct_type: ty, - $element_type: ty - ) => { - paste! { - decl_identified_array_of!( - $( - #[doc = $expr] - )* - $struct_type, - $element_type, - IdentifiedVecVia<$element_type> - ); - - decl_never_empty_impl!( - $struct_type, - $element_type, - [< $struct_type SecretMagic >] - ); - } - }; -} - -pub(crate) use decl_can_be_empty_identified_array_of; -pub(crate) use decl_can_be_empty_impl; -pub(crate) use decl_identified_array_of; -pub(crate) use decl_never_empty_identified_array_of; -pub(crate) use decl_never_empty_impl; diff --git a/src/profile/v100/mod.rs b/src/profile/v100/mod.rs index 2c2a3467e..36d62336f 100644 --- a/src/profile/v100/mod.rs +++ b/src/profile/v100/mod.rs @@ -4,7 +4,6 @@ mod entity; mod entity_security_state; mod factors; mod header; -mod identified_elements; mod json_data_convertible; mod networks; mod profile; @@ -18,7 +17,6 @@ pub use entity::*; pub use entity_security_state::*; pub use factors::*; pub use header::*; -pub use identified_elements::*; pub use json_data_convertible::*; pub use networks::*; pub use profile::*; diff --git a/src/profile/v100/networks/network/accounts.rs b/src/profile/v100/networks/network/accounts.rs index e1f92db54..94f21337b 100644 --- a/src/profile/v100/networks/network/accounts.rs +++ b/src/profile/v100/networks/network/accounts.rs @@ -1,10 +1,9 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// An ordered set of [`Account`]s on a specific network, most commonly /// the set is non-empty, since wallets guide user to create a first /// Account. - Accounts, Account ); @@ -89,7 +88,7 @@ mod tests { AppearanceID::default(), ); let accounts = SUT::just(account.clone()); - assert_eq!(accounts.get_account_by_id(&address), Some(&account)); + assert_eq!(accounts.get_id(&address), Some(&account)); } #[test] @@ -99,95 +98,95 @@ mod tests { &sut, r#" [ - { - "securityState": { - "unsecuredEntityControl": { - "transactionSigning": { - "badge": { - "virtualSource": { - "hierarchicalDeterministicPublicKey": { - "publicKey": { - "curve": "curve25519", - "compressedData": "18c7409458a82281711b668f833b0485e8fb58a3ceb8a728882bf6b83d3f06a9" - }, - "derivationPath": { - "scheme": "cap26", - "path": "m/44H/1022H/2H/525H/1460H/0H" - } - }, - "discriminator": "hierarchicalDeterministicPublicKey" - }, - "discriminator": "virtualSource" - }, - "factorSourceID": { - "fromHash": { - "kind": "device", - "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" - }, - "discriminator": "fromHash" - } - } - }, - "discriminator": "unsecured" - }, - "networkID": 2, - "appearanceID": 0, - "flags": [], - "displayName": "Nadia", - "onLedgerSettings": { - "thirdPartyDeposits": { - "depositRule": "acceptAll", - "assetsExceptionList": [], - "depositorsAllowList": [] - } - }, - "address": "account_tdx_2_1289zm062j788dwrjefqkfgfeea5tkkdnh8htqhdrzdvjkql4kxceql" - }, - { - "securityState": { - "unsecuredEntityControl": { - "transactionSigning": { - "badge": { - "virtualSource": { - "hierarchicalDeterministicPublicKey": { - "publicKey": { - "curve": "curve25519", - "compressedData": "26b3fd7f65f01ff8e418a56722fde9cc6fc18dc983e0474e6eb6c1cf3bd44f23" - }, - "derivationPath": { - "scheme": "cap26", - "path": "m/44H/1022H/2H/525H/1460H/1H" - } - }, - "discriminator": "hierarchicalDeterministicPublicKey" - }, - "discriminator": "virtualSource" - }, - "factorSourceID": { - "fromHash": { - "kind": "device", - "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" - }, - "discriminator": "fromHash" - } - } - }, - "discriminator": "unsecured" - }, - "networkID": 2, - "appearanceID": 1, - "flags": ["deletedByUser"], - "displayName": "Olivia", - "onLedgerSettings": { - "thirdPartyDeposits": { - "depositRule": "acceptAll", - "assetsExceptionList": [], - "depositorsAllowList": [] - } - }, - "address": "account_tdx_2_129663ef7fj8azge3y6sl73lf9vyqt53ewzlf7ul2l76mg5wyqlqlpr" - } - ] + { + "securityState": { + "unsecuredEntityControl": { + "transactionSigning": { + "badge": { + "virtualSource": { + "hierarchicalDeterministicPublicKey": { + "publicKey": { + "curve": "curve25519", + "compressedData": "18c7409458a82281711b668f833b0485e8fb58a3ceb8a728882bf6b83d3f06a9" + }, + "derivationPath": { + "scheme": "cap26", + "path": "m/44H/1022H/2H/525H/1460H/0H" + } + }, + "discriminator": "hierarchicalDeterministicPublicKey" + }, + "discriminator": "virtualSource" + }, + "factorSourceID": { + "fromHash": { + "kind": "device", + "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" + }, + "discriminator": "fromHash" + } + } + }, + "discriminator": "unsecured" + }, + "networkID": 2, + "appearanceID": 0, + "flags": [], + "displayName": "Nadia", + "onLedgerSettings": { + "thirdPartyDeposits": { + "depositRule": "acceptAll", + "assetsExceptionList": [], + "depositorsAllowList": [] + } + }, + "address": "account_tdx_2_1289zm062j788dwrjefqkfgfeea5tkkdnh8htqhdrzdvjkql4kxceql" + }, + { + "securityState": { + "unsecuredEntityControl": { + "transactionSigning": { + "badge": { + "virtualSource": { + "hierarchicalDeterministicPublicKey": { + "publicKey": { + "curve": "curve25519", + "compressedData": "26b3fd7f65f01ff8e418a56722fde9cc6fc18dc983e0474e6eb6c1cf3bd44f23" + }, + "derivationPath": { + "scheme": "cap26", + "path": "m/44H/1022H/2H/525H/1460H/1H" + } + }, + "discriminator": "hierarchicalDeterministicPublicKey" + }, + "discriminator": "virtualSource" + }, + "factorSourceID": { + "fromHash": { + "kind": "device", + "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" + }, + "discriminator": "fromHash" + } + } + }, + "discriminator": "unsecured" + }, + "networkID": 2, + "appearanceID": 1, + "flags": ["deletedByUser"], + "displayName": "Olivia", + "onLedgerSettings": { + "thirdPartyDeposits": { + "depositRule": "acceptAll", + "assetsExceptionList": [], + "depositorsAllowList": [] + } + }, + "address": "account_tdx_2_129663ef7fj8azge3y6sl73lf9vyqt53ewzlf7ul2l76mg5wyqlqlpr" + } + ] "#, ); } @@ -199,102 +198,104 @@ mod tests { &sut, r#" [ - { - "securityState": { - "unsecuredEntityControl": { - "transactionSigning": { - "badge": { - "virtualSource": { - "hierarchicalDeterministicPublicKey": { - "publicKey": { - "curve": "curve25519", - "compressedData": "d24cc6af91c3f103d7f46e5691ce2af9fea7d90cfb89a89d5bba4b513b34be3b" - }, - "derivationPath": { - "scheme": "cap26", - "path": "m/44H/1022H/1H/525H/1460H/0H" - } - }, - "discriminator": "hierarchicalDeterministicPublicKey" - }, - "discriminator": "virtualSource" - }, - "factorSourceID": { - "fromHash": { - "kind": "device", - "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" - }, - "discriminator": "fromHash" - } - } - }, - "discriminator": "unsecured" - }, - "networkID": 1, - "appearanceID": 0, - "flags": [], - "displayName": "Alice", - "onLedgerSettings": { - "thirdPartyDeposits": { - "depositRule": "acceptAll", - "assetsExceptionList": [], - "depositorsAllowList": [] - } - }, - "address": "account_rdx12yy8n09a0w907vrjyj4hws2yptrm3rdjv84l9sr24e3w7pk7nuxst8" - }, - { - "securityState": { - "unsecuredEntityControl": { - "transactionSigning": { - "badge": { - "virtualSource": { - "hierarchicalDeterministicPublicKey": { - "publicKey": { - "curve": "curve25519", - "compressedData": "08740a2fd178c40ce71966a6537f780978f7f00548cfb59196344b5d7d67e9cf" - }, - "derivationPath": { - "scheme": "cap26", - "path": "m/44H/1022H/1H/525H/1460H/1H" - } - }, - "discriminator": "hierarchicalDeterministicPublicKey" - }, - "discriminator": "virtualSource" - }, - "factorSourceID": { - "fromHash": { - "kind": "device", - "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" - }, - "discriminator": "fromHash" - } - } - }, - "discriminator": "unsecured" - }, - "networkID": 1, - "appearanceID": 1, - "flags": [], - "displayName": "Bob", - "onLedgerSettings": { - "thirdPartyDeposits": { - "depositRule": "acceptAll", - "assetsExceptionList": [], - "depositorsAllowList": [] - } - }, - "address": "account_rdx129a9wuey40lducsf6yu232zmzk5kscpvnl6fv472r0ja39f3hced69" - } - ] + { + "securityState": { + "unsecuredEntityControl": { + "transactionSigning": { + "badge": { + "virtualSource": { + "hierarchicalDeterministicPublicKey": { + "publicKey": { + "curve": "curve25519", + "compressedData": "d24cc6af91c3f103d7f46e5691ce2af9fea7d90cfb89a89d5bba4b513b34be3b" + }, + "derivationPath": { + "scheme": "cap26", + "path": "m/44H/1022H/1H/525H/1460H/0H" + } + }, + "discriminator": "hierarchicalDeterministicPublicKey" + }, + "discriminator": "virtualSource" + }, + "factorSourceID": { + "fromHash": { + "kind": "device", + "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" + }, + "discriminator": "fromHash" + } + } + }, + "discriminator": "unsecured" + }, + "networkID": 1, + "appearanceID": 0, + "flags": [], + "displayName": "Alice", + "onLedgerSettings": { + "thirdPartyDeposits": { + "depositRule": "acceptAll", + "assetsExceptionList": [], + "depositorsAllowList": [] + } + }, + "address": "account_rdx12yy8n09a0w907vrjyj4hws2yptrm3rdjv84l9sr24e3w7pk7nuxst8" + }, + { + "securityState": { + "unsecuredEntityControl": { + "transactionSigning": { + "badge": { + "virtualSource": { + "hierarchicalDeterministicPublicKey": { + "publicKey": { + "curve": "curve25519", + "compressedData": "08740a2fd178c40ce71966a6537f780978f7f00548cfb59196344b5d7d67e9cf" + }, + "derivationPath": { + "scheme": "cap26", + "path": "m/44H/1022H/1H/525H/1460H/1H" + } + }, + "discriminator": "hierarchicalDeterministicPublicKey" + }, + "discriminator": "virtualSource" + }, + "factorSourceID": { + "fromHash": { + "kind": "device", + "body": "3c986ebf9dcd9167a97036d3b2c997433e85e6cc4e4422ad89269dac7bfea240" + }, + "discriminator": "fromHash" + } + } + }, + "discriminator": "unsecured" + }, + "networkID": 1, + "appearanceID": 1, + "flags": [], + "displayName": "Bob", + "onLedgerSettings": { + "thirdPartyDeposits": { + "depositRule": "acceptAll", + "assetsExceptionList": [], + "depositorsAllowList": [] + } + }, + "address": "account_rdx129a9wuey40lducsf6yu232zmzk5kscpvnl6fv472r0ja39f3hced69" + } + ] "#, ); } } #[cfg(test)] -mod uniffi_tests { +mod test_uniffi_tests { + + use uniffi::{Lift, Lower}; use super::*; @@ -302,20 +303,14 @@ mod uniffi_tests { type SUT = Accounts; #[test] - fn test_updating_or_appending() { - let mut sut = SUT::new(); - let first = Account::sample(); - let mut second = Account::sample_other(); - sut.append(first.clone()); - sut.append(second.clone()); - assert_eq!(sut.len(), 2); - assert_eq!( - new_accounts_by_updating_or_appending(second.clone(), &sut), - sut - ); - second.display_name = DisplayName::new("Changed").unwrap(); - let updated = new_accounts_by_updating_or_appending(second, &sut); - assert_eq!(updated.len(), 2); - assert_ne!(updated, sut); + fn manual_perform_uniffi_conversion_successful() { + let test = |sut: SUT| { + let ffi_side = >::lower(sut.clone()); + let from_ffi = + >::try_lift(ffi_side).unwrap(); + assert_eq!(from_ffi, sut); + }; + + test(SUT::new()); // test can be empty (`FactorSources` cannot be empty, enforced by our `try_lift` impl of `IdentifiedVecOf`, so this test cannot be put in macro declaring the `decl_identified_vec_of` macro) } } diff --git a/src/profile/v100/networks/network/authorized_dapp/authorized_persona_simple.rs b/src/profile/v100/networks/network/authorized_dapp/authorized_persona_simple.rs index 968f8d7b3..beb9cf6d8 100644 --- a/src/profile/v100/networks/network/authorized_dapp/authorized_persona_simple.rs +++ b/src/profile/v100/networks/network/authorized_dapp/authorized_persona_simple.rs @@ -90,10 +90,10 @@ impl PersonaData { SharedPersonaData::new( self.name.clone().map(|x| x.id), SharedToDappWithPersonaIDsOfPersonaDataEntries::exactly( - self.email_addresses.clone().ids(), + self.email_addresses.ids().into_iter().cloned(), ), SharedToDappWithPersonaIDsOfPersonaDataEntries::exactly( - self.phone_numbers.clone().ids(), + self.phone_numbers.ids().into_iter().cloned(), ), ) } diff --git a/src/profile/v100/networks/network/authorized_dapp/references_to_authorized_personas.rs b/src/profile/v100/networks/network/authorized_dapp/references_to_authorized_personas.rs index 4fc46054a..746142421 100644 --- a/src/profile/v100/networks/network/authorized_dapp/references_to_authorized_personas.rs +++ b/src/profile/v100/networks/network/authorized_dapp/references_to_authorized_personas.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// An order set of `AuthorizedPersonaSimple`s, which is a collection of all /// the Personas the user has used to interact with this Dapp, it is called /// "references to", since the Personas are not stored in full, that would be diff --git a/src/profile/v100/networks/network/authorized_dapp/shared_persona_data.rs b/src/profile/v100/networks/network/authorized_dapp/shared_persona_data.rs index b7f7c0fa3..93c950238 100644 --- a/src/profile/v100/networks/network/authorized_dapp/shared_persona_data.rs +++ b/src/profile/v100/networks/network/authorized_dapp/shared_persona_data.rs @@ -76,11 +76,11 @@ impl HasSampleValues for SharedPersonaData { id.next(), SharedToDappWithPersonaIDsOfPersonaDataEntries::new( RequestedQuantity::exactly(2), - IdentifiedVecVia::from_iter([id.next(), id.next()]), + [id.next(), id.next()], ), SharedToDappWithPersonaIDsOfPersonaDataEntries::new( RequestedQuantity::at_least(1), - IdentifiedVecVia::from_iter([id.next(), id.next()]), + [id.next(), id.next()], ), ) } @@ -93,11 +93,11 @@ impl HasSampleValues for SharedPersonaData { id.next(), SharedToDappWithPersonaIDsOfPersonaDataEntries::new( RequestedQuantity::exactly(2), - IdentifiedVecVia::from_iter([id.next(), id.next()]), + [id.next(), id.next()], ), SharedToDappWithPersonaIDsOfPersonaDataEntries::new( RequestedQuantity::at_least(1), - IdentifiedVecVia::from_iter([id.next(), id.next()]), + [id.next(), id.next()], ), ) } diff --git a/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_account_addresses.rs b/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_account_addresses.rs index 4d3832fd3..398424cb3 100644 --- a/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_account_addresses.rs +++ b/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_account_addresses.rs @@ -34,35 +34,31 @@ impl SharedToDappWithPersonaAccountAddresses { pub fn sample_mainnet() -> Self { Self::new( RequestedQuantity::exactly(2), - IdentifiedVecVia::from_iter([ + [ Account::sample_mainnet().address, Account::sample_mainnet_other().address, - ]), + ], ) } pub fn sample_mainnet_other() -> Self { Self::new( RequestedQuantity::at_least(1), - IdentifiedVecVia::from_iter([ - Account::sample_mainnet_other().address - ]), + [Account::sample_mainnet_other().address], ) } pub fn sample_stokenet() -> Self { Self::new( RequestedQuantity::exactly(2), - IdentifiedVecVia::from_iter([ + [ AccountAddress::sample_stokenet(), AccountAddress::sample_stokenet_other(), - ]), + ], ) } pub fn sample_stokenet_other() -> Self { Self::new( RequestedQuantity::at_least(1), - IdentifiedVecVia::from_iter([ - AccountAddress::sample_stokenet_other(), - ]), + [AccountAddress::sample_stokenet_other()], ) } } diff --git a/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_ids_of_persona_data_entries.rs b/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_ids_of_persona_data_entries.rs index c8bc8bd9d..c3f333bd9 100644 --- a/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_ids_of_persona_data_entries.rs +++ b/src/profile/v100/networks/network/authorized_dapp/shared_to_dapp_with_persona_ids_of_persona_data_entries.rs @@ -22,18 +22,18 @@ impl HasSampleValues for SharedToDappWithPersonaIDsOfPersonaDataEntries { fn sample() -> Self { Self::new( RequestedQuantity::at_least(2), - IdentifiedVecVia::from_iter([ + [ PersonaDataEntryID::sample_one(), PersonaDataEntryID::sample_two(), PersonaDataEntryID::sample_four(), - ]), + ], ) } fn sample_other() -> Self { Self::new( RequestedQuantity::exactly(1), - IdentifiedVecVia::from_iter([PersonaDataEntryID::sample_one()]), + [PersonaDataEntryID::sample_one()], ) } } diff --git a/src/profile/v100/networks/network/authorized_dapp/shared_with_dapp.rs b/src/profile/v100/networks/network/authorized_dapp/shared_with_dapp.rs index d482e7039..58f043817 100644 --- a/src/profile/v100/networks/network/authorized_dapp/shared_with_dapp.rs +++ b/src/profile/v100/networks/network/authorized_dapp/shared_with_dapp.rs @@ -37,7 +37,7 @@ macro_rules! declare_shared_with_dapp { /// The by user shared IDs of data identifiable data shared with the /// Dapp. - pub ids: IdentifiedVecVia<$id>, + pub ids: IdentifiedVecOf<$id>, } impl $struct_name { @@ -50,7 +50,7 @@ macro_rules! declare_shared_with_dapp { request: RequestedQuantity, ids: impl IntoIterator, ) -> Self { - let ids = IdentifiedVecVia::from_iter(ids.into_iter()); + let ids = IdentifiedVecOf::from_iter(ids.into_iter()); let len = ids.len(); assert!( request.is_fulfilled_by_ids(len), @@ -64,14 +64,14 @@ macro_rules! declare_shared_with_dapp { pub fn exactly( ids: impl IntoIterator, ) -> Self { - let ids = IdentifiedVecVia::from_iter(ids.into_iter()); + let ids = ids.into_iter().collect_vec(); Self::new(RequestedQuantity::exactly(ids.len() as u16), ids) } pub fn just( id: $id, ) -> Self { - Self::exactly(IdentifiedVecVia::from_iter([id])) + Self::exactly([id]) } /// String representation of the request and shared ids. @@ -110,19 +110,19 @@ macro_rules! declare_shared_with_dapp { #[test] #[should_panic = "ids does not fulfill request, got: #0, but requested: AtLeast: 1"] fn panics_when_at_least_is_not_fulfilled() { - _ = SUT::new(RequestedQuantity::at_least(1), IdentifiedVecVia::new()) + _ = SUT::new(RequestedQuantity::at_least(1), []) } #[test] #[should_panic = "ids does not fulfill request, got: #0, but requested: Exactly: 1"] fn panics_when_exactly_is_not_fulfilled() { - _ = SUT::new(RequestedQuantity::exactly(1), IdentifiedVecVia::new()) + _ = SUT::new(RequestedQuantity::exactly(1), []) } #[test] #[should_panic = "Invalid quantity Exactly: 0"] fn panics_when_exactly_0() { - _ = SUT::new(RequestedQuantity::exactly(0), IdentifiedVecVia::new()) + _ = SUT::new(RequestedQuantity::exactly(0), []) } #[test] diff --git a/src/profile/v100/networks/network/authorized_dapps.rs b/src/profile/v100/networks/network/authorized_dapps.rs index db50f4fe5..a5919980e 100644 --- a/src/profile/v100/networks/network/authorized_dapps.rs +++ b/src/profile/v100/networks/network/authorized_dapps.rs @@ -1,8 +1,7 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// An ordered set of ['AuthorizedDapp`]s on a specific network. - AuthorizedDapps, AuthorizedDapp ); @@ -86,10 +85,7 @@ mod tests { let authorized_dapp = AuthorizedDapp::sample(); let address = authorized_dapp.dapp_definition_address; let authorized_dapps = AuthorizedDapps::just(authorized_dapp.clone()); - assert_eq!( - authorized_dapps.get_authorized_dapp_by_id(&address), - Some(&authorized_dapp) - ); + assert_eq!(authorized_dapps.get_id(&address), Some(&authorized_dapp)); } #[test] diff --git a/src/profile/v100/networks/network/personas.rs b/src/profile/v100/networks/network/personas.rs index 9fe452343..0fec49d41 100644 --- a/src/profile/v100/networks/network/personas.rs +++ b/src/profile/v100/networks/network/personas.rs @@ -1,8 +1,7 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// An ordered set of [`Persona`]s on a specific network. - Personas, Persona ); @@ -82,7 +81,7 @@ mod tests { let persona = Persona::sample(); let address = persona.address; let personas = Personas::just(persona.clone()); - assert_eq!(personas.get_persona_by_id(&address), Some(&persona)); + assert_eq!(personas.get_id(&address), Some(&persona)); } #[test] diff --git a/src/profile/v100/networks/network/profile_network.rs b/src/profile/v100/networks/network/profile_network.rs index d3cf2976b..b553db527 100644 --- a/src/profile/v100/networks/network/profile_network.rs +++ b/src/profile/v100/networks/network/profile_network.rs @@ -120,7 +120,7 @@ impl ProfileNetwork { F: FnMut(&mut Account), { if self.accounts.update_with(address, mutate) { - self.accounts.get(address).cloned() + self.accounts.get_id(address).cloned() } else { None } diff --git a/src/profile/v100/networks/profile_networks.rs b/src/profile/v100/networks/profile_networks.rs index 98bc40e54..9136cee25 100644 --- a/src/profile/v100/networks/profile_networks.rs +++ b/src/profile/v100/networks/profile_networks.rs @@ -1,17 +1,16 @@ use crate::prelude::*; -decl_can_be_empty_identified_array_of!( +decl_identified_vec_of!( /// An ordered mapping of NetworkID -> `Profile.Network`, containing /// all the users Accounts, Personas and AuthorizedDapps the user /// has created and interacted with on this network. - ProfileNetworks, ProfileNetwork ); impl ProfileNetworks { pub fn get_account(&self, address: &AccountAddress) -> Option { - self.get(&address.network_id()) - .and_then(|n| n.accounts.get_account_by_id(address)) + self.get_id(&address.network_id()) + .and_then(|n| n.accounts.get_id(address)) .cloned() } @@ -106,7 +105,7 @@ mod tests { ); assert_eq!( - sut.get(&NetworkID::Mainnet).unwrap().accounts.items(), + sut.get_id(&NetworkID::Mainnet).unwrap().accounts.items(), [ Account::sample_mainnet_alice(), Account::sample_mainnet_bob() @@ -120,10 +119,10 @@ mod tests { let id = &NetworkID::Mainnet; let account_address = Account::sample().address; assert_eq!( - sut.get(id) + sut.get_id(id) .unwrap() .accounts - .get(&account_address) + .get_id(&account_address) .unwrap() .display_name .value, @@ -135,10 +134,10 @@ mod tests { }); assert_eq!( - sut.get(id) + sut.get_id(id) .unwrap() .accounts - .get(&account_address) + .get_id(&account_address) .unwrap() .display_name .value, @@ -151,7 +150,10 @@ mod tests { let mut sut = ProfileNetworks::sample(); let id = &NetworkID::Mainnet; let account_address = Account::sample_nebunet().address; - assert_eq!(sut.get(id).unwrap().accounts.get(&account_address), None); + assert_eq!( + sut.get_id(id).unwrap().accounts.get_id(&account_address), + None + ); assert!(sut .update_account(&account_address, |a| { @@ -168,7 +170,10 @@ mod tests { let mut sut = ProfileNetworks::sample(); let id = &NetworkID::Mainnet; let account_address = Account::sample_mainnet_carol().address; - assert_eq!(sut.get(id).unwrap().accounts.get(&account_address), None); + assert_eq!( + sut.get_id(id).unwrap().accounts.get_id(&account_address), + None + ); assert!(sut .update_account(&account_address, |a| { diff --git a/src/profile/v100/profile.rs b/src/profile/v100/profile.rs index 460f5a002..6c154069f 100644 --- a/src/profile/v100/profile.rs +++ b/src/profile/v100/profile.rs @@ -114,6 +114,9 @@ impl Profile { app_preferences: AppPreferences, networks: ProfileNetworks, ) -> Self { + if factor_sources.is_empty() { + panic!("FactorSources MUST NOT be empty.") + } Self { header, factor_sources, @@ -173,16 +176,17 @@ impl Profile { S: IsFactorSource, M: FnMut(S) -> Result, { - self.factor_sources.try_update_with(factor_source_id, |f| { - S::try_from(f.clone()) - .map_err(|_| CommonError::CastFactorSourceWrongKind { - expected: S::kind(), - found: f.factor_source_kind(), - }) - .and_then(|element| { - mutate(element).map(|modified| modified.into()) - }) - }) + self.factor_sources + .maybe_update_with(factor_source_id, |f| { + S::try_from(f.clone()) + .map_err(|_| CommonError::CastFactorSourceWrongKind { + expected: S::kind(), + found: f.factor_source_kind(), + }) + .and_then(|element| { + mutate(element).map(|modified| modified.into()) + }) + }) } } @@ -230,6 +234,24 @@ mod tests { assert_eq!(SUT::sample_other(), SUT::sample_other()); } + #[should_panic(expected = "FactorSources MUST NOT be empty.")] + #[test] + fn not_allowed_to_create_profile_with_empty_factor_source() { + let _ = SUT::with( + Header::sample(), + IdentifiedVecOf::new(), + AppPreferences::sample(), + ProfileNetworks::sample(), + ); + } + + #[test] + fn serialize_empty_factor_sources_is_err() { + let mut sut = SUT::sample(); + sut.factor_sources = FactorSources::new(); + assert!(serde_json::to_value(sut).is_err()); + } + #[test] fn equality_display() { // This test might seem trivial, in fact it is not, @@ -279,7 +301,7 @@ mod tests { assert_eq!( sut.factor_sources - .get(id) + .get_id(id) .unwrap() .as_device() .unwrap() @@ -309,7 +331,7 @@ mod tests { assert_eq!( sut.factor_sources - .get(id) + .get_id(id) .unwrap() .as_device() .unwrap() @@ -333,7 +355,7 @@ mod tests { assert_eq!( sut.factor_sources - .get(id) + .get_id(id) .unwrap() .as_device() .unwrap() @@ -362,7 +384,7 @@ mod tests { // Remains unchanged assert_eq!( sut.factor_sources - .get(id) + .get_id(id) .unwrap() .as_device() .unwrap() @@ -401,7 +423,7 @@ mod tests { let mut sut = SUT::sample(); let account = sut .networks - .get(&NetworkID::Mainnet) + .get_id(&NetworkID::Mainnet) .unwrap() .accounts .get_at_index(0) @@ -416,7 +438,7 @@ mod tests { assert_eq!( sut.networks - .get(&NetworkID::Mainnet) + .get_id(&NetworkID::Mainnet) .unwrap() .accounts .get_at_index(0) diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index bfff0809e..7c3135230 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use std::sync::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; -pub type HeadersList = IdentifiedVecVia
; +pub type HeadersList = IdentifiedVecOf
; #[derive(Debug, uniffi::Object)] pub struct Wallet { diff --git a/src/wallet/wallet_accounts.rs b/src/wallet/wallet_accounts.rs index aacdd8957..c4a77abad 100644 --- a/src/wallet/wallet_accounts.rs +++ b/src/wallet/wallet_accounts.rs @@ -96,7 +96,7 @@ impl Wallet { let number_of_accounts_on_network = profile .networks - .get(&network_id) + .get_id(&network_id) .map(|n| n.accounts.len()) .unwrap_or(0); @@ -125,17 +125,14 @@ impl Wallet { self.try_update_profile_with(|mut p| { let networks = &mut p.networks; if networks.contains_id(&network_id) { - networks - .try_update_with(&network_id, |network| { - if (*network.accounts).append(account.clone()).0 { - Ok(network.clone()) - } else { - Err(err_exists.clone()) - } - }) - .and_then( - |r| if r { Ok(()) } else { Err(err_exists.clone()) }, - ) + networks.try_try_update_with(&network_id, |network| { + if network.accounts.append(account.clone()).0 { + Ok(()) + } else { + Err(err_exists.clone()) + } + })?; + Ok(()) } else { let network = ProfileNetwork::new( network_id, diff --git a/src/wrapped_radix_engine_toolkit/high_level/manifest_building/third_party_deposit_update/third_party_deposits_delta.rs b/src/wrapped_radix_engine_toolkit/high_level/manifest_building/third_party_deposit_update/third_party_deposits_delta.rs index e730f7f9c..a25420101 100644 --- a/src/wrapped_radix_engine_toolkit/high_level/manifest_building/third_party_deposit_update/third_party_deposits_delta.rs +++ b/src/wrapped_radix_engine_toolkit/high_level/manifest_building/third_party_deposit_update/third_party_deposits_delta.rs @@ -38,7 +38,7 @@ impl ThirdPartyDepositsDelta { !to.assets_exception_list .clone() .unwrap_or_default() - .contains(x) + .contains_by_id(x) }) .map(ScryptoManifestValue::from) .collect(), diff --git a/src/wrapped_radix_engine_toolkit/high_level/sargon_specific_types/assets_transfers/per_recipient/per_recipient_asset_transfers.rs b/src/wrapped_radix_engine_toolkit/high_level/sargon_specific_types/assets_transfers/per_recipient/per_recipient_asset_transfers.rs index f94ae40af..fe85944b4 100644 --- a/src/wrapped_radix_engine_toolkit/high_level/sargon_specific_types/assets_transfers/per_recipient/per_recipient_asset_transfers.rs +++ b/src/wrapped_radix_engine_toolkit/high_level/sargon_specific_types/assets_transfers/per_recipient/per_recipient_asset_transfers.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +use indexmap::IndexMap; #[derive(Clone, Debug, PartialEq, Eq, Hash, uniffi::Record)] pub struct PerRecipientAssetTransfers { diff --git a/src/wrapped_radix_engine_toolkit/low_level/execution_summary/execution_summary.rs b/src/wrapped_radix_engine_toolkit/low_level/execution_summary/execution_summary.rs index 465ac5268..40803bb78 100644 --- a/src/wrapped_radix_engine_toolkit/low_level/execution_summary/execution_summary.rs +++ b/src/wrapped_radix_engine_toolkit/low_level/execution_summary/execution_summary.rs @@ -1,3 +1,5 @@ +use radix_engine::types::IndexMap; + use crate::prelude::*; /// A summary of the execution of the manifest and the information that helps diff --git a/src/wrapped_radix_engine_toolkit/low_level/execution_summary/newly_created_resource.rs b/src/wrapped_radix_engine_toolkit/low_level/execution_summary/newly_created_resource.rs index ad5b3a10d..3094ee9af 100644 --- a/src/wrapped_radix_engine_toolkit/low_level/execution_summary/newly_created_resource.rs +++ b/src/wrapped_radix_engine_toolkit/low_level/execution_summary/newly_created_resource.rs @@ -1,3 +1,5 @@ +use radix_engine::types::IndexMap; + use crate::prelude::*; /// Metadata about a newly created Resource diff --git a/src/wrapped_radix_engine_toolkit/low_level/execution_summary/resource_indicator/predicted.rs b/src/wrapped_radix_engine_toolkit/low_level/execution_summary/resource_indicator/predicted.rs index 5073251b5..3a90e05d9 100644 --- a/src/wrapped_radix_engine_toolkit/low_level/execution_summary/resource_indicator/predicted.rs +++ b/src/wrapped_radix_engine_toolkit/low_level/execution_summary/resource_indicator/predicted.rs @@ -1,3 +1,5 @@ +use radix_engine::types::{IndexMap, IndexSet}; + use crate::prelude::*; /// This macro exists since UniFFI does not support generics currently, when/if diff --git a/uniffi.toml b/uniffi.toml index 31ac21710..785268a79 100644 --- a/uniffi.toml +++ b/uniffi.toml @@ -36,9 +36,9 @@ into_custom = "URL(string: {})!" from_custom = "String(describing: {})" [bindings.kotlin.custom_types.Url] -type_name = "URL" -imports = ["java.net.URI", "java.net.URL"] -into_custom = "URI({}).toURL()" +type_name = "HttpUrl" +imports = ["okhttp3.HttpUrl", "okhttp3.HttpUrl.Companion.toHttpUrl"] +into_custom = "{}.toHttpUrl()" from_custom = "{}.toString()" [bindings.swift.custom_types.Timestamp]