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"