Compare commits

...

42 Commits

Author SHA1 Message Date
Lukas Kubanek f08ff3e872 Updated version in README 2020-05-22 09:08:16 +02:00
Lukas Kubanek f0da8a43be Removed concrete version from Xcode project 2020-05-22 09:07:44 +02:00
Lukas Kubanek dbd6b816db Mentioned older Swift versions support in README 2020-05-22 09:04:56 +02:00
Lukas Kubanek 9818933b59 Dropped support for Swift <4.2 (#61) 2020-05-22 08:57:45 +02:00
Lukas Kubanek 88cc1ad101 Moved Travis scripts 2020-05-21 23:48:15 +02:00
Lukas Kubanek 4cd37bd207 Reduced Travis configuration to Swift 4.2 only 2020-05-21 23:44:40 +02:00
Lukas Kubanek 5e62daeff2 Added GitHub action for CI (#59) 2020-05-21 23:31:42 +02:00
Lukas Kubanek 52e42cd938 Refreshed README 2020-05-21 16:14:49 +02:00
Lukas Kubanek dbf4484048 Updated manifest files 2020-05-21 16:14:49 +02:00
Lukas Kubanek 804f2847b4 Updated .gitignore 2020-05-21 16:14:49 +02:00
Lukas Kubanek 46952da3c3 Updated to Xcode 11.4
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-03-26 10:29:23 +01:00
Lukas Kubanek acb62df760 Bumped version to 2.4.0
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-03-02 10:58:22 +00:00
Lukas Kubanek f303e02f63 Merge branch 'pr-capacity'
Closes #54

Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-03-02 10:38:54 +00:00
Lukas Kubanek 244d0128c9 Added basic tests for capacity reservation
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-03-02 10:32:41 +00:00
Lukas Kubanek 0d5e16fc4f Expose min reserved capacity of underlying types
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-03-02 10:32:24 +00:00
Lukas Kubanek ecd3f176e5 Introduced init(minimumCapacity:)
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-03-02 10:26:27 +00:00
Lukas Kubanek ac3f8fa5eb Tweaked documentation comments
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-03-02 10:26:26 +00:00
Gal Cohen 19046fb4a8 adds capacity getter and reserveCapacity method 2020-01-31 21:30:29 -05:00
Lukas Kubanek 005ef5c3ee 2019 → 2020
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2020-01-12 10:08:56 +01:00
Lukas Kubanek 68f2557694 Updated to Xcode 11.2
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-11-04 16:53:55 +01:00
Lukas Kubanek 72d4779e9b Concretized Swift version in the recent tweak
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-09-26 16:14:02 +02:00
Lukas Kubanek 8547583792 Another try to satisfy Swift 4.0
It turns out Swift <4.1 does not understand the rethrows keyword and thus sees the newly annotated initializer as failing. Resorted to a force unwrap in the deprecated initializer as its parameter is non-throwing.

Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-09-26 16:04:40 +02:00
Lukas Kubanek 3688348461 Another attempt on fixing the bug with missing try keyword
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-09-26 15:40:41 +02:00
Lukas Kubanek f875439709 Fixed a bug introduced in the last commit
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-09-26 15:32:43 +02:00
Lukas Kubanek 1920f07525 init(values:uniquelyKeyedBy:) now takes throwing closure
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-09-26 15:03:57 +02:00
Lukas Kubanek 69ed90dcfc Bumped version to 2.3.0
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-30 15:41:05 +02:00
Lukas Kubanek 33fa9622ce Removed irrelevant part of a playground
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-30 15:40:31 +02:00
Lukas Kubanek 468ad1c83a Attempted to fix type inference issue in Swift 4
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 13:00:43 +02:00
Lukas Kubanek 174c21d58f Fixed a warning for Swift 5.0
Fixes #52

Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 12:44:37 +02:00
Lukas Kubanek 5f076fccbb init(_:) → init(uniqueKeysWithValues:)
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 12:38:22 +02:00
Lukas Kubanek 642b5623b7 init(values:keyedBy:) → init(values:uniquelyKeyedBy:)
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 12:22:32 +02:00
Lukas Kubanek 03b5817530 Annotated Travis configuration with exact 4.1.X version
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 09:42:34 +02:00
Lukas Kubanek 7ba07fcef1 Re-added Travis configurations for different Swift versions
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 09:35:49 +02:00
Lukas Kubanek 0e1273e2ab Attempt to use specified Swift versions by Travis
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 09:25:32 +02:00
Lukas Kubanek 7b8b3c39a3 Simplified Travis setup
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 09:11:26 +02:00
Lukas Kubanek 1e5c2926a7 Made tests compatible with Swift 4
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 08:56:24 +02:00
Lukas Kubanek b678702e3d Introduced mapValues(_:) & compactMapValues(_:)
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-07-12 08:38:59 +02:00
Lukas Kubanek 4e4b205dcb Revert "Disabled automatic linking"
This reverts commit b345a3e8df.
2019-07-04 14:53:30 +02:00
Lukas Kubanek b345a3e8df Disabled automatic linking
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-06-05 16:56:17 +02:00
Lukas Kubanek 2cf9220874 Updated project file to Xcode 11
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-06-04 10:13:56 +02:00
Lukas Kubanek 08e9ff5371 Minor adjustment in README
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-29 14:01:50 +02:00
Lukas Kubanek e7adba0cb9 Fixed version numbers by bumped version to 2.2.2
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-29 13:54:22 +02:00
21 changed files with 446 additions and 364 deletions
+42
View File
@@ -0,0 +1,42 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
macos:
name: macOS (Xcode ${{ matrix.xcode }})
runs-on: macos-latest
strategy:
matrix:
# See https://github.com/actions/virtual-environments/tree/master/images/macos
# No Xcode with support for Swift 4.2 available
xcode:
- "11.5_beta" # Swift 5.2.4
- "11.4" # Swift 5.2
- "11" # Swift 5.1
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: Build
run: swift build -v
- name: Test
run: swift test -v
linux:
name: Linux
runs-on: ubuntu-latest
container:
image: swift:5.2
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build
run: swift build -v
- name: Test
run: swift test -v
+8 -29
View File
@@ -1,32 +1,11 @@
# OS X
# SPM
.build
.swiftpm
# Xcode
xcuserdata/
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Ruby
.ruby-*
.rbenv-*
# Xcode
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
*.xctimeline
# Carthage
Carthage
# SPM
.build
+7 -27
View File
@@ -1,49 +1,29 @@
# Git
branches:
only:
- master
# OS
os: osx
language: objective-c
language: swift
# Xcode Project
xcode_project: OrderedDictionary.xcodeproj
# Build Matrix
matrix:
include:
# Swift 4.0 / macOS
- osx_image: xcode9.2
xcode_scheme: OrderedDictionary-Mac
# macOS 10.13 / Xcode 10.0 / Swift 4.2 / Target: macOS
- osx_image: xcode10
xcode_scheme: OrderedDictionary-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build test"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND_TARGET="x86_64-apple-macosx10.10"
# Swift 4.0 / iOS
- osx_image: xcode9.2
xcode_scheme: OrderedDictionary-iOS
env:
- XCODE_SDK=iphonesimulator
- XCODE_ACTION="build-for-testing test-without-building"
- XCODE_DESTINATION="platform=iOS Simulator,name=iPhone 6s,OS=10.1"
# Swift 4.1 / macOS
- osx_image: xcode9.3beta
xcode_scheme: OrderedDictionary-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build test"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND_TARGET="x86_64-apple-macosx10.10"
# Swift 4.1 / iOS
- osx_image: xcode9.3beta
# macOS 10.13 / Xcode 10.0 / Swift 4.2 / Target: iOS
- osx_image: xcode10
xcode_scheme: OrderedDictionary-iOS
env:
- XCODE_SDK=iphonesimulator
- XCODE_ACTION="build-for-testing test-without-building"
- XCODE_DESTINATION="platform=iOS Simulator,name=iPhone 6s,OS=10.1"
# Build Script
script:
- Scripts/build.sh
- .travis/build.sh
+4 -1
View File
@@ -32,6 +32,9 @@ if [[ -z $XCODE_DESTINATION ]]; then
fi
set -o pipefail
swift --version
xcodebuild $XCODE_ACTION \
-project "$TRAVIS_XCODE_PROJECT" \
-scheme "$TRAVIS_XCODE_SCHEME" \
@@ -50,5 +53,5 @@ fi
if [[ $XCODE_SDK = "macosx" ]]; then
echo "SDK is ${XCODE_SDK}, validating playground..."
. Scripts/validate-playgrounds.sh
. .travis/validate-playgrounds.sh
fi
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2019 Lukas Kubanek
Copyright © 2015-2020 Lukas Kubanek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+8
View File
@@ -0,0 +1,8 @@
import XCTest
import OrderedDictionaryTests
var tests = [XCTestCaseEntry]()
tests += OrderedDictionaryTests.__allTests()
XCTMain(tests)
+10 -2
View File
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
8048C8AB22D8911B0086B88B /* OrderedDictionary+Deprecated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8048C8AA22D8911B0086B88B /* OrderedDictionary+Deprecated.swift */; };
8048C8AC22D8911B0086B88B /* OrderedDictionary+Deprecated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8048C8AA22D8911B0086B88B /* OrderedDictionary+Deprecated.swift */; };
8055B0421E201C5D009DC3EE /* OrderedDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */; };
8055B0591E201DF3009DC3EE /* OrderedDictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */; };
80A203A11F3F483700622481 /* OrderedDictionary+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */; };
@@ -38,9 +40,9 @@
/* Begin PBXFileReference section */
8024947E2277123600AB44C7 /* Package@swift-4.2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Package@swift-4.2.swift"; sourceTree = "<group>"; };
8024947F2277136D00AB44C7 /* Package@swift-5.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Package@swift-5.swift"; sourceTree = "<group>"; };
804879371E217C7700AD31A3 /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = "<group>"; };
804879381E217CA100AD31A3 /* validate-playgrounds.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "validate-playgrounds.sh"; sourceTree = "<group>"; };
8048C8AA22D8911B0086B88B /* OrderedDictionary+Deprecated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OrderedDictionary+Deprecated.swift"; sourceTree = "<group>"; };
8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OrderedDictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8055B0411E201C5D009DC3EE /* OrderedDictionary_Mac_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OrderedDictionary_Mac_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionaryTests.swift; sourceTree = "<group>"; };
@@ -108,7 +110,6 @@
80DE329420F4DD910053EDA7 /* LICENSE.md */,
80DE329220F4CAFA0053EDA7 /* Package.swift */,
8024947E2277123600AB44C7 /* Package@swift-4.2.swift */,
8024947F2277136D00AB44C7 /* Package@swift-5.swift */,
8055B0521E201D24009DC3EE /* Sources */,
80B28EB11E201F72007E3A77 /* Playgrounds */,
8055B0571E201DF3009DC3EE /* Tests */,
@@ -135,6 +136,7 @@
80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */,
80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */,
80E8E22F1E2133D100395E49 /* OrderedDictionary+Description.swift */,
8048C8AA22D8911B0086B88B /* OrderedDictionary+Deprecated.swift */,
);
path = Sources;
sourceTree = "<group>";
@@ -346,6 +348,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8048C8AB22D8911B0086B88B /* OrderedDictionary+Deprecated.swift in Sources */,
80E8E2301E2133D100395E49 /* OrderedDictionary+Description.swift in Sources */,
80E8E21D1E20301E00395E49 /* OrderedDictionary.swift in Sources */,
80A203A11F3F483700622481 /* OrderedDictionary+Codable.swift in Sources */,
@@ -364,6 +367,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8048C8AC22D8911B0086B88B /* OrderedDictionary+Deprecated.swift in Sources */,
80E8E2311E2133D100395E49 /* OrderedDictionary+Description.swift in Sources */,
80E8E21F1E20425B00395E49 /* OrderedDictionary.swift in Sources */,
80A203A21F3F4C1F00622481 /* OrderedDictionary+Codable.swift in Sources */,
@@ -532,6 +536,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionary;
PRODUCT_NAME = OrderedDictionary;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -553,6 +558,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionary;
PRODUCT_NAME = OrderedDictionary;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
};
name = Release;
};
@@ -598,6 +604,7 @@
PRODUCT_NAME = OrderedDictionary;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -620,6 +627,7 @@
PRODUCT_NAME = OrderedDictionary;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1140"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -27,6 +27,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8055B0371E201C5D009DC3EE"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-Mac"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@@ -39,17 +48,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8055B0371E201C5D009DC3EE"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-Mac"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -70,8 +68,6 @@
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1140"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -27,6 +27,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "80B28E961E201EC8007E3A77"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-iOS"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@@ -39,17 +48,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "80B28E961E201EC8007E3A77"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-iOS"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -70,8 +68,6 @@
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
+2 -3
View File
@@ -1,4 +1,4 @@
// swift-tools-version:4
// swift-tools-version:5.0
import PackageDescription
@@ -22,6 +22,5 @@ let package = Package(
dependencies: ["OrderedDictionary"],
path: "Tests"
)
],
swiftLanguageVersions: [4]
]
)
+1 -1
View File
@@ -23,5 +23,5 @@ let package = Package(
path: "Tests"
)
],
swiftLanguageVersions: [.v4, .v4_2]
swiftLanguageVersions: [.v4_2]
)
-27
View File
@@ -1,27 +0,0 @@
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "OrderedDictionary",
products: [
.library(
name: "OrderedDictionary",
targets: ["OrderedDictionary"]
)
],
dependencies: [],
targets: [
.target(
name: "OrderedDictionary",
dependencies: [],
path: "Sources"
),
.testTarget(
name: "OrderedDictionaryTests",
dependencies: ["OrderedDictionary"],
path: "Tests"
)
],
swiftLanguageVersions: [.v5]
)
@@ -31,19 +31,3 @@ let plistDecoder = PropertyListDecoder()
let orderedDictionary3 = try! plistDecoder.decode(OrderedDictionary<String, Int>.self, from: plistData)
orderedDictionary1 == orderedDictionary3
// ======================================================= //
// MARK: - Non-codable Type
// ======================================================= //
struct NonCodableType {
var string: String
}
let orderedDictionary4: OrderedDictionary<String, NonCodableType> = [
"A" : NonCodableType(string: "Foo"),
"B" : NonCodableType(string: "Bar"),
"C" : NonCodableType(string: "Baz")
]
//try? jsonEncoder.encode(x)
+48 -35
View File
@@ -1,64 +1,77 @@
# OrderedDictionary
[![](https://img.shields.io/travis/lukaskubanek/OrderedDictionary.svg?style=flat-square "Build")](https://travis-ci.org/lukaskubanek/OrderedDictionary) [![](https://img.shields.io/badge/release-v2.2.0-blue.svg?style=flat-square)](https://github.com/lukaskubanek/OrderedDictionary/releases) [![](https://img.shields.io/badge/Swift-4.0+-orange.svg?style=flat-square)](https://developer.apple.com/swift/ "Swift 4") ![](https://img.shields.io/badge/platform-macOS/iOS-yellowgreen.svg?style=flat-square "Platform: macOS/iOS") [![](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square "Carthage compatible")](https://github.com/Carthage/Carthage)
[![](https://img.shields.io/badge/SPM-compatible-brightgreen.svg?style=flat-square "SPM compatible")](https://github.com/Carthage/Carthage) [![](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square "License: MIT")](LICENSE.md)
<p align="left">
<a href="https://github.com/lukaskubanek/OrderedDictionary/releases">
<img src="https://img.shields.io/github/release/lukaskubanek/OrderedDictionary/all.svg?style=flat-square">
</a>
<a href="https://developer.apple.com/swift">
<img src="https://img.shields.io/badge/Swift-4.2+-orange.svg?style=flat-square" alt="Swift 4.2+">
</a>
<a href="https://swift.org/package-manager">
<img src="https://img.shields.io/badge/SPM-compatible-brightgreen.svg?style=flat-square" alt="Swift Package Manager">
</a>
<a href="https://github.com/Carthage/Carthage">
<img src="https://img.shields.io/badge/Carthage-compatible-brightgreen.svg?style=flat-square" alt="Carthage">
</a>
<a href="LICENSE.md">
<img src="https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square" alt="License: MIT">
</a>
<a href="https://twitter.com/lukaskubanek">
<img src="https://img.shields.io/badge/contact-@lukaskubanek-olive.svg?style=flat-square" alt="Twitter: @lukaskubanek">
</a>
</p>
**OrderedDictionary** is a lightweight implementation of an ordered dictionary data structure in Swift.
OrderedDictionary is a lightweight implementation of an ordered dictionary data structure in Swift.
The `OrderedDictionary` struct is a generic collection which combines the features of `Dictionary` and `Array` from the Swift standard library. Like `Dictionary` it stores key-value pairs with each key being unique and maps each key to an associated value. Like `Array` it stores those pairs sorted and accessible by a zero-based integer index.
The `OrderedDictionary` struct is a generic collection that combines the features of `Dictionary` and `Array` data structures from the Swift standard library. Like `Dictionary`, it stores key-value pairs with each key being unique and maps each key to an associated value. Like `Array`, it stores those pairs sorted and accessible by a zero-based integer index.
`OrderedDictionary` provides similar APIs like collections from the Swift standard library. This includes accessing contents by keys or indices, inserting and removing elements, iterating, sorting etc.
`OrderedDictionary` provides similar APIs to collections in the Swift standard library like accessing contents by keys or indices, inserting and removing elements, iterating, sorting, filtering, etc.
Internally, `OrderedDictionary` uses a backing store composed of an instance of `Dictionary` for storing the key-value pairs and an instance of `Array` for managing the ordered keys. This means it is not the most performant implementation possible, but it gets its job done by reusing most functionality from the Swift standard library.
Internally, `OrderedDictionary` uses a backing storage composed of a `Dictionary` for storing the key-value pairs and an `Array` for managing the ordered keys. This architecture makes it not the most pefromant implementation possible, but it gets its job done while reusing most functionality from the Swift standard library.
## Requirements
- Swift 4.0, 4.2, 5.0
- Xcode 9.2+
- Swift 4.2+
- Xcode 10.0+
- iOS 8.0+ / macOS 10.10+
*For support of Swift 4.0 and 4.1 please refer to version 2.x of this library.*
*The Xcode and OS requirements apply only when the library is integrated as a framework or via the Xcode project.*
## Installation
The library is distributed as a Swift framework and can be integrated into your project in following ways:
### Swift Package Manager
#### Carthage
To install OrderedDictionary using the [Swift Package Manager](https://swift.org/package-manager/), add it as a dependency into your `Package.swift` file:
If you use [Carthage](https://github.com/Carthage/Carthage) for managing your dependencies, put OrderedDictionary into your `Cartfile`:
```plain
github "lukaskubanek/OrderedDictionary"
```swift
let package = Package(
...
dependencies: [
.package(url: "https://github.com/lukaskubanek/OrderedDictionary.git", from: "3.0.0")
],
...
)
```
Then, drag either the `OrderedDictionary.xcodeproj` or the `OrderedDictionary.framework` into your project/workspace and link your target against the `OrderedDictionary.framework`. Also make sure that the framework [gets copied](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to your application bundle.
### Carthage
#### Swift Package Manager
Another option is to use the [Swift Package Manager](https://swift.org/package-manager/). If you prefer this option, put OrderedDictionary as a dependency to your `Package.swift`:
To install OrderedDictionary using [Carthage](https://github.com/Carthage/Carthage), add it as a dependency into your `Cartfile`:
```plain
.package(url: "https://github.com/lukaskubanek/OrderedDictionary.git", from: "2.2.0")
github "lukaskubanek/LoremSwiftum"
```
#### Git Submodules
Then drag either the `OrderedDictionary.xcodeproj` or the `OrderedDictionary.framework` into your Xcode project/workspace and link your target against the `OrderedDictionary.framework`. Make sure that the framework [gets copied](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to your application bundle.
Yet another option is using [Git submodules](http://git-scm.com/book/en/v2/Git-Tools-Submodules) and integrating the Xcode project `OrderedDictionary.xcodeproj` from the submodule directly to your Xcode workspace.
### Git Submodules
#### ⚠️ Note About CocoaPods
You can also install OrderedDictionary via [Git submodules](http://git-scm.com/book/en/v2/Git-Tools-Submodules) and integrate the project `OrderedDictionary.xcodeproj` from the submodule directly into your Xcode workspace.
Although there is high demand for [CocoaPods](https://cocoapods.org) support, this method won't be officially supported by this library. Since I'm not using CocoaPods myself and since I think this method will be once replaced by the Swift Package Manager, I don't want to put any effort in maintaining an official podspec. If you really want to include this library via CocoaPods, there is still a way by creating a custom podspec (see the last section of [this post](https://guides.cocoapods.org/syntax/podfile.html#pod)).
### ⚠️ Note About CocoaPods
Although there has been a high demand for [CocoaPods](https://cocoapods.org) support, this distribution method won't be officially supported by this library. If you really want to integrate this library via CocoaPods, you can create and maintain a custom podspec (see the last section of [this post](https://guides.cocoapods.org/syntax/podfile.html#pod)).
## Usage & Docs
For the usage of this library please refer to [the example playground](Playgrounds/OrderedDictionary.playground/Contents.swift). For documentation please refer to [the documentation comments](Sources/OrderedDictionary.swift).
## Changelog
The changelog is managed on the [GitHub releases page](https://github.com/lukaskubanek/OrderedDictionary/releases).
## Author
Lukas Kubanek // [lukaskubanek.com](http://lukaskubanek.com) // [@kubanekl](https://twitter.com/kubanekl)
## License
**OrderedDictionary** is provided under the [MIT License](LICENSE.md).
-87
View File
@@ -1,5 +1,3 @@
#if swift(>=4.1)
extension OrderedDictionary: Encodable where Key: Encodable, Value: Encodable {
/// __inheritdoc__
@@ -34,91 +32,6 @@ extension OrderedDictionary: Decodable where Key: Decodable, Value: Decodable {
}
}
#else
extension OrderedDictionary: Encodable {
/// __inheritdoc__
public func encode(to encoder: Encoder) throws {
// Since Swift 4.0 lacks the protocol conditional conformance support, we have to make the
// whole OrderedDictionary type conform to Encodable and assert that the key and value
// types conform to Encodable. Furthermore, we leverage a trick of super encoders to be
// able to encode objects without knowing their exact types. This trick was used in the
// standard library for encoding/decoding Dictionary before Swift 4.1.
_assertTypeIsEncodable(Key.self, in: type(of: self))
_assertTypeIsEncodable(Value.self, in: type(of: self))
var container = encoder.unkeyedContainer()
for (key, value) in self {
let keyEncoder = container.superEncoder()
try (key as! Encodable).encode(to: keyEncoder)
let valueEncoder = container.superEncoder()
try (value as! Encodable).encode(to: valueEncoder)
}
}
private func _assertTypeIsEncodable<T>(_ type: T.Type, in wrappingType: Any.Type) {
guard T.self is Encodable.Type else {
if T.self == Encodable.self || T.self == Codable.self {
preconditionFailure("\(wrappingType) does not conform to Encodable because Encodable does not conform to itself. You must use a concrete type to encode or decode.")
} else {
preconditionFailure("\(wrappingType) does not conform to Encodable because \(T.self) does not conform to Encodable.")
}
}
}
}
extension OrderedDictionary: Decodable {
/// __inheritdoc__
public init(from decoder: Decoder) throws {
// Since Swift 4.0 lacks the protocol conditional conformance support, we have to make the
// whole OrderedDictionary type conform to Decodable and assert that the key and value
// types conform to Decodable. Furthermore, we leverage a trick of super decoders to be
// able to decode objects without knowing their exact types. This trick was used in the
// standard library for encoding/decoding Dictionary before Swift 4.1.
self.init()
_assertTypeIsDecodable(Key.self, in: type(of: self))
_assertTypeIsDecodable(Value.self, in: type(of: self))
var container = try decoder.unkeyedContainer()
let keyMetaType = (Key.self as! Decodable.Type)
let valueMetaType = (Value.self as! Decodable.Type)
while !container.isAtEnd {
let keyDecoder = try container.superDecoder()
let key = try keyMetaType.init(from: keyDecoder) as! Key
guard !container.isAtEnd else { throw DecodingError.unkeyedContainerReachedEndBeforeValue(decoder.codingPath) }
let valueDecoder = try container.superDecoder()
let value = try valueMetaType.init(from: valueDecoder) as! Value
self[key] = value
}
}
private func _assertTypeIsDecodable<T>(_ type: T.Type, in wrappingType: Any.Type) {
guard T.self is Decodable.Type else {
if T.self == Decodable.self || T.self == Codable.self {
preconditionFailure("\(wrappingType) does not conform to Decodable because Decodable does not conform to itself. You must use a concrete type to encode or decode.")
} else {
preconditionFailure("\(wrappingType) does not conform to Decodable because \(T.self) does not conform to Decodable.")
}
}
}
}
#endif
extension DecodingError {
@@ -0,0 +1,26 @@
extension OrderedDictionary {
#if swift(>=5.0)
@available(*, deprecated, message: "Please use init(values:uniquelyKeyedBy:).", renamed: "init(values:uniquelyKeyedBy:)")
public init<S: Sequence>(
values: S,
keyedBy extractKey: (Value) -> Key
) where S.Element == Value {
self.init(values: values, uniquelyKeyedBy: extractKey)
}
#endif
@available(*, deprecated, message: "Please use init(values:uniquelyKeyedBy:).", renamed: "init(values:uniquelyKeyedBy:)")
public init(
values: [Value],
keyedBy keyPath: KeyPath<Value, Key>
) {
self.init(values: values, uniquelyKeyedBy: keyPath)
}
@available(*, deprecated, message: "Please use init(uniqueKeysWithValues:).", renamed: "init(uniqueKeysWithValues:)")
public init<S: Sequence>(_ elements: S) where S.Element == Element {
self.init(uniqueKeysWithValues: elements)
}
}
+136 -77
View File
@@ -27,32 +27,20 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
// MARK: - Initialization
// ======================================================= //
/// Creates an empty ordered dictionary.
public init() {}
/// Creates an ordered dictionary from a sequence of values keyed by a key which gets extracted
/// from the value in the provided closure.
///
/// - Parameter values: The sequence of values.
/// - Parameter getKey: The closure which provides a key for the given value from the values
/// sequence.
public init<Values: Sequence>(
values: Values,
keyedBy getKey: (Value) -> Key
) where Values.Element == Value {
self.init(values.map { (getKey($0), $0) })
/// Initializes an empty ordered dictionary.
public init() {
self._orderedKeys = [Key]()
self._keysToValues = [Key: Value]()
}
/// Creates an ordered dictionary from a sequence of values keyed by a key loaded from the value
/// at the given key path.
///
/// - Parameter values: The sequence of values.
/// - Parameter keyPath: The key path for the value to locate its key at.
public init(values: [Value], keyedBy keyPath: KeyPath<Value, Key>) {
self.init(values.map { ($0[keyPath: keyPath], $0) })
/// Initializes an empty ordered dictionary with preallocated space for at least the specified
/// number of elements.
public init(minimumCapacity: Int) {
self.init()
self.reserveCapacity(minimumCapacity)
}
/// Creates an ordered dictionary from a regular unsorted dictionary by sorting it using the
/// Initializes an ordered dictionary from a regular unsorted dictionary by sorting it using
/// the given sort function.
///
/// - Parameter unsorted: The unsorted dictionary.
@@ -61,20 +49,65 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
unsorted: Dictionary<Key, Value>,
areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows {
let elements = try unsorted
.map { (key: $0.key, value: $0.value) }
.sorted(by: areInIncreasingOrder)
let keysAndValues = try Array(unsorted).sorted(by: areInIncreasingOrder)
self.init(elements)
self.init(
uniqueKeysWithValues: keysAndValues,
minimumCapacity: unsorted.count
)
}
/// Creates an ordered dictionary from a sequence of key-value pairs.
/// Initializes an ordered dictionary from a sequence of values keyed by a unique key extracted
/// from the value using the given closure.
///
/// - Parameter elements: The key-value pairs that will make up the new ordered dictionary.
/// Each key in `elements` must be unique.
public init<S: Sequence>(_ elements: S) where S.Element == Element {
for (key, value) in elements {
precondition(!containsKey(key), "Elements sequence contains duplicate keys")
/// - Parameter values: The sequence of values.
/// - Parameter extractKey: The closure which extracts a key from the value. The returned keys
/// must be unique for all values from the sequence.
public init<S: Sequence>(
values: S,
uniquelyKeyedBy extractKey: (Value) throws -> Key
) rethrows where S.Element == Value {
self.init(uniqueKeysWithValues: try values.map { value in
return (try extractKey(value), value)
})
}
/// Initializes an ordered dictionary from a sequence of values keyed by a unique key extracted
/// from the value using the given key path.
///
/// - Parameter values: The sequence of values.
/// - Parameter keyPath: The key path to use for extracting a key from the value. The extracted
/// keys must be unique for all values from the sequence.
public init<S: Sequence>(
values: S,
uniquelyKeyedBy keyPath: KeyPath<Value, Key>
) where S.Element == Value {
self.init(uniqueKeysWithValues: values.map { value in
return (value[keyPath: keyPath], value)
})
}
/// Initializes an ordered dictionary from a sequence of key-value pairs.
///
/// - Parameter keysAndValues: A sequence of key-value pairs to use for the new ordered
/// dictionary. Every key in `keysAndValues` must be unique.
public init<S: Sequence>(
uniqueKeysWithValues keysAndValues: S
) where S.Element == Element {
self.init(
uniqueKeysWithValues: keysAndValues,
minimumCapacity: keysAndValues.underestimatedCount
)
}
private init<S: Sequence>(
uniqueKeysWithValues keysAndValues: S,
minimumCapacity: Int
) where S.Element == Element {
self.init(minimumCapacity: minimumCapacity)
for (key, value) in keysAndValues {
precondition(!containsKey(key), "Sequence of key-value pairs contains duplicate keys")
self[key] = value
}
}
@@ -288,7 +321,11 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
/// - Returns: The index for `key` and its associated value if `key` is in the ordered
/// dictionary; otherwise, `nil`.
public func index(forKey key: Key) -> Index? {
#if swift(>=5.0)
return _orderedKeys.firstIndex(of: key)
#else
return _orderedKeys.index(of: key)
#endif
}
/// Returns the key-value pair at the specified index, or `nil` if there is no key-value pair
@@ -543,7 +580,7 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
public func sorted(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows -> OrderedDictionary<Key, Value> {
return OrderedDictionary(try _sortedElements(by: areInIncreasingOrder))
return OrderedDictionary(uniqueKeysWithValues: try _sortedElements(by: areInIncreasingOrder))
}
private func _sortedElements(
@@ -552,15 +589,73 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
return try sorted(by: areInIncreasingOrder)
}
// ======================================================= //
// MARK: - Mapping Values
// ======================================================= //
/// Returns a new ordered dictionary containing the keys of this ordered dictionary with the
/// values transformed by the given closure by preserving the original order.
public func mapValues<T>(
_ transform: (Value) throws -> T
) rethrows -> OrderedDictionary<Key, T> {
var result = OrderedDictionary<Key, T>()
for (key, value) in self {
result[key] = try transform(value)
}
return result
}
/// Returns a new ordered dictionary containing only the key-value pairs that have non-nil
/// values as the result of transformation by the given closure by preserving the original
/// order.
public func compactMapValues<T>(
_ transform: (Value) throws -> T?
) rethrows -> OrderedDictionary<Key, T> {
var result = OrderedDictionary<Key, T>()
for (key, value) in self {
if let transformedValue = try transform(value) {
result[key] = transformedValue
}
}
return result
}
// ======================================================= //
// MARK: - Capacity
// ======================================================= //
/// The total number of elements that the ordered dictionary can contain without allocating
/// new storage.
public var capacity: Int {
return Swift.min(_orderedKeys.capacity, _keysToValues.capacity)
}
/// Reserves enough space to store the specified number of elements, when appropriate
/// for the underlying types.
///
/// If you are adding a known number of elements to an ordered dictionary, use this method
/// to avoid multiple reallocations. This method ensures that the underlying types of the
/// ordered dictionary have space allocated for at least the requested number of elements.
///
/// - Parameter minimumCapacity: The requested number of elements to store.
public mutating func reserveCapacity(_ minimumCapacity: Int) {
_orderedKeys.reserveCapacity(minimumCapacity)
_keysToValues.reserveCapacity(minimumCapacity)
}
// ======================================================= //
// MARK: - Internal Storage
// ======================================================= //
/// The backing storage for the ordered keys.
fileprivate var _orderedKeys = [Key]()
fileprivate var _orderedKeys: [Key]
/// The backing storage for the mapping of keys to values.
fileprivate var _keysToValues = [Key: Value]()
fileprivate var _keysToValues: [Key: Value]
}
@@ -568,8 +663,6 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
// MARK: - Subtypes
// ======================================================= //
#if swift(>=4.1)
/// A view into an ordered dictionary whose indices are a subrange of the indices of the ordered
/// dictionary.
public typealias OrderedDictionarySlice<Key: Hashable, Value> = Slice<OrderedDictionary<Key, Value>>
@@ -586,45 +679,26 @@ public typealias OrderedDictionaryKeys<Key: Hashable, Value> = LazyMapCollection
/// the base ordered dictionary on-the-fly.
public typealias OrderedDictionaryValues<Key: Hashable, Value> = LazyMapCollection<OrderedDictionary<Key, Value>, Value>
#else
/// A view into an ordered dictionary whose indices are a subrange of the indices of the ordered
/// dictionary.
public typealias OrderedDictionarySlice<Key: Hashable, Value> = BidirectionalSlice<OrderedDictionary<Key, Value>>
/// A collection containing the keys of the ordered dictionary.
///
/// Under the hood this is a lazily evaluated bidirectional collection deriving the keys from
/// the base ordered dictionary on-the-fly.
public typealias OrderedDictionaryKeys<Key: Hashable, Value> = LazyMapBidirectionalCollection<OrderedDictionary<Key, Value>, Key>
/// A collection containing the values of the ordered dictionary.
///
/// Under the hood this is a lazily evaluated bidirectional collection deriving the values from
/// the base ordered dictionary on-the-fly.
public typealias OrderedDictionaryValues<Key: Hashable, Value> = LazyMapBidirectionalCollection<OrderedDictionary<Key, Value>, Value>
#endif
// ======================================================= //
// MARK: - Literals
// ======================================================= //
extension OrderedDictionary: ExpressibleByArrayLiteral {
/// Creates an ordered dictionary initialized from an array literal containing a list of
/// key-value pairs.
/// Initializes an ordered dictionary initialized from an array literal containing a list of
/// key-value pairs. Every key in `elements` must be unique.
public init(arrayLiteral elements: Element...) {
self.init(elements)
self.init(uniqueKeysWithValues: elements)
}
}
extension OrderedDictionary: ExpressibleByDictionaryLiteral {
/// Creates an ordered dictionary initialized from a dictionary literal.
/// Initializes an ordered dictionary initialized from a dictionary literal. Every key in
/// `elements` must be unique.
public init(dictionaryLiteral elements: (Key, Value)...) {
self.init(elements.map { element in
self.init(uniqueKeysWithValues: elements.map { element in
let (key, value) = element
return (key: key, value: value)
})
@@ -636,23 +710,8 @@ extension OrderedDictionary: ExpressibleByDictionaryLiteral {
// MARK: - Equatable Conformance
// ======================================================= //
#if swift(>=4.1)
extension OrderedDictionary: Equatable where Value: Equatable {}
#endif
extension OrderedDictionary where Value: Equatable {
/// Returns a Boolean value that indicates whether the two given ordered dictionaries with
/// equatable values are equal.
public static func == (lhs: OrderedDictionary, rhs: OrderedDictionary) -> Bool {
return lhs._orderedKeys == rhs._orderedKeys
&& lhs._keysToValues == rhs._keysToValues
}
}
// ======================================================= //
// MARK: - Dictionary Extension
// ======================================================= //
+2 -2
View File
@@ -15,13 +15,13 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.2.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2015-2019 Lukas Kubanek. All rights reserved.</string>
<string>Copyright © 2015-2020 Lukas Kubanek. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
+70 -28
View File
@@ -2,26 +2,6 @@ import OrderedDictionary
import Foundation
import XCTest
#if !swift(>=4.1)
/// This is a shim for testing the equality in Swift <4.1.
public func XCTAssertEqual<K, V: Equatable>(
_ expression1: OrderedDictionary<K, V>,
_ expression2: OrderedDictionary<K, V>,
_ message: @autoclosure () -> String = "",
file: StaticString = #file,
line: UInt = #line
) {
return XCTAssertTrue(
expression1 == expression2,
message,
file: file,
line: line
)
}
#endif
struct TestValue: Equatable {
var string: String
static func == (lhs: TestValue, rhs: TestValue) -> Bool {
@@ -42,7 +22,7 @@ class OrderedDictionaryTests: XCTestCase {
("C", 3)
]
let expected = OrderedDictionary<String, Int>([
let expected = OrderedDictionary<String, Int>(uniqueKeysWithValues: [
(key: "A", value: 1),
(key: "B", value: 2),
(key: "C", value: 3)
@@ -58,7 +38,7 @@ class OrderedDictionaryTests: XCTestCase {
"C": 3
]
let expected = OrderedDictionary<String, Int>([
let expected = OrderedDictionary<String, Int>(uniqueKeysWithValues: [
(key: "A", value: 1),
(key: "B", value: 2),
(key: "C", value: 3)
@@ -70,10 +50,10 @@ class OrderedDictionaryTests: XCTestCase {
func testInitializationUsingValuesAndKeyProviderClosure() {
let actual = OrderedDictionary(
values: [1, 2, 3],
keyedBy: { "\($0)" }
uniquelyKeyedBy: { "\($0)" }
)
let expected = OrderedDictionary<String, Int>([
let expected = OrderedDictionary<String, Int>(uniqueKeysWithValues: [
(key: "1", value: 1),
(key: "2", value: 2),
(key: "3", value: 3)
@@ -89,10 +69,10 @@ class OrderedDictionaryTests: XCTestCase {
TestValue(string: "B"),
TestValue(string: "C")
],
keyedBy: \.string
uniquelyKeyedBy: \.string
)
let expected = OrderedDictionary<String, TestValue>([
let expected = OrderedDictionary<String, TestValue>(uniqueKeysWithValues: [
(key: "A", value: TestValue(string: "A")),
(key: "B", value: TestValue(string: "B")),
(key: "C", value: TestValue(string: "C"))
@@ -113,7 +93,7 @@ class OrderedDictionaryTests: XCTestCase {
areInIncreasingOrder: { $0.key < $1.key }
)
let expected = OrderedDictionary([
let expected = OrderedDictionary(uniqueKeysWithValues: [
(key: 1, value: "bar"),
(key: 2, value: "foo"),
(key: 3, value: "bam"),
@@ -133,7 +113,7 @@ class OrderedDictionaryTests: XCTestCase {
3: "bam"
].sorted(by: { $0.key < $1.key })
let expected = OrderedDictionary([
let expected = OrderedDictionary(uniqueKeysWithValues: [
(key: 1, value: "bar"),
(key: 2, value: "foo"),
(key: 3, value: "bam"),
@@ -511,6 +491,28 @@ class OrderedDictionaryTests: XCTestCase {
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Mapping Values
// ======================================================= //
func testMapValues() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let actual = orderedDictionary.mapValues { String($0) }
let expected: OrderedDictionary<String, String> = ["A": "1", "B": "2", "C": "3", "D": "4"]
XCTAssertEqual(actual, expected)
}
func testCompactMapValues() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let actual = orderedDictionary.compactMapValues { $0 % 2 == 0 ? String($0) : nil }
let expected: OrderedDictionary<String, String> = ["B": "2", "D": "4"]
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Slices
// ======================================================= //
@@ -527,6 +529,46 @@ class OrderedDictionaryTests: XCTestCase {
XCTAssert(slice[3] == (key: "D", value: 4))
}
// ============================================================================ //
// MARK: - Capacity
// ============================================================================ //
func testCapacityReservationViaInit() {
let orderedDictionary = OrderedDictionary<String, Int>(minimumCapacity: 10)
XCTAssertGreaterThanOrEqual(orderedDictionary.capacity, 10)
}
func testCapacityReservationViaMethod() {
var orderedDictionary = OrderedDictionary<String, Int>()
XCTAssertEqual(orderedDictionary.capacity, 0)
orderedDictionary.reserveCapacity(10)
XCTAssertGreaterThanOrEqual(orderedDictionary.capacity, 10)
XCTAssertLessThan(orderedDictionary.capacity, 20)
orderedDictionary.reserveCapacity(20)
XCTAssertGreaterThanOrEqual(orderedDictionary.capacity, 20)
}
func testCapacityGrowForElementInsertion() {
var orderedDictionary = OrderedDictionary<String, Int>()
XCTAssertEqual(orderedDictionary.capacity, 0)
orderedDictionary["A"] = 1
XCTAssertEqual(orderedDictionary.capacity, 1)
orderedDictionary["B"] = 2
orderedDictionary["A"] = 3
XCTAssertEqual(orderedDictionary.capacity, 2)
}
// ======================================================= //
// MARK: - Codable
// ======================================================= //
+61
View File
@@ -0,0 +1,61 @@
#if !canImport(ObjectiveC)
import XCTest
extension OrderedDictionaryTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__OrderedDictionaryTests = [
("testAccessingContent", testAccessingContent),
("testAccessingOrderedKeys", testAccessingOrderedKeys),
("testAccessingOrderedValues", testAccessingOrderedValues),
("testAccessingUnsortedDictionary", testAccessingUnsortedDictionary),
("testCapacityGrowForElementInsertion", testCapacityGrowForElementInsertion),
("testCapacityReservationViaInit", testCapacityReservationViaInit),
("testCapacityReservationViaMethod", testCapacityReservationViaMethod),
("testCompactMapValues", testCompactMapValues),
("testCreatingIterator", testCreatingIterator),
("testCreationFromDictionary", testCreationFromDictionary),
("testDebugDescription", testDebugDescription),
("testDescription", testDescription),
("testEmptyDebugDescription", testEmptyDebugDescription),
("testEmptyDescription", testEmptyDescription),
("testEncodingAndDecodingViaJSON", testEncodingAndDecodingViaJSON),
("testEncodingAndDecodingViaPropertyList", testEncodingAndDecodingViaPropertyList),
("testIndexBasedInsertionsWithUniqueKeys", testIndexBasedInsertionsWithUniqueKeys),
("testIndexBasedInsertionWithDuplicateKey", testIndexBasedInsertionWithDuplicateKey),
("testIndexBasedInsertionWithIndexOutOfBounds", testIndexBasedInsertionWithIndexOutOfBounds),
("testIndexBasedInsertionWithNegativeIndex", testIndexBasedInsertionWithNegativeIndex),
("testIndexBasedRemoval", testIndexBasedRemoval),
("testIndexBasedUpdateMethodByDuplicatingKey", testIndexBasedUpdateMethodByDuplicatingKey),
("testIndexBasedUpdateMethodByReplacingSameKey", testIndexBasedUpdateMethodByReplacingSameKey),
("testIndexBasedUpdateMethodWithNewUniqueKey", testIndexBasedUpdateMethodWithNewUniqueKey),
("testInitializationUsingArrayLiteral", testInitializationUsingArrayLiteral),
("testInitializationUsingDictionaryLiteral", testInitializationUsingDictionaryLiteral),
("testInitializationUsingUnsortedDictionaryAndSortFunction", testInitializationUsingUnsortedDictionaryAndSortFunction),
("testInitializationUsingValuesAndKeyProviderClosure", testInitializationUsingValuesAndKeyProviderClosure),
("testInitializationUsingValuesAnyKeyPath", testInitializationUsingValuesAnyKeyPath),
("testKeyBasedModifications", testKeyBasedModifications),
("testKeyBasedRemoval", testKeyBasedRemoval),
("testMapValues", testMapValues),
("testMovingElements", testMovingElements),
("testPopFirstEmpty", testPopFirstEmpty),
("testPopFirstNonEmpty", testPopFirstNonEmpty),
("testPopLastEmpty", testPopLastEmpty),
("testPopLastNonEmpty", testPopLastNonEmpty),
("testRemoveAll", testRemoveAll),
("testRemoveFirstNonEmpty", testRemoveFirstNonEmpty),
("testRemoveLastNonEmpty", testRemoveLastNonEmpty),
("testRetrievingElementAtNonExistentIndex", testRetrievingElementAtNonExistentIndex),
("testSliceAccess", testSliceAccess),
("testSortingWithMutation", testSortingWithMutation),
("testSortingWithoutMutation", testSortingWithoutMutation),
]
}
public func __allTests() -> [XCTestCaseEntry] {
return [
testCase(OrderedDictionaryTests.__allTests__OrderedDictionaryTests),
]
}
#endif