diff --git a/Package.swift b/Package.swift
index c63d500f..a352c21a 100644
--- a/Package.swift
+++ b/Package.swift
@@ -294,7 +294,10 @@ for target:PackageDescription.Target in package.targets
settings.append(.enableUpcomingFeature("BareSlashRegexLiterals"))
settings.append(.enableUpcomingFeature("ConciseMagicFile"))
+ settings.append(.enableUpcomingFeature("DeprecateApplicationMain"))
settings.append(.enableUpcomingFeature("ExistentialAny"))
+ settings.append(.enableUpcomingFeature("GlobalConcurrency"))
+ settings.append(.enableUpcomingFeature("IsolatedDefaultValues"))
settings.append(.enableExperimentalFeature("StrictConcurrency"))
$0 = settings
diff --git a/README.md b/README.md
index 24cce36b..e916b5e2 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-***`mongodb`***
`0.14`
+***`mongodb`***
`0.15`
[![ci status](https://github.com/tayloraswift/swift-mongodb/actions/workflows/ci.yml/badge.svg)](https://github.com/tayloraswift/swift-mongodb/actions/workflows/ci.yml)
diff --git a/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateOperatorEncoder.swift b/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateOperatorEncoder.swift
index 47eaa3ac..2a8bd5c8 100644
--- a/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateOperatorEncoder.swift
+++ b/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateOperatorEncoder.swift
@@ -33,7 +33,7 @@ extension Mongo.PredicateOperatorEncoder:BSON.Encoder
extension Mongo.PredicateOperatorEncoder
{
@frozen public
- enum Binary:String, Hashable, Sendable
+ enum Binary:String, Sendable
{
case bitsAllClear = "$bitsAllClear"
case bitsAllSet = "$bitsAllSet"
@@ -67,7 +67,7 @@ extension Mongo.PredicateOperatorEncoder
extension Mongo.PredicateOperatorEncoder
{
@frozen public
- enum Exists:String, Hashable, Sendable
+ enum Exists:String, Sendable
{
case exists = "$exists"
}
@@ -88,7 +88,7 @@ extension Mongo.PredicateOperatorEncoder
extension Mongo.PredicateOperatorEncoder
{
@frozen public
- enum Metatype:String, Hashable, Sendable
+ enum Metatype:String, Sendable
{
case type = "$type"
}
@@ -121,7 +121,7 @@ extension Mongo.PredicateOperatorEncoder
extension Mongo.PredicateOperatorEncoder
{
@frozen public
- enum Mod:String, Hashable, Sendable
+ enum Mod:String, Sendable
{
case mod = "$mod"
}
@@ -154,7 +154,7 @@ extension Mongo.PredicateOperatorEncoder
extension Mongo.PredicateOperator
{
@frozen public
- enum Recursive:String, Hashable, Sendable
+ enum Recursive:String, Sendable
{
case not = "$not"
case any = "$elemMatch"
@@ -180,7 +180,7 @@ extension Mongo.PredicateOperator
extension Mongo.PredicateOperatorEncoder
{
@frozen public
- enum Regex:String, Hashable, Sendable
+ enum Regex:String, Sendable
{
case regex = "$regex"
}
@@ -201,7 +201,7 @@ extension Mongo.PredicateOperatorEncoder
extension Mongo.PredicateOperatorEncoder
{
@frozen public
- enum Variadic:String, Hashable, Sendable
+ enum Variadic:String, Sendable
{
case all = "$all"
case `in` = "$in"
diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateArray.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateArray.swift
new file mode 100644
index 00000000..8d8e567c
--- /dev/null
+++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateArray.swift
@@ -0,0 +1,22 @@
+import BSON
+
+extension Mongo
+{
+ @frozen public
+ struct UpdateArray:BSONRepresentable, BSONDecodable, BSONEncodable, Sendable
+ {
+ public
+ var bson:BSON.Document
+
+ @inlinable public
+ init(_ bson:BSON.Document)
+ {
+ self.bson = bson
+ }
+ }
+}
+extension Mongo.UpdateArray:Mongo.EncodableDocument
+{
+ public
+ typealias Encoder = Mongo.UpdateArrayEncoder
+}
diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateArrayEncoder.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateArrayEncoder.swift
new file mode 100644
index 00000000..7e808a2d
--- /dev/null
+++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateArrayEncoder.swift
@@ -0,0 +1,92 @@
+import BSON
+
+extension Mongo
+{
+ @frozen public
+ struct UpdateArrayEncoder:Sendable
+ {
+ @usableFromInline
+ var bson:BSON.DocumentEncoder
+
+ @inlinable internal
+ init(bson:BSON.DocumentEncoder)
+ {
+ self.bson = bson
+ }
+ }
+}
+extension Mongo.UpdateArrayEncoder:BSON.Encoder
+{
+ @inlinable public
+ init(_ output:consuming BSON.Output)
+ {
+ self.init(bson: .init(output))
+ }
+
+ @inlinable public consuming
+ func move() -> BSON.Output { self.bson.move() }
+
+ @inlinable public static
+ var type:BSON.AnyType { .document }
+}
+
+extension Mongo.UpdateArrayEncoder
+{
+ @frozen public
+ enum Each:String, Sendable
+ {
+ case each = "$each"
+ }
+
+ @inlinable public
+ subscript(key:Each) -> Array? where Array:BSONEncodable
+ {
+ get
+ {
+ nil
+ }
+ set(value)
+ {
+ value?.encode(to: &self.bson[with: key])
+ }
+ }
+}
+extension Mongo.UpdateArrayEncoder
+{
+ @frozen public
+ enum Index:String, Sendable
+ {
+ case position = "$position"
+ case sort = "$sort"
+ }
+
+ @inlinable public
+ subscript(key:Index) -> Int?
+ {
+ get
+ {
+ nil
+ }
+ set(value)
+ {
+ value?.encode(to: &self.bson[with: key])
+ }
+ }
+}
+extension Mongo.UpdateArrayEncoder
+{
+ @frozen public
+ enum Sort:String, Sendable
+ {
+ case sort = "$sort"
+ }
+
+ @inlinable public
+ subscript(key:Sort, yield:(inout Mongo.SortEncoder) -> ()) -> Void
+ {
+ mutating get
+ {
+ yield(&self.bson[with: key][as: Mongo.SortEncoder.self])
+ }
+ }
+}
diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateEncoder.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateEncoder.swift
index 8d85ccd0..d113ccbf 100644
--- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateEncoder.swift
+++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateEncoder.swift
@@ -52,7 +52,7 @@ extension Mongo.UpdateEncoder
extension Mongo.UpdateEncoder
{
@frozen public
- enum Assignment:String, Hashable, Sendable
+ enum Assignment:String, Sendable, Mongo.UpdateValueOperator
{
case set = "$set"
case setOnInsert = "$setOnInsert"
@@ -86,7 +86,7 @@ extension Mongo.UpdateEncoder
extension Mongo.UpdateEncoder
{
@frozen public
- enum Bit:String, Hashable, Sendable
+ enum Bit:String, Sendable
{
case bit = "$bit"
}
@@ -104,7 +104,7 @@ extension Mongo.UpdateEncoder
extension Mongo.UpdateEncoder
{
@frozen public
- enum CurrentDate:String, Hashable, Sendable
+ enum CurrentDate:String, Sendable
{
case currentDate = "$currentDate"
}
@@ -122,7 +122,7 @@ extension Mongo.UpdateEncoder
extension Mongo.UpdateEncoder
{
@frozen public
- enum Pop:String, Hashable, Sendable
+ enum Pop:String, Sendable
{
case pop = "$pop"
}
@@ -140,7 +140,7 @@ extension Mongo.UpdateEncoder
extension Mongo.UpdateEncoder
{
@frozen public
- enum Pull:String, Hashable, Sendable
+ enum Pull:String, Sendable, Mongo.UpdateValueOperator
{
case pull = "$pull"
}
@@ -158,9 +158,8 @@ extension Mongo.UpdateEncoder
extension Mongo.UpdateEncoder
{
@frozen public
- enum Reduction:String, Hashable, Sendable
+ enum Reduction:String, Sendable, Mongo.UpdateValueOperator
{
- case addToSet = "$addToSet"
case max = "$max"
case min = "$min"
// $pullAll is a reduction, it only accepts field values that form
@@ -181,7 +180,7 @@ extension Mongo.UpdateEncoder
extension Mongo.UpdateEncoder
{
@frozen public
- enum Rename:String, Hashable, Sendable
+ enum Rename:String, Sendable
{
case rename = "$rename"
}
@@ -197,12 +196,31 @@ extension Mongo.UpdateEncoder
}
}
extension Mongo.UpdateEncoder
+{
+ @frozen public
+ enum ArrayUnion:String, Sendable, Mongo.UpdateValueOperator
+ {
+ case addToSet = "$addToSet"
+ case push = "$push"
+ }
+
+ @inlinable public
+ subscript(key:ArrayUnion,
+ yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void
+ {
+ mutating get
+ {
+ yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self])
+ }
+ }
+}
+extension Mongo.UpdateEncoder
{
/// Takes a document and removes the specified fields.
/// Not to be confused with the ``Mongo.Pipeline.Unset/unset``
/// aggregation pipeline stage, which can take a field path directly.
@frozen public
- enum Unset:String, Hashable, Sendable
+ enum Unset:String, Sendable
{
case unset = "$unset"
}
diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFieldsEncoder.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFieldsEncoder.swift
index cad39c85..d6861aaa 100644
--- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFieldsEncoder.swift
+++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFieldsEncoder.swift
@@ -31,6 +31,21 @@ extension Mongo.UpdateFieldsEncoder:BSON.Encoder
var type:BSON.AnyType { .document }
}
+extension Mongo.UpdateFieldsEncoder where Operator:Mongo.UpdateValueOperator
+{
+ @inlinable public
+ subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable
+ {
+ get
+ {
+ nil
+ }
+ set(value)
+ {
+ value?.encode(to: &self.bson[with: path])
+ }
+ }
+}
extension Mongo.UpdateFieldsEncoder
{
@inlinable public
@@ -42,7 +57,7 @@ extension Mongo.UpdateFieldsEncoder
}
set(value)
{
- value?.encode(to: &self.bson[with: path.stem])
+ value?.encode(to: &self.bson[with: path])
}
}
@inlinable public
@@ -54,7 +69,7 @@ extension Mongo.UpdateFieldsEncoder
}
set(value)
{
- value?.encode(to: &self.bson[with: path.stem])
+ value?.encode(to: &self.bson[with: path])
}
}
}
@@ -66,19 +81,6 @@ extension Mongo.UpdateFieldsEncoder
mutating
get { yield(&self.bson[with: path][as: Mongo.ExpressionEncoder.self]) }
}
-
- @inlinable public
- subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable
- {
- get
- {
- nil
- }
- set(value)
- {
- value?.encode(to: &self.bson[with: path])
- }
- }
}
extension Mongo.UpdateFieldsEncoder
{
@@ -95,7 +97,7 @@ extension Mongo.UpdateFieldsEncoder
{
{
$0[name] = operand
- } (&self.bson[with: path.stem][
+ } (&self.bson[with: path][
as: BSON.DocumentEncoder.self])
}
}
@@ -113,7 +115,7 @@ extension Mongo.UpdateFieldsEncoder
{
{
$0[name] = operand
- } (&self.bson[with: path.stem][
+ } (&self.bson[with: path][
as: BSON.DocumentEncoder.self])
}
}
@@ -132,7 +134,7 @@ extension Mongo.UpdateFieldsEncoder
{
{
$0["$type"] = "date"
- } (&self.bson[with: path.stem][as: BSON.DocumentEncoder.self])
+ } (&self.bson[with: path][as: BSON.DocumentEncoder.self])
}
}
}
@@ -147,12 +149,13 @@ extension Mongo.UpdateFieldsEncoder
}
set(value)
{
- value?.encode(to: &self.bson[with: path.stem])
+ value?.encode(to: &self.bson[with: path])
}
}
}
extension Mongo.UpdateFieldsEncoder
{
+ @available(*, deprecated, message: "use the streaming subscript instead")
@inlinable public
subscript(path:Mongo.AnyKeyPath) -> Mongo.PredicateOperator?
{
@@ -162,35 +165,24 @@ extension Mongo.UpdateFieldsEncoder
}
set(value)
{
- value?.encode(to: &self.bson[with: path.stem])
+ value?.encode(to: &self.bson[with: path])
}
}
+
@inlinable public
- subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable
+ subscript(path:Mongo.AnyKeyPath, yield:(inout Mongo.PredicateOperatorEncoder) -> ()) -> Void
{
- get
- {
- nil
- }
- set(value)
- {
- value?.encode(to: &self.bson[with: path.stem])
- }
+ mutating
+ get { yield(&self.bson[with: path][as: Mongo.PredicateOperatorEncoder.self]) }
}
}
-extension Mongo.UpdateFieldsEncoder
+extension Mongo.UpdateFieldsEncoder
{
@inlinable public
- subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable
+ subscript(path:Mongo.AnyKeyPath, yield:(inout Mongo.UpdateArrayEncoder) -> ()) -> Void
{
- get
- {
- nil
- }
- set(value)
- {
- value?.encode(to: &self.bson[with: path.stem])
- }
+ mutating
+ get { yield(&self.bson[with: path][as: Mongo.UpdateArrayEncoder.self]) }
}
}
extension Mongo.UpdateFieldsEncoder
diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateModifier.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateModifier.swift
deleted file mode 100644
index b6057ea6..00000000
--- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateModifier.swift
+++ /dev/null
@@ -1,2 +0,0 @@
-// TODO: figure out how to model `$each`, etc. We cannot make this a document type,
-// because then it would be ambiguous with ordinary nested BSON documents.
diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateValueOperator.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateValueOperator.swift
new file mode 100644
index 00000000..cf5878be
--- /dev/null
+++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateValueOperator.swift
@@ -0,0 +1,10 @@
+extension Mongo
+{
+ /// A value operator is an update operator that encodes a document that can contain fields
+ /// of arbitrary ``BSONEncodable`` types. It has no requirements, as it only exists to gate
+ /// the subscripts of ``UpdateFieldsEncoder``.
+ public
+ protocol UpdateValueOperator
+ {
+ }
+}
diff --git a/Sources/MongoBuiltins/Expressions/Mongo.ExpressionEncoder.swift b/Sources/MongoBuiltins/Expressions/Mongo.ExpressionEncoder.swift
index b2a3a699..27099056 100644
--- a/Sources/MongoBuiltins/Expressions/Mongo.ExpressionEncoder.swift
+++ b/Sources/MongoBuiltins/Expressions/Mongo.ExpressionEncoder.swift
@@ -32,7 +32,7 @@ extension Mongo.ExpressionEncoder:BSON.Encoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Unary:String, Hashable, Sendable
+ enum Unary:String, Sendable
{
case abs = "$abs"
case arrayToObject = "$arrayToObject"
@@ -69,7 +69,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum UnaryParenthesized:String, Hashable, Sendable
+ enum UnaryParenthesized:String, Sendable
{
case isArray = "$isArray"
case not = "$not"
@@ -106,7 +106,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Binary:String, Hashable, Sendable
+ enum Binary:String, Sendable
{
case cmp = "$cmp"
case eq = "$eq"
@@ -144,7 +144,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Cond:String, Hashable, Sendable
+ enum Cond:String, Sendable
{
case cond = "$cond"
}
@@ -175,7 +175,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Division:String, Hashable, Sendable
+ enum Division:String, Sendable
{
case divide = "$divide"
case mod = "$mod"
@@ -205,7 +205,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Element:String, Hashable, Sendable
+ enum Element:String, Sendable
{
case element = "$arrayElemAt"
@@ -239,7 +239,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum In:String, Hashable, Sendable
+ enum In:String, Sendable
{
case `in` = "$in"
}
@@ -268,7 +268,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Log:String, Hashable, Sendable
+ enum Log:String, Sendable
{
case log = "$log"
}
@@ -297,7 +297,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Pow:String, Hashable, Sendable
+ enum Pow:String, Sendable
{
case pow = "$pow"
}
@@ -326,7 +326,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Quantization:String, Hashable, Sendable
+ enum Quantization:String, Sendable
{
case round = "$round"
case trunc = "$trunc"
@@ -368,7 +368,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Range:String, Hashable, Sendable
+ enum Range:String, Sendable
{
case range = "$range"
}
@@ -410,7 +410,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Slice:String, Hashable, Sendable
+ enum Slice:String, Sendable
{
case slice = "$slice"
}
@@ -452,7 +452,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Subtract:String, Hashable, Sendable
+ enum Subtract:String, Sendable
{
case subtract = "$subtract"
}
@@ -480,7 +480,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Superlative:String, Hashable, Sendable
+ enum Superlative:String, Sendable
{
case first = "$firstN"
case last = "$lastN"
@@ -524,7 +524,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Variadic:String, Hashable, Sendable
+ enum Variadic:String, Sendable
{
case add = "$add"
case and = "$and"
@@ -627,7 +627,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Filter:String, Hashable, Sendable
+ enum Filter:String, Sendable
{
case filter = "$filter"
}
@@ -648,7 +648,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Map:String, Hashable, Sendable
+ enum Map:String, Sendable
{
case map = "$map"
}
@@ -669,7 +669,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Reduce:String, Hashable, Sendable
+ enum Reduce:String, Sendable
{
case reduce = "$reduce"
}
@@ -690,7 +690,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum SortArray:String, Hashable, Sendable
+ enum SortArray:String, Sendable
{
case sortArray = "$sortArray"
}
@@ -711,7 +711,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Switch:String, Hashable, Sendable
+ enum Switch:String, Sendable
{
case `switch` = "$switch"
}
@@ -732,7 +732,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Zip:String, Hashable, Sendable
+ enum Zip:String, Sendable
{
case zip = "$zip"
}
@@ -754,7 +754,7 @@ extension Mongo.ExpressionEncoder
extension Mongo.ExpressionEncoder
{
@frozen public
- enum Index:String, Hashable, Sendable
+ enum Index:String, Sendable
{
case elementIndex = "indexOfArray"
case unicodeScalarIndex = "indexOfCP"