diff --git a/Sources/BSONABI/Fields/BSON.Key.swift b/Sources/BSONABI/Fields/BSON.Key.swift index d0ac6ec3..ea0f5d1f 100644 --- a/Sources/BSONABI/Fields/BSON.Key.swift +++ b/Sources/BSONABI/Fields/BSON.Key.swift @@ -65,7 +65,7 @@ extension BSON.Key /// /// Some applications that use BSON, such as MongoDB, consider `.` /// characters significant. - @available(*, deprecated, message: "Prefer 'Mongo.KeyPath' instead.") + @available(*, deprecated, message: "Prefer 'Mongo.AnyKeyPath' instead.") @inlinable public static func / (self:Self, next:Self) -> Self { diff --git a/Sources/MongoABI/Mongo.KeyPath.swift b/Sources/MongoABI/Mongo.AnyKeyPath.swift similarity index 58% rename from Sources/MongoABI/Mongo.KeyPath.swift rename to Sources/MongoABI/Mongo.AnyKeyPath.swift index c1fe1c06..27858f6f 100644 --- a/Sources/MongoABI/Mongo.KeyPath.swift +++ b/Sources/MongoABI/Mongo.AnyKeyPath.swift @@ -2,8 +2,12 @@ import BSON extension Mongo { + @available(*, deprecated, renamed: "AnyKeyPath") + public + typealias KeyPath = AnyKeyPath + @frozen public - struct KeyPath:Equatable, Hashable, Sendable + struct AnyKeyPath:Equatable, Hashable, Sendable { public var stem:BSON.Key @@ -15,18 +19,21 @@ extension Mongo } } } -extension Mongo.KeyPath +extension Mongo.AnyKeyPath:RawRepresentable { + /// See ``rawValue``. @inlinable public init(rawValue:String) { self.init(stem: .init(rawValue: rawValue)) } + /// The key path stem, which is the entire key path minus the leading `$` character that + /// would normally appear when encoding the key path in an expression. @inlinable public var rawValue:String { self.stem.rawValue } } -extension Mongo.KeyPath:ExpressibleByStringLiteral +extension Mongo.AnyKeyPath:ExpressibleByStringLiteral { @inlinable public init(stringLiteral:String) @@ -34,15 +41,15 @@ extension Mongo.KeyPath:ExpressibleByStringLiteral self.init(rawValue: stringLiteral) } } -extension Mongo.KeyPath:CustomStringConvertible +extension Mongo.AnyKeyPath:CustomStringConvertible { @inlinable public var description:String { "$\(self.stem)" } } -extension Mongo.KeyPath:BSONStringEncodable +extension Mongo.AnyKeyPath:BSONStringEncodable { } -extension Mongo.KeyPath +extension Mongo.AnyKeyPath { /// Creates a key path by joining two key paths with a `.` character. @inlinable public static diff --git a/Sources/MongoABI/Mongo.Variable.swift b/Sources/MongoABI/Mongo.Variable.swift index 000f9e00..80230d09 100644 --- a/Sources/MongoABI/Mongo.Variable.swift +++ b/Sources/MongoABI/Mongo.Variable.swift @@ -18,9 +18,9 @@ extension Mongo extension Mongo.Variable where T:MongoMasterCodingModel { @inlinable public - subscript(key:T.CodingKey) -> Mongo.KeyPath + subscript(key:T.CodingKey) -> Mongo.AnyKeyPath { - // When the key path is encoded, ``Mongo.KeyPath`` + // When the key path is encoded, ``Mongo.AnyKeyPath`` // will add an additional prefixed dollar sign. .init(rawValue: "$\(self.name).\(key.rawValue)") } diff --git a/Sources/MongoABI/MongoMasterCodingModel.swift b/Sources/MongoABI/MongoMasterCodingModel.swift index 5de0c056..993d19ab 100644 --- a/Sources/MongoABI/MongoMasterCodingModel.swift +++ b/Sources/MongoABI/MongoMasterCodingModel.swift @@ -12,7 +12,7 @@ protocol MongoMasterCodingModel extension MongoMasterCodingModel { @inlinable public static - subscript(key:CodingKey) -> Mongo.KeyPath + subscript(key:CodingKey) -> Mongo.AnyKeyPath { .init(rawValue: key.rawValue) } diff --git a/Sources/MongoBuiltins/BSONEncodable (ext).swift b/Sources/MongoBuiltins/BSONEncodable (ext).swift index 152d1072..a592f190 100644 --- a/Sources/MongoBuiltins/BSONEncodable (ext).swift +++ b/Sources/MongoBuiltins/BSONEncodable (ext).swift @@ -3,10 +3,10 @@ import BSON extension BSONEncodable where Self == Mongo.Expression { @inlinable public static - func expr(with populate:(inout Self) throws -> ()) rethrows -> Self + func expr(with populate:(inout Mongo.ExpressionEncoder) throws -> ()) rethrows -> Self { - var expr:Self = .init(.init()) - try populate(&expr) - return expr + var document:BSON.Document = .init() + try populate(&document.output[as: Mongo.ExpressionEncoder.self]) + return .init(document) } } diff --git a/Sources/MongoBuiltins/Documents/Bucket/Mongo.BucketOutputDocument.swift b/Sources/MongoBuiltins/Documents/Bucket/Mongo.BucketOutputDocument.swift index 2f980e0c..43fa5a19 100644 --- a/Sources/MongoBuiltins/Documents/Bucket/Mongo.BucketOutputDocument.swift +++ b/Sources/MongoBuiltins/Documents/Bucket/Mongo.BucketOutputDocument.swift @@ -19,7 +19,7 @@ extension Mongo extension Mongo.BucketOutputDocument { @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.Accumulator? + subscript(path:Mongo.AnyKeyPath) -> Mongo.Accumulator? { get { diff --git a/Sources/MongoBuiltins/Documents/Facet/Mongo.FacetDocument.swift b/Sources/MongoBuiltins/Documents/Facet/Mongo.FacetDocument.swift index 0dc80992..cda8d1dc 100644 --- a/Sources/MongoBuiltins/Documents/Facet/Mongo.FacetDocument.swift +++ b/Sources/MongoBuiltins/Documents/Facet/Mongo.FacetDocument.swift @@ -19,7 +19,7 @@ extension Mongo extension Mongo.FacetDocument { @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.Pipeline? + subscript(path:Mongo.AnyKeyPath) -> Mongo.Pipeline? { get { diff --git a/Sources/MongoBuiltins/Documents/Group/Mongo.GroupDocument.swift b/Sources/MongoBuiltins/Documents/Group/Mongo.GroupDocument.swift index 070c78fa..4f997f9e 100644 --- a/Sources/MongoBuiltins/Documents/Group/Mongo.GroupDocument.swift +++ b/Sources/MongoBuiltins/Documents/Group/Mongo.GroupDocument.swift @@ -19,7 +19,7 @@ extension Mongo extension Mongo.GroupDocument { @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.Accumulator? + subscript(path:Mongo.AnyKeyPath) -> Mongo.Accumulator? { get { diff --git a/Sources/MongoBuiltins/Documents/Let/Mongo.LetDocument.swift b/Sources/MongoBuiltins/Documents/Let/Mongo.LetDocument.swift index 0887388b..398c1968 100644 --- a/Sources/MongoBuiltins/Documents/Let/Mongo.LetDocument.swift +++ b/Sources/MongoBuiltins/Documents/Let/Mongo.LetDocument.swift @@ -19,7 +19,7 @@ extension Mongo extension Mongo.LetDocument { @inlinable public - subscript(path:Mongo.KeyPath) -> Encodable? + subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable { get diff --git a/Sources/MongoBuiltins/Documents/Lookup/Mongo.LookupDocument.swift b/Sources/MongoBuiltins/Documents/Lookup/Mongo.LookupDocument.swift index 400699da..b5c001c8 100644 --- a/Sources/MongoBuiltins/Documents/Lookup/Mongo.LookupDocument.swift +++ b/Sources/MongoBuiltins/Documents/Lookup/Mongo.LookupDocument.swift @@ -19,7 +19,7 @@ extension Mongo extension Mongo.LookupDocument { @inlinable public - subscript(key:Field) -> Mongo.KeyPath? + subscript(key:Field) -> Mongo.AnyKeyPath? { get { diff --git a/Sources/MongoBuiltins/Documents/Merge/Mongo.MergeDocument.swift b/Sources/MongoBuiltins/Documents/Merge/Mongo.MergeDocument.swift index 67515c91..bb46c971 100644 --- a/Sources/MongoBuiltins/Documents/Merge/Mongo.MergeDocument.swift +++ b/Sources/MongoBuiltins/Documents/Merge/Mongo.MergeDocument.swift @@ -44,7 +44,7 @@ extension Mongo.MergeDocument } @inlinable public - subscript(key:On) -> Mongo.KeyPath? + subscript(key:On) -> Mongo.AnyKeyPath? { get { diff --git a/Sources/MongoBuiltins/Documents/Mongo.AnyKeyPath (ext).swift b/Sources/MongoBuiltins/Documents/Mongo.AnyKeyPath (ext).swift new file mode 100644 index 00000000..de586bd3 --- /dev/null +++ b/Sources/MongoBuiltins/Documents/Mongo.AnyKeyPath (ext).swift @@ -0,0 +1,5 @@ +import MongoABI + +extension Mongo.AnyKeyPath:_MongoExpressionRestrictedEncodable +{ +} diff --git a/Sources/MongoBuiltins/Documents/Mongo.KeyPath (ext).swift b/Sources/MongoBuiltins/Documents/Mongo.KeyPath (ext).swift deleted file mode 100644 index ba1fe3a3..00000000 --- a/Sources/MongoBuiltins/Documents/Mongo.KeyPath (ext).swift +++ /dev/null @@ -1,5 +0,0 @@ -import MongoABI - -extension Mongo.KeyPath:_MongoExpressionRestrictedEncodable -{ -} diff --git a/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateDocument.swift b/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateDocument.swift index efb2e511..15df434a 100644 --- a/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateDocument.swift +++ b/Sources/MongoBuiltins/Documents/Predicate/Mongo.PredicateDocument.swift @@ -30,7 +30,7 @@ extension Mongo.PredicateDocument /// ``PredicateOperator`` has no subscripts that accept string /// literals, so it will never conflict with ``BSON.Document``. @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.PredicateOperator? + subscript(path:Mongo.AnyKeyPath) -> Mongo.PredicateOperator? { get { @@ -42,7 +42,7 @@ extension Mongo.PredicateDocument } } @inlinable public - subscript(path:Mongo.KeyPath) -> Self? + subscript(path:Mongo.AnyKeyPath) -> Self? { get { @@ -57,7 +57,7 @@ extension Mongo.PredicateDocument // ``_MongoExpressionRestrictedEncodable``-gated diagnostic subscript. @_disfavoredOverload @inlinable public - subscript(path:Mongo.KeyPath) -> Encodable? where Encodable:BSONEncodable + subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable { get { @@ -76,7 +76,7 @@ extension Mongo.PredicateDocument even in a '$match' stage of an aggregation pipeline. """) public - subscript(path:Mongo.KeyPath) -> Expression? + subscript(path:Mongo.AnyKeyPath) -> Expression? where Expression:_MongoExpressionRestrictedEncodable { get diff --git a/Sources/MongoBuiltins/Documents/Projection/Mongo.ProjectionDocument.swift b/Sources/MongoBuiltins/Documents/Projection/Mongo.ProjectionDocument.swift index 7c051f34..b82833b4 100644 --- a/Sources/MongoBuiltins/Documents/Projection/Mongo.ProjectionDocument.swift +++ b/Sources/MongoBuiltins/Documents/Projection/Mongo.ProjectionDocument.swift @@ -24,7 +24,7 @@ extension Mongo.ProjectionDocument /// ``ProjectionOperator`` has no subscripts that accept string /// literals, so it will never conflict with ``BSON.Document``. @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.ProjectionOperator? + subscript(path:Mongo.AnyKeyPath) -> Mongo.ProjectionOperator? { get { @@ -36,7 +36,7 @@ extension Mongo.ProjectionDocument } } @inlinable public - subscript(path:Mongo.KeyPath) -> Encodable? where Encodable:BSONEncodable + subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable { get { diff --git a/Sources/MongoBuiltins/Documents/Set/Mongo.SetDocument.swift b/Sources/MongoBuiltins/Documents/Set/Mongo.SetDocument.swift index 6d2fc718..c230d68a 100644 --- a/Sources/MongoBuiltins/Documents/Set/Mongo.SetDocument.swift +++ b/Sources/MongoBuiltins/Documents/Set/Mongo.SetDocument.swift @@ -19,7 +19,7 @@ extension Mongo extension Mongo.SetDocument { @inlinable public - subscript(path:Mongo.KeyPath) -> Encodable? where Encodable:BSONEncodable + subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable { get { @@ -27,7 +27,7 @@ extension Mongo.SetDocument } set(value) { - value?.encode(to: &self.bson[with: path.stem]) + value?.encode(to: &self.bson[with: path]) } } } diff --git a/Sources/MongoBuiltins/Documents/Sort/Mongo.SortDocument.swift b/Sources/MongoBuiltins/Documents/Sort/Mongo.SortDocument.swift index 094cd24a..7e294aea 100644 --- a/Sources/MongoBuiltins/Documents/Sort/Mongo.SortDocument.swift +++ b/Sources/MongoBuiltins/Documents/Sort/Mongo.SortDocument.swift @@ -21,7 +21,7 @@ extension Mongo.SortDocument @available(*, unavailable, message: "pass the `(+)` or `(-)` operator functions to specify sort direction.") @inlinable public - subscript(path:Mongo.KeyPath) -> Int? + subscript(path:Mongo.AnyKeyPath) -> Int? { get { @@ -50,7 +50,7 @@ extension Mongo.SortDocument } } @inlinable public - subscript(path:Mongo.KeyPath) -> ((Mongo.SortAscending) -> Never)? + subscript(path:Mongo.AnyKeyPath) -> ((Mongo.SortAscending) -> Never)? { get { @@ -81,7 +81,7 @@ extension Mongo.SortDocument } } @inlinable public - subscript(path:Mongo.KeyPath) -> ((Mongo.SortDescending) -> Never)? + subscript(path:Mongo.AnyKeyPath) -> ((Mongo.SortDescending) -> Never)? { get { @@ -96,7 +96,7 @@ extension Mongo.SortDocument } } @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.SortOperator? + subscript(path:Mongo.AnyKeyPath) -> Mongo.SortOperator? { get { diff --git a/Sources/MongoBuiltins/Documents/Unwind/Mongo.UnwindDocument.swift b/Sources/MongoBuiltins/Documents/Unwind/Mongo.UnwindDocument.swift index 33aff6b9..fb987283 100644 --- a/Sources/MongoBuiltins/Documents/Unwind/Mongo.UnwindDocument.swift +++ b/Sources/MongoBuiltins/Documents/Unwind/Mongo.UnwindDocument.swift @@ -19,7 +19,7 @@ extension Mongo extension Mongo.UnwindDocument { @inlinable public - subscript(key:Field) -> Mongo.KeyPath? + subscript(key:Field) -> Mongo.AnyKeyPath? { get { diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.swift index 01925def..b1550fb7 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.swift @@ -3,7 +3,7 @@ import BSON extension Mongo { @frozen public - struct UpdateDocument:MongoDocumentDSL, Sendable + struct UpdateDocument:Sendable { public var bson:BSON.Document @@ -15,114 +15,8 @@ extension Mongo } } } -extension Mongo.UpdateDocument +extension Mongo.UpdateDocument:MongoDocumentDSL { - @inlinable public - subscript(key:Arithmetic) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Bit) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:CurrentDate) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Pop) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Pull) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - - @inlinable public - subscript(key:Reduction) -> Document? - where Document:BSONEncodable - { - get { nil } - set (value) - { - value?.encode(to: &self.bson[with: key]) - } - } - - @inlinable public - subscript(key:Reduction) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Rename) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Unset) -> Mongo.UpdateFields? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } + public + typealias Encoder = Mongo.UpdateDocumentEncoder } diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Arithmetic.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Arithmetic.swift similarity index 77% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Arithmetic.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Arithmetic.swift index b099e95c..f0ebf757 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Arithmetic.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Arithmetic.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { @frozen public enum Arithmetic:String, Hashable, Sendable diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Assignment.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Assignment.swift new file mode 100644 index 00000000..e53030cc --- /dev/null +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Assignment.swift @@ -0,0 +1,9 @@ +extension Mongo.UpdateDocumentEncoder +{ + @frozen public + enum Assignment:String, Hashable, Sendable + { + case set = "$set" + case setOnInsert = "$setOnInsert" + } +} diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Bit.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Bit.swift similarity index 72% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Bit.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Bit.swift index 2cc54492..4cfbc91f 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Bit.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Bit.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { @frozen public enum Bit:String, Hashable, Sendable diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.CurrentDate.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.CurrentDate.swift similarity index 76% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.CurrentDate.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.CurrentDate.swift index 9bc1880c..bbff39be 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.CurrentDate.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.CurrentDate.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { @frozen public enum CurrentDate:String, Hashable, Sendable diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Pop.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Pop.swift similarity index 72% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Pop.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Pop.swift index a7c087fb..e127c534 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Pop.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Pop.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { @frozen public enum Pop:String, Hashable, Sendable diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Pull.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Pull.swift similarity index 73% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Pull.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Pull.swift index 43fc0f96..b0e41872 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Pull.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Pull.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { @frozen public enum Pull:String, Hashable, Sendable diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Reduction.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Reduction.swift similarity index 66% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Reduction.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Reduction.swift index e4c36d04..843c088f 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Reduction.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Reduction.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { @frozen public enum Reduction:String, Hashable, Sendable @@ -9,7 +9,10 @@ extension Mongo.UpdateDocument // $pullAll is a reduction, it only accepts field values that form // BSON lists, but we can’t represent that in our type system. case pullAll = "$pullAll" + + @available(*, unavailable, renamed: "Mongo.UpdateDocument.Assignment.set") case set = "$set" + @available(*, unavailable, renamed: "Mongo.UpdateDocument.Assignment.setOnInsert") case setOnInsert = "$setOnInsert" } } diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Rename.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Rename.swift similarity index 74% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Rename.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Rename.swift index e844c831..267173e4 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Rename.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Rename.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { @frozen public enum Rename:String, Hashable, Sendable diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Unset.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Unset.swift similarity index 89% rename from Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Unset.swift rename to Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Unset.swift index 053c204c..8b7b21f7 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocument.Unset.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.Unset.swift @@ -1,4 +1,4 @@ -extension Mongo.UpdateDocument +extension Mongo.UpdateDocumentEncoder { /// Takes a document and removes the specified fields. /// Not to be confused with the ``Mongo.PipelineState.Unset/unset`` diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.swift new file mode 100644 index 00000000..caabb162 --- /dev/null +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateDocumentEncoder.swift @@ -0,0 +1,228 @@ +import BSON +import MongoABI + +extension Mongo +{ + @frozen public + struct UpdateDocumentEncoder:Sendable + { + @usableFromInline + var bson:BSON.DocumentEncoder + + @inlinable internal + init(bson:BSON.DocumentEncoder) + { + self.bson = bson + } + } +} +extension Mongo.UpdateDocumentEncoder: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.UpdateDocumentEncoder +{ + @inlinable public + subscript(key:Arithmetic, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:Assignment, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:Bit, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:CurrentDate, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:Pop, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:Pull, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:Reduction, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:Rename, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } + + @inlinable public + subscript(key:Unset, + yield:(inout Mongo.UpdateFieldsEncoder) -> ()) -> Void + { + mutating get + { + yield(&self.bson[with: key][as: Mongo.UpdateFieldsEncoder.self]) + } + } +} + +@available(*, deprecated, message: "Use the functional subscripts instead.") +extension Mongo.UpdateDocumentEncoder +{ + @inlinable public + subscript(key:Arithmetic) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + + @inlinable public + subscript(key:Bit) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:CurrentDate) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Pop) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Pull) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + + @inlinable public + subscript(key:Reduction) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + + @inlinable public + subscript(key:Rename) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Unset) -> Mongo.UpdateFields? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } +} diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFields.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFields.swift index 0cff6ba2..8d95ea2f 100644 --- a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFields.swift +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFields.swift @@ -4,7 +4,7 @@ import MongoABI extension Mongo { @frozen public - struct UpdateFields:MongoDocumentDSL, Sendable + struct UpdateFields:Sendable { public var bson:BSON.Document @@ -16,173 +16,8 @@ extension Mongo } } } -extension Mongo.UpdateFields +extension Mongo.UpdateFields:MongoDocumentDSL { - @inlinable public - subscript(path:Mongo.KeyPath) -> Int? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: path.stem]) - } - } - @inlinable public - subscript(path:Mongo.KeyPath) -> Double? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: path.stem]) - } - } -} -extension Mongo.UpdateFields -{ - @inlinable public - subscript(path:Mongo.KeyPath) -> (operator:Mongo.UpdateBitwiseOperator, int32:Int32)? - { - get - { - nil - } - set(value) - { - if case let (name, operand)? = value - { - { - $0[name] = operand - } (&self.bson[with: path.stem][ - as: BSON.DocumentEncoder.self]) - } - } - } - @inlinable public - subscript(path:Mongo.KeyPath) -> (operator:Mongo.UpdateBitwiseOperator, int64:Int64)? - { - get - { - nil - } - set(value) - { - if case let (name, operand)? = value - { - { - $0[name] = operand - } (&self.bson[with: path.stem][ - as: BSON.DocumentEncoder.self]) - } - } - } -} -extension Mongo.UpdateFields -{ - @inlinable public - subscript(path:Mongo.KeyPath) -> BSON.Millisecond.Type? - { - get - { - nil - } - set(value) - { - { - $0["$type"] = "date" - } (&self.bson[with: path.stem][as: BSON.DocumentEncoder.self]) - } - } -} -extension Mongo.UpdateFields -{ - @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.UpdatePosition? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: path.stem]) - } - } -} -extension Mongo.UpdateFields -{ - @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.PredicateOperator? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: path.stem]) - } - } - @inlinable public - subscript(path:Mongo.KeyPath) -> Encodable? where Encodable:BSONEncodable - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: path.stem]) - } - } -} -extension Mongo.UpdateFields -{ - @inlinable public - subscript(path:Mongo.KeyPath) -> Encodable? where Encodable:BSONEncodable - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: path.stem]) - } - } -} -extension Mongo.UpdateFields -{ - @inlinable public - subscript(path:Mongo.KeyPath) -> Mongo.KeyPath? - { - get - { - nil - } - set(value) - { - value?.stem.encode(to: &self.bson[with: path.stem]) - } - } -} -extension Mongo.UpdateFields -{ - @inlinable public - subscript(path:Mongo.KeyPath) -> Void? - { - get - { - nil - } - set(value) - { - (nil as Never?).encode(to: &self.bson[with: path.stem]) - } - } + public + typealias Encoder = Mongo.UpdateFieldsEncoder } diff --git a/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFieldsEncoder.swift b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFieldsEncoder.swift new file mode 100644 index 00000000..1449442c --- /dev/null +++ b/Sources/MongoBuiltins/Documents/Update/Mongo.UpdateFieldsEncoder.swift @@ -0,0 +1,225 @@ +import BSON +import MongoABI + +extension Mongo +{ + @frozen public + struct UpdateFieldsEncoder:Sendable + { + @usableFromInline + var bson:BSON.DocumentEncoder + + @inlinable internal + init(bson:BSON.DocumentEncoder) + { + self.bson = bson + } + } +} +extension Mongo.UpdateFieldsEncoder: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.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Int? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: path.stem]) + } + } + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Double? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: path.stem]) + } + } +} +extension Mongo.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath, yield:(inout Mongo.ExpressionEncoder) -> ()) -> Void + { + 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 +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> (operator:Mongo.UpdateBitwiseOperator, int32:Int32)? + { + get + { + nil + } + set(value) + { + if case let (name, operand)? = value + { + { + $0[name] = operand + } (&self.bson[with: path.stem][ + as: BSON.DocumentEncoder.self]) + } + } + } + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> (operator:Mongo.UpdateBitwiseOperator, int64:Int64)? + { + get + { + nil + } + set(value) + { + if case let (name, operand)? = value + { + { + $0[name] = operand + } (&self.bson[with: path.stem][ + as: BSON.DocumentEncoder.self]) + } + } + } +} +extension Mongo.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> BSON.Millisecond.Type? + { + get + { + nil + } + set(value) + { + { + $0["$type"] = "date" + } (&self.bson[with: path.stem][as: BSON.DocumentEncoder.self]) + } + } +} +extension Mongo.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Mongo.UpdatePosition? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: path.stem]) + } + } +} +extension Mongo.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Mongo.PredicateOperator? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: path.stem]) + } + } + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: path.stem]) + } + } +} +extension Mongo.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: path.stem]) + } + } +} +extension Mongo.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Mongo.AnyKeyPath? + { + get + { + nil + } + set(value) + { + value?.stem.encode(to: &self.bson[with: path.stem]) + } + } +} +extension Mongo.UpdateFieldsEncoder +{ + @inlinable public + subscript(path:Mongo.AnyKeyPath) -> Void? + { + get + { + nil + } + set(value) + { + (nil as Never?).encode(to: &self.bson[with: path.stem]) + } + } +} diff --git a/Sources/MongoBuiltins/Expressions/BSON.ListEncoder (ext).swift b/Sources/MongoBuiltins/Expressions/BSON.ListEncoder (ext).swift index c408634c..8c902a64 100644 --- a/Sources/MongoBuiltins/Expressions/BSON.ListEncoder (ext).swift +++ b/Sources/MongoBuiltins/Expressions/BSON.ListEncoder (ext).swift @@ -3,8 +3,8 @@ import BSON extension BSON.ListEncoder { @inlinable public mutating - func expr(with encode:(inout Mongo.Expression) -> ()) + func expr(with encode:(inout Mongo.ExpressionEncoder) -> ()) { - self.append(Mongo.Expression.expr(with: encode)) + self.append { encode(&$0[as: Mongo.ExpressionEncoder.self]) } } } diff --git a/Sources/MongoBuiltins/Expressions/Mongo.Expression.swift b/Sources/MongoBuiltins/Expressions/Mongo.Expression.swift index e1563385..3fb0764f 100644 --- a/Sources/MongoBuiltins/Expressions/Mongo.Expression.swift +++ b/Sources/MongoBuiltins/Expressions/Mongo.Expression.swift @@ -19,536 +19,3 @@ extension Mongo } } } -extension Mongo.Expression -{ - @inlinable public - subscript(key:Unary) -> Encodable? - where Encodable:BSONEncodable - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - - /// Creates a `$not` or `$isArray` expression. This subscript already - /// brackets the expression when passing it in an argument tuple; - /// doing so manually will create an expression that always evaluates - /// to false for `$not` (because an array evaluates to true), - /// or true for `$isArray` (because an array is an array). - @inlinable public - subscript(key:UnaryParenthesized) -> Encodable? - where Encodable:BSONEncodable - { - get - { - nil - } - set(value) - { - if let value:Encodable - { - { - $0.append(value) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Binary) -> (_:First?, _:Second?) - where First:BSONEncodable, - Second:BSONEncodable - { - get - { - (of: nil, at: nil) - } - set(value) - { - if case (let first?, let second?) = value - { - { - $0.append(first) - $0.append(second) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Cond) -> (if:Predicate?, then:Then?, else:Else?) - where Predicate:BSONEncodable, - Then:BSONEncodable, - Else:BSONEncodable - { - get - { - (nil, nil, nil) - } - set(value) - { - if case (if: let predicate?, then: let first?, else: let second?) = value - { - { - $0.append(predicate) - $0.append(first) - $0.append(second) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Division) -> (_:Dividend?, by:Divisor?) - where Dividend:BSONEncodable, - Divisor:BSONEncodable - { - get - { - (nil, by: nil) - } - set(value) - { - if case (let dividend?, by: let divisor?) = value - { - { - $0.append(dividend) - $0.append(divisor) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Element) -> (of:Array?, at:Index?) - where Array:BSONEncodable, - Index:BSONEncodable - { - get - { - (of: nil, at: nil) - } - set(value) - { - if case (of: let array?, at: let index?) = value - { - { - $0.append(array) - $0.append(index) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:In) -> (_:Encodable?, in:Array?) - where Encodable:BSONEncodable, - Array:BSONEncodable - { - get - { - (nil, in: nil) - } - set(value) - { - if case (let element?, in: let array?) = value - { - { - $0.append(element) - $0.append(array) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Log) -> (base:Base?, of:Exponential?) - where Base:BSONEncodable, - Exponential:BSONEncodable - { - get - { - (base: nil, of: nil) - } - set(value) - { - if case (base: let base?, of: let exponential?) = value - { - { - $0.append(base) - $0.append(exponential) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Pow) -> (base:Base?, to:Exponent?) - where Base:BSONEncodable, - Exponent:BSONEncodable - { - get - { - (base: nil, to: nil) - } - set(value) - { - if case (base: let base?, to: let exponent?) = value - { - { - $0.append(base) - $0.append(exponent) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Quantization) -> Fraction? - where Fraction:BSONEncodable - { - get - { - nil - } - set(value) - { - self[key] = (value, nil as Int32?) - } - } - @inlinable public - subscript(key:Quantization) -> (_:Fraction?, places:Places?) - where Fraction:BSONEncodable, - Places:BSONEncodable - { - get - { - (nil, places: nil) - } - set(value) - { - if case (let fraction?, let places) = value - { - { - $0.append(fraction) - $0.push(places) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Range) -> (from:Start?, to:End?, by:Step?) - where Start:BSONEncodable, - End:BSONEncodable, - Step:BSONEncodable - { - get - { - (from: nil, to: nil, by: nil) - } - set(value) - { - if case (from: let start?, to: let end?, by: let step) = value - { - { - $0.append(start) - $0.append(end) - $0.push(step) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - @inlinable public - subscript(key:Range) -> (from:Start?, to:End?) - where Start:BSONEncodable, - End:BSONEncodable - { - get - { - (from: nil, to: nil) - } - set(value) - { - self[key] = (from: value.from, to: value.to, by: nil as Never?) - } - } - - @inlinable public - subscript(key:Slice) -> (_:Array?, at:Index?, distance:Distance?) - where Array:BSONEncodable, - Index:BSONEncodable, - Distance:BSONEncodable - { - get - { - (nil, at: nil, distance: nil) - } - set(value) - { - if case (let array?, at: let index, distance: let distance?) = value - { - { - $0.append(array) - $0.push(index) - $0.append(distance) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - @inlinable public - subscript(key:Slice) -> (_:Array?, distance:Distance?) - where Array:BSONEncodable, - Distance:BSONEncodable - { - get - { - (nil, distance: nil) - } - set(value) - { - self[key] = (value.0, at: nil as Never?, distance: value.distance) - } - } - - @inlinable public - subscript(key:Subtract) -> (_:Minuend?, minus:Difference?) - where Minuend:BSONEncodable, - Difference:BSONEncodable - { - get - { - (nil, minus: nil) - } - set(value) - { - if case (let minuend?, minus: let difference?) = value - { - { - $0.append(minuend) - $0.append(difference) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Superlative) -> (_:Count?, of:Array?) - where Count:BSONEncodable, - Array:BSONEncodable - { - get - { - (nil, of: nil) - } - set(value) - { - if case (let count?, of: let array?) = value - { - { - $0.append(count) - $0.append(array) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - - @inlinable public - subscript(key:Variadic) -> Encodable? - where Encodable:BSONEncodable - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Variadic) -> (T0?, T1?) - where T0:BSONEncodable, - T1:BSONEncodable - { - get - { - (nil, nil) - } - set(value) - { - { - $0.push(value.0) - $0.push(value.1) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - @inlinable public - subscript(key:Variadic) -> (T0?, T1?, T2?) - where T0:BSONEncodable, - T1:BSONEncodable, - T2:BSONEncodable - { - get - { - (nil, nil, nil) - } - set(value) - { - { - $0.push(value.0) - $0.push(value.1) - $0.push(value.2) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - @inlinable public - subscript(key:Variadic) -> (T0?, T1?, T2?, T3?) - where T0:BSONEncodable, - T1:BSONEncodable, - T2:BSONEncodable, - T3:BSONEncodable - { - get - { - (nil, nil, nil, nil) - } - set(value) - { - { - $0.push(value.0) - $0.push(value.1) - $0.push(value.2) - $0.push(value.3) - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } -} - -extension Mongo.Expression -{ - @inlinable public - subscript(key:Filter) -> Mongo.FilterDocument? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Map) -> Mongo.MapDocument? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Reduce) -> Mongo.ReduceDocument? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:SortArray) -> Mongo.SortArrayDocument? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Switch) -> Mongo.SwitchDocument? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } - @inlinable public - subscript(key:Zip) -> Mongo.ZipDocument? - { - get - { - nil - } - set(value) - { - value?.encode(to: &self.bson[with: key]) - } - } -} - -extension Mongo.Expression -{ - @inlinable public - subscript( - key:Index) -> (in:Sequence?, of:Element?, from:Start?, to:End?) - where Sequence:BSONEncodable, - Element:BSONEncodable, - Start:BSONEncodable, - End:BSONEncodable - { - get - { - (in: nil, of: nil, from: nil, to: nil) - } - set(value) - { - if case (in: let sequence?, of: let element?, let start, let end) = value - { - { - $0.append(sequence) - $0.append(element) - - if let start:Start - { - $0.append(start) - $0.push(end) - } - } (&self.bson[with: key][as: BSON.ListEncoder.self]) - } - } - } - @inlinable public - subscript(key:Index) -> (in:Sequence?, of:Element?) - where Sequence:BSONEncodable, - Element:BSONEncodable - { - get - { - (in: nil, of: nil) - } - set(value) - { - self[key] = (value.0, value.1, nil as Never?, nil as Never?) - } - } -} diff --git a/Sources/MongoBuiltins/Expressions/Mongo.ExpressionEncoder.swift b/Sources/MongoBuiltins/Expressions/Mongo.ExpressionEncoder.swift new file mode 100644 index 00000000..2e331f2c --- /dev/null +++ b/Sources/MongoBuiltins/Expressions/Mongo.ExpressionEncoder.swift @@ -0,0 +1,568 @@ +import BSON + +extension Mongo +{ + @frozen public + struct ExpressionEncoder:Sendable + { + @usableFromInline + var bson:BSON.DocumentEncoder + + @inlinable internal + init(bson:BSON.DocumentEncoder) + { + self.bson = bson + } + } +} +extension Mongo.ExpressionEncoder: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.ExpressionEncoder +{ + @inlinable public + subscript(key:Mongo.Expression.Unary) -> Encodable? + where Encodable:BSONEncodable + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + + /// Creates a `$not` or `$isArray` expression. This subscript already + /// brackets the expression when passing it in an argument tuple; + /// doing so manually will create an expression that always evaluates + /// to false for `$not` (because an array evaluates to true), + /// or true for `$isArray` (because an array is an array). + @inlinable public + subscript(key:Mongo.Expression.UnaryParenthesized) -> Encodable? + where Encodable:BSONEncodable + { + get + { + nil + } + set(value) + { + if let value:Encodable + { + { + $0.append(value) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Binary) -> (_:First?, _:Second?) + where First:BSONEncodable, + Second:BSONEncodable + { + get + { + (of: nil, at: nil) + } + set(value) + { + if case (let first?, let second?) = value + { + { + $0.append(first) + $0.append(second) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript( + key:Mongo.Expression.Cond) -> (if:Predicate?, then:Then?, else:Else?) + where Predicate:BSONEncodable, + Then:BSONEncodable, + Else:BSONEncodable + { + get + { + (nil, nil, nil) + } + set(value) + { + if case (if: let predicate?, then: let first?, else: let second?) = value + { + { + $0.append(predicate) + $0.append(first) + $0.append(second) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Division) -> (_:Dividend?, by:Divisor?) + where Dividend:BSONEncodable, + Divisor:BSONEncodable + { + get + { + (nil, by: nil) + } + set(value) + { + if case (let dividend?, by: let divisor?) = value + { + { + $0.append(dividend) + $0.append(divisor) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Element) -> (of:Array?, at:Index?) + where Array:BSONEncodable, + Index:BSONEncodable + { + get + { + (of: nil, at: nil) + } + set(value) + { + if case (of: let array?, at: let index?) = value + { + { + $0.append(array) + $0.append(index) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.In) -> (_:Encodable?, in:Array?) + where Encodable:BSONEncodable, + Array:BSONEncodable + { + get + { + (nil, in: nil) + } + set(value) + { + if case (let element?, in: let array?) = value + { + { + $0.append(element) + $0.append(array) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Log) -> (base:Base?, of:Exponential?) + where Base:BSONEncodable, + Exponential:BSONEncodable + { + get + { + (base: nil, of: nil) + } + set(value) + { + if case (base: let base?, of: let exponential?) = value + { + { + $0.append(base) + $0.append(exponential) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Pow) -> (base:Base?, to:Exponent?) + where Base:BSONEncodable, + Exponent:BSONEncodable + { + get + { + (base: nil, to: nil) + } + set(value) + { + if case (base: let base?, to: let exponent?) = value + { + { + $0.append(base) + $0.append(exponent) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Quantization) -> Fraction? + where Fraction:BSONEncodable + { + get + { + nil + } + set(value) + { + self[key] = (value, nil as Int32?) + } + } + @inlinable public + subscript( + key:Mongo.Expression.Quantization) -> (_:Fraction?, places:Places?) + where Fraction:BSONEncodable, + Places:BSONEncodable + { + get + { + (nil, places: nil) + } + set(value) + { + if case (let fraction?, let places) = value + { + { + $0.append(fraction) + $0.push(places) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Range) -> (from:Start?, to:End?, by:Step?) + where Start:BSONEncodable, + End:BSONEncodable, + Step:BSONEncodable + { + get + { + (from: nil, to: nil, by: nil) + } + set(value) + { + if case (from: let start?, to: let end?, by: let step) = value + { + { + $0.append(start) + $0.append(end) + $0.push(step) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + @inlinable public + subscript(key:Mongo.Expression.Range) -> (from:Start?, to:End?) + where Start:BSONEncodable, + End:BSONEncodable + { + get + { + (from: nil, to: nil) + } + set(value) + { + self[key] = (from: value.from, to: value.to, by: nil as Never?) + } + } + + @inlinable public + subscript( + key:Mongo.Expression.Slice) -> (_:Array?, at:Index?, distance:Distance?) + where Array:BSONEncodable, + Index:BSONEncodable, + Distance:BSONEncodable + { + get + { + (nil, at: nil, distance: nil) + } + set(value) + { + if case (let array?, at: let index, distance: let distance?) = value + { + { + $0.append(array) + $0.push(index) + $0.append(distance) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + @inlinable public + subscript(key:Mongo.Expression.Slice) -> (_:Array?, distance:Distance?) + where Array:BSONEncodable, + Distance:BSONEncodable + { + get + { + (nil, distance: nil) + } + set(value) + { + self[key] = (value.0, at: nil as Never?, distance: value.distance) + } + } + + @inlinable public + subscript( + key:Mongo.Expression.Subtract) -> (_:Minuend?, minus:Difference?) + where Minuend:BSONEncodable, + Difference:BSONEncodable + { + get + { + (nil, minus: nil) + } + set(value) + { + if case (let minuend?, minus: let difference?) = value + { + { + $0.append(minuend) + $0.append(difference) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Superlative) -> (_:Count?, of:Array?) + where Count:BSONEncodable, + Array:BSONEncodable + { + get + { + (nil, of: nil) + } + set(value) + { + if case (let count?, of: let array?) = value + { + { + $0.append(count) + $0.append(array) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + + @inlinable public + subscript(key:Mongo.Expression.Variadic) -> Encodable? + where Encodable:BSONEncodable + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Mongo.Expression.Variadic) -> (T0?, T1?) + where T0:BSONEncodable, + T1:BSONEncodable + { + get + { + (nil, nil) + } + set(value) + { + { + $0.push(value.0) + $0.push(value.1) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + @inlinable public + subscript(key:Mongo.Expression.Variadic) -> (T0?, T1?, T2?) + where T0:BSONEncodable, + T1:BSONEncodable, + T2:BSONEncodable + { + get + { + (nil, nil, nil) + } + set(value) + { + { + $0.push(value.0) + $0.push(value.1) + $0.push(value.2) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + @inlinable public + subscript(key:Mongo.Expression.Variadic) -> (T0?, T1?, T2?, T3?) + where T0:BSONEncodable, + T1:BSONEncodable, + T2:BSONEncodable, + T3:BSONEncodable + { + get + { + (nil, nil, nil, nil) + } + set(value) + { + { + $0.push(value.0) + $0.push(value.1) + $0.push(value.2) + $0.push(value.3) + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } +} + +extension Mongo.ExpressionEncoder +{ + @inlinable public + subscript(key:Mongo.Expression.Filter) -> Mongo.FilterDocument? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Mongo.Expression.Map) -> Mongo.MapDocument? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Mongo.Expression.Reduce) -> Mongo.ReduceDocument? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Mongo.Expression.SortArray) -> Mongo.SortArrayDocument? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Mongo.Expression.Switch) -> Mongo.SwitchDocument? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } + @inlinable public + subscript(key:Mongo.Expression.Zip) -> Mongo.ZipDocument? + { + get + { + nil + } + set(value) + { + value?.encode(to: &self.bson[with: key]) + } + } +} + +extension Mongo.ExpressionEncoder +{ + @inlinable public + subscript( + key:Mongo.Expression.Index) -> (in:Sequence?, of:Element?, from:Start?, to:End?) + where Sequence:BSONEncodable, + Element:BSONEncodable, + Start:BSONEncodable, + End:BSONEncodable + { + get + { + (in: nil, of: nil, from: nil, to: nil) + } + set(value) + { + if case (in: let sequence?, of: let element?, let start, let end) = value + { + { + $0.append(sequence) + $0.append(element) + + if let start:Start + { + $0.append(start) + $0.push(end) + } + } (&self.bson[with: key][as: BSON.ListEncoder.self]) + } + } + } + @inlinable public + subscript(key:Mongo.Expression.Index) -> (in:Sequence?, of:Element?) + where Sequence:BSONEncodable, + Element:BSONEncodable + { + get + { + (in: nil, of: nil) + } + set(value) + { + self[key] = (value.0, value.1, nil as Never?, nil as Never?) + } + } +} diff --git a/Sources/MongoBuiltins/Expressions/Optional (ext).swift b/Sources/MongoBuiltins/Expressions/Optional (ext).swift index 3e4c2ec0..ccc99bdb 100644 --- a/Sources/MongoBuiltins/Expressions/Optional (ext).swift +++ b/Sources/MongoBuiltins/Expressions/Optional (ext).swift @@ -3,7 +3,7 @@ extension Mongo.Expression? { @inlinable public static - func expr(with populate:(inout Mongo.Expression) throws -> ()) rethrows -> Self + func expr(with populate:(inout Mongo.ExpressionEncoder) throws -> ()) rethrows -> Self { .some(try .expr(with: populate)) } diff --git a/Sources/MongoBuiltins/Pipelines/Mongo.PipelineEncoder.swift b/Sources/MongoBuiltins/Pipelines/Mongo.PipelineEncoder.swift index 46034779..1e2a3b99 100644 --- a/Sources/MongoBuiltins/Pipelines/Mongo.PipelineEncoder.swift +++ b/Sources/MongoBuiltins/Pipelines/Mongo.PipelineEncoder.swift @@ -33,6 +33,7 @@ extension Mongo.PipelineEncoder:BSON.Encoder extension Mongo.PipelineEncoder { /// This is a legacy source compatibility aid that does nothing and will be deprecated soon. + @available(*, deprecated, message: "use subscripts instead") @inlinable public mutating func stage(_ populate:(inout Self) throws -> ()) rethrows { @@ -41,8 +42,16 @@ extension Mongo.PipelineEncoder } extension Mongo.PipelineEncoder { + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Out) -> Mongo.Collection? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Out) -> Mongo.Collection? { get { nil } set (value) @@ -60,8 +69,18 @@ extension Mongo.PipelineEncoder } } } + + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Out) -> Mongo.Namespaced? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Out) -> Mongo.Namespaced? { get { nil } set (value) @@ -80,8 +99,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Merge) -> Mongo.MergeDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Merge) -> Mongo.MergeDocument? { get { nil } set (value) @@ -102,8 +130,16 @@ extension Mongo.PipelineEncoder } extension Mongo.PipelineEncoder { + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Bucket) -> Mongo.BucketDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Bucket) -> Mongo.BucketDocument? { get { nil } set (value) @@ -122,8 +158,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.BucketAuto) -> Mongo.BucketAutoDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.BucketAuto) -> Mongo.BucketAutoDocument? { get { nil } set (value) @@ -142,14 +187,23 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") + @inlinable public + subscript(key:Mongo.Pipeline.Count) -> Mongo.AnyKeyPath? + { + get { nil } + set (value) { self[stage: key] = value } + } + @inlinable public - subscript(key:Mongo.Pipeline.Count) -> Mongo.KeyPath? + subscript(stage key:Mongo.Pipeline.Count) -> Mongo.AnyKeyPath? { get { nil } set (value) { guard - let value:Mongo.KeyPath + let value:Mongo.AnyKeyPath else { return @@ -164,13 +218,22 @@ extension Mongo.PipelineEncoder @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.ChangeStream) -> Never? + subscript(stage key:Mongo.Pipeline.ChangeStream) -> Never? { nil } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.CollectionStats) -> Mongo.CollectionStatsDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.CollectionStats) -> Mongo.CollectionStatsDocument? { get { nil } set (value) @@ -189,8 +252,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.CurrentOperation) -> Mongo.CurrentOperationDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.CurrentOperation) -> Mongo.CurrentOperationDocument? { get { nil } set (value) @@ -211,13 +283,22 @@ extension Mongo.PipelineEncoder @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.Densify) -> Never? + subscript(stage key:Mongo.Pipeline.Densify) -> Never? { nil } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Documents) -> Array? where Array:BSONEncodable + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Documents) -> Array? where Array:BSONEncodable { get { nil } set (value) @@ -236,8 +317,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Facet) -> Mongo.FacetDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Facet) -> Mongo.FacetDocument? { get { nil } set (value) @@ -258,27 +348,36 @@ extension Mongo.PipelineEncoder @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.Fill) -> Never? + subscript(stage key:Mongo.Pipeline.Fill) -> Never? { nil } @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.GeoNear) -> Never? + subscript(stage key:Mongo.Pipeline.GeoNear) -> Never? { nil } @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.GraphLookup) -> Never? + subscript(stage key:Mongo.Pipeline.GraphLookup) -> Never? { nil } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Group) -> Mongo.GroupDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Group) -> Mongo.GroupDocument? { get { nil } set (value) @@ -297,8 +396,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.IndexStats) -> [String: Never]? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.IndexStats) -> [String: Never]? { get { nil } set (value) @@ -317,8 +425,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Limit) -> Int? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Limit) -> Int? { get { nil } set (value) @@ -339,19 +456,28 @@ extension Mongo.PipelineEncoder @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.ListLocalSessions) -> Never? + subscript(stage key:Mongo.Pipeline.ListLocalSessions) -> Never? { nil } @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.ListSessions) -> Never? + subscript(stage key:Mongo.Pipeline.ListSessions) -> Never? { nil } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Lookup) -> Mongo.LookupDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Lookup) -> Mongo.LookupDocument? { get { nil } set (value) @@ -370,8 +496,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Match) -> Mongo.PredicateDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Match) -> Mongo.PredicateDocument? { get { nil } set (value) @@ -390,8 +525,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.PlanCacheStats) -> [String: Never]? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.PlanCacheStats) -> [String: Never]? { get { nil } set (value) @@ -410,8 +554,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Project) -> Mongo.ProjectionDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Project) -> Mongo.ProjectionDocument? { get { nil } set (value) @@ -430,9 +583,19 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Redact) -> RedactMode? where RedactMode:BSONEncodable + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Redact) -> RedactMode? + where RedactMode:BSONEncodable { get { nil } set (value) @@ -451,9 +614,19 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.ReplaceWith) -> Document? where Document:BSONEncodable + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.ReplaceWith) -> Document? + where Document:BSONEncodable { get { nil } set (value) @@ -471,8 +644,17 @@ extension Mongo.PipelineEncoder } } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.ReplaceWith) -> Mongo.SetDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.ReplaceWith) -> Mongo.SetDocument? { get { nil } set (value) @@ -491,8 +673,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Sample) -> Mongo.SampleDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Sample) -> Mongo.SampleDocument? { get { nil } set (value) @@ -511,8 +702,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Set) -> Mongo.SetDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Set) -> Mongo.SetDocument? { get { nil } set (value) @@ -533,13 +733,22 @@ extension Mongo.PipelineEncoder @available(*, unavailable, message: "unimplemented") @inlinable public - subscript(key:Mongo.Pipeline.SetWindowFields) -> Never? + subscript(stage key:Mongo.Pipeline.SetWindowFields) -> Never? { nil } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.ShardedDataDistribution) -> [String: Never]? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.ShardedDataDistribution) -> [String: Never]? { get { nil } set (value) @@ -558,8 +767,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Skip) -> Int? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Skip) -> Int? { get { nil } set (value) @@ -578,8 +796,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Sort) -> Mongo.SortDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Sort) -> Mongo.SortDocument? { get { nil } set (value) @@ -598,9 +825,19 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.SortByCount) -> GroupKey? where GroupKey:BSONEncodable + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.SortByCount) -> GroupKey? + where GroupKey:BSONEncodable { get { nil } set (value) @@ -619,8 +856,17 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.UnionWith) -> Mongo.Collection? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.UnionWith) -> Mongo.Collection? { get { nil } set (value) @@ -638,8 +884,17 @@ extension Mongo.PipelineEncoder } } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.UnionWith) -> Mongo.UnionWithDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.UnionWith) -> Mongo.UnionWithDocument? { get { nil } set (value) @@ -658,14 +913,23 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") + @inlinable public + subscript(key:Mongo.Pipeline.Unset) -> Mongo.AnyKeyPath? + { + get { nil } + set (value) { self[stage: key] = value } + } + @inlinable public - subscript(key:Mongo.Pipeline.Unset) -> Mongo.KeyPath? + subscript(stage key:Mongo.Pipeline.Unset) -> Mongo.AnyKeyPath? { get { nil } set (value) { guard - let value:Mongo.KeyPath + let value:Mongo.AnyKeyPath else { return @@ -677,9 +941,17 @@ extension Mongo.PipelineEncoder } } } + + @available(*, deprecated, renamed: "subscript(stage:)") + @inlinable public + subscript(key:Mongo.Pipeline.Unset) -> [Mongo.AnyKeyPath] + { + get { [ ] } + set (value) { self[stage: key] = value } + } /// Does nothing if the assigned array is empty. @inlinable public - subscript(key:Mongo.Pipeline.Unset) -> [Mongo.KeyPath] + subscript(stage key:Mongo.Pipeline.Unset) -> [Mongo.AnyKeyPath] { get { [ ] } set (value) @@ -693,7 +965,7 @@ extension Mongo.PipelineEncoder { $0[.unset] { - for path:Mongo.KeyPath in value + for path:Mongo.AnyKeyPath in value { $0.append(path.stem) } @@ -702,14 +974,23 @@ extension Mongo.PipelineEncoder } } + + @available(*, deprecated, renamed: "subscript(stage:)") + @inlinable public + subscript(key:Mongo.Pipeline.Unwind) -> Mongo.AnyKeyPath? + { + get { nil } + set (value) { self[stage: key] = value } + } + @inlinable public - subscript(key:Mongo.Pipeline.Unwind) -> Mongo.KeyPath? + subscript(stage key:Mongo.Pipeline.Unwind) -> Mongo.AnyKeyPath? { get { nil } set (value) { guard - let value:Mongo.KeyPath + let value:Mongo.AnyKeyPath else { return @@ -722,8 +1003,17 @@ extension Mongo.PipelineEncoder } } } + + @available(*, deprecated, renamed: "subscript(stage:)") @inlinable public subscript(key:Mongo.Pipeline.Unwind) -> Mongo.UnwindDocument? + { + get { nil } + set (value) { self[stage: key] = value } + } + + @inlinable public + subscript(stage key:Mongo.Pipeline.Unwind) -> Mongo.UnwindDocument? { get { nil } set (value) diff --git a/Sources/MongoDB/Mongo.Session (ext).swift b/Sources/MongoDB/Mongo.Session (ext).swift index 17ebdd39..e24eeca5 100644 --- a/Sources/MongoDB/Mongo.Session (ext).swift +++ b/Sources/MongoDB/Mongo.Session (ext).swift @@ -8,14 +8,14 @@ extension Mongo.Session collection.name, pipeline: .init { - $0[.collectionStats] = .init + $0[stage: .collectionStats] = .init { $0[.storageStats] = [:] } // A typical collection stats output document contains a huge amount of // data, most of which is redundant. - $0[.project] = .init + $0[stage: .project] = .init { for key:Mongo.CollectionStats.Storage.CodingKey in Mongo.CollectionStats.Storage.CodingKey.allCases diff --git a/Sources/MongoDBTests/Aggregate/Aggregate.swift b/Sources/MongoDBTests/Aggregate/Aggregate.swift index 6eef0abf..5b774abd 100644 --- a/Sources/MongoDBTests/Aggregate/Aggregate.swift +++ b/Sources/MongoDBTests/Aggregate/Aggregate.swift @@ -61,9 +61,9 @@ struct Aggregate:MongoTestBattery where Configuration:MongoTestCo readConcern: .majority, pipeline: .init { - $0[.project] = .init { $0[Article[.tags]] = 1 } - $0[.unwind] = Article[.tags] - $0[.group] = .init + $0[stage: .project] = .init { $0[Article[.tags]] = 1 } + $0[stage: .unwind] = Article[.tags] + $0[stage: .group] = .init { $0[.id] = Article[.tags] @@ -92,22 +92,16 @@ struct Aggregate:MongoTestBattery where Configuration:MongoTestCo readConcern: .majority, pipeline: .init { - $0.stage + $0[stage: .project] = .init { - $0[.project] = .init - { - $0[Article[.author]] = 1 - $0[Article[.views]] = 1 - } + $0[Article[.author]] = 1 + $0[Article[.views]] = 1 } - $0.stage + $0[stage: .group] = .init { - $0[.group] = .init - { - $0[.id] = Article[.author] + $0[.id] = Article[.author] - $0[Article[.views]] = .init { $0[.sum] = Article[.views] } - } + $0[Article[.views]] = .init { $0[.sum] = Article[.views] } } }, stride: 10), diff --git a/Sources/MongoDBTests/FindAndModify/FindAndModify.swift b/Sources/MongoDBTests/FindAndModify/FindAndModify.swift index b1cc289d..9e791078 100644 --- a/Sources/MongoDBTests/FindAndModify/FindAndModify.swift +++ b/Sources/MongoDBTests/FindAndModify/FindAndModify.swift @@ -117,7 +117,7 @@ struct FindAndModify:MongoTestBattery where Configuration:MongoTe } $0[.update] = .init { - $0[.set] = .init + $0[.set] { $0["party"] = "Independent" } diff --git a/Sources/MongoDBTests/Main.swift b/Sources/MongoDBTests/Main.swift index 577b200a..51f73bdb 100644 --- a/Sources/MongoDBTests/Main.swift +++ b/Sources/MongoDBTests/Main.swift @@ -19,6 +19,7 @@ enum Main:TestMain Indexes .self, Insert .self, Update .self, + UpdateNested .self, Transactions .self, CausalConsistency .self, @@ -37,5 +38,6 @@ enum Main:TestMain Indexes .self, Insert .self, Update .self, + UpdateNested .self, ] } diff --git a/Sources/MongoDBTests/Update/Update.Member.swift b/Sources/MongoDBTests/Update/Update.Member.swift index b568e3c6..7e55e994 100644 --- a/Sources/MongoDBTests/Update/Update.Member.swift +++ b/Sources/MongoDBTests/Update/Update.Member.swift @@ -8,7 +8,7 @@ extension Update let member:String let status:String let points:Int - let comments:[String] + let comments:[String?] let misc1:String? let misc2:String? @@ -16,7 +16,7 @@ extension Update member:String, status:String, points:Int, - comments:[String] = [], + comments:[String?] = [], misc1:String? = nil, misc2:String? = nil) { diff --git a/Sources/MongoDBTests/Update/Update.swift b/Sources/MongoDBTests/Update/Update.swift index 64d800c6..6e3156c2 100644 --- a/Sources/MongoDBTests/Update/Update.swift +++ b/Sources/MongoDBTests/Update/Update.swift @@ -12,7 +12,7 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi // https://www.mongodb.com/docs/manual/reference/command/update/#examples let collection:Mongo.Collection = "members" - let states:([Member], [Member], [Member], [Member], [Member]) + let states:([Member], [Member], [Member], [Member], [Member], [Member]) states.0 = [ @@ -47,6 +47,22 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi misc2: "Some random comment"), ] states.2 = + [ + .init(id: 1, + member: "abc123", + status: "A", + points: 1, + misc1: "note to self: confirm status", + misc2: "Need to activate"), + + .init(id: 2, + member: "xyz123", + status: "A", + points: 59, + misc1: "reminder: ping me at 100pts", + misc2: nil), + ] + states.3 = [ .init(id: 1, member: "abc123", @@ -60,9 +76,9 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi status: "A", points: 60, misc1: "reminder: ping me at 100pts", - misc2: "Some random comment"), + misc2: nil), ] - states.3 = + states.4 = [ .init(id: 1, member: "abc123", @@ -74,9 +90,9 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi member: "xyz123", status: "Modified", points: 60, - comments: ["reminder: ping me at 100pts", "Some random comment"]), + comments: ["reminder: ping me at 100pts", nil]), ] - states.4 = + states.5 = [ .init(id: 1, member: "abc123", @@ -88,7 +104,7 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi member: "xyz123", status: "Modified", points: 60, - comments: ["reminder: ping me at 100pts", "Some random comment"]), + comments: ["reminder: ping me at 100pts", nil]), .init(id: 3, member: "upserted", @@ -107,7 +123,7 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi } do { - let tests:TestGroup = tests ! "one" + let tests:TestGroup = tests ! "One" await tests.do { @@ -126,13 +142,13 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi { $0["member"] = "abc123" } - $0[.u] = .init + $0[.u] { - $0[.set] = .init + $0[.set] { $0["status"] = "A" } - $0[.inc] = .init + $0[.inc] { $0["points"] = 1 } @@ -155,7 +171,45 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi } do { - let tests:TestGroup = tests ! "many" + let tests:TestGroup = tests ! "Replace" + + await tests.do + { + let expected:Mongo.UpdateResponse = .init(selected: 1, modified: 1) + let response:Mongo.UpdateResponse = try await session.run( + command: Mongo.Update.init(collection, + writeConcern: .majority) + { + $0[.ordered] = false + } + updates: + { + $0 + { + $0[.q] = .init + { + $0["_id"] = states.2.last?.id + } + $0[.u] = states.2.last + } + }, + against: database) + + tests.expect(response ==? expected) + } + await tests.do + { + let members:[Member] = try await session.run( + command: Mongo.Find>.init(collection, + limit: 10), + against: database) + + tests.expect(members **? states.2) + } + } + do + { + let tests:TestGroup = tests ! "Many" await tests.do { @@ -171,13 +225,13 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi $0 { $0[.q] = .init() - $0[.u] = .init + $0[.u] { - $0[.set] = .init + $0[.set] { $0["status"] = "A" } - $0[.inc] = .init + $0[.inc] { $0["points"] = 1 } @@ -196,12 +250,12 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi limit: 10), against: database) - tests.expect(members **? states.2) + tests.expect(members **? states.3) } } do { - let tests:TestGroup = tests ! "pipeline" + let tests:TestGroup = tests ! "Pipeline" await tests.do { @@ -217,20 +271,14 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi $0 { $0[.q] = .init() - $0[.u] = .init + $0[.u] { - $0.stage - { - $0[.set] = .init - { - $0["status"] = "Modified" - $0["comments"] = ["$misc1", "$misc2"] - } - } - $0.stage + $0[stage: .set] = .init { - $0[.unset] = ["misc1", "misc2"] + $0["status"] = "Modified" + $0["comments"] = ["$misc1", "$misc2"] } + $0[stage: .unset] = ["misc1", "misc2"] } $0[.multi] = true } @@ -246,12 +294,12 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi limit: 10), against: database) - tests.expect(members **? states.3) + tests.expect(members **? states.4) } } do { - let tests:TestGroup = tests ! "upsert" + let tests:TestGroup = tests ! "Upsert" await tests.do { @@ -272,7 +320,7 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi { $0["_id"] = 3 } - $0[.u] = states.4.last + $0[.u] = states.5.last $0[.upsert] = true } }, @@ -287,7 +335,7 @@ struct Update:MongoTestBattery where Configuration:MongoTestConfi limit: 10), against: database) - tests.expect(members **? states.4) + tests.expect(members **? states.5) } } } diff --git a/Sources/MongoDBTests/Update/UpdateNested.Ape.Food.swift b/Sources/MongoDBTests/Update/UpdateNested.Ape.Food.swift new file mode 100644 index 00000000..aa033eed --- /dev/null +++ b/Sources/MongoDBTests/Update/UpdateNested.Ape.Food.swift @@ -0,0 +1,41 @@ +import BSON + +extension UpdateNested.Ape +{ + struct Food:Equatable, Hashable + { + let expires:BSON.Millisecond? + let type:String + + init(expires:BSON.Millisecond?, type:String) + { + self.expires = expires + self.type = type + } + } +} +extension UpdateNested.Ape.Food +{ + enum CodingKey:String, Sendable + { + case expires + case type + } +} +extension UpdateNested.Ape.Food:BSONDocumentEncodable +{ + func encode(to bson:inout BSON.DocumentEncoder) + { + bson[.expires] = self.expires + bson[.type] = self.type + } +} +extension UpdateNested.Ape.Food:BSONDocumentDecodable +{ + init(bson:BSON.DocumentDecoder) throws + { + self.init( + expires: try bson[.expires]?.decode(), + type: try bson[.type].decode()) + } +} diff --git a/Sources/MongoDBTests/Update/UpdateNested.Ape.swift b/Sources/MongoDBTests/Update/UpdateNested.Ape.swift new file mode 100644 index 00000000..a40ed6a6 --- /dev/null +++ b/Sources/MongoDBTests/Update/UpdateNested.Ape.swift @@ -0,0 +1,46 @@ +import BSON + +extension UpdateNested +{ + struct Ape:Equatable, Hashable + { + let id:Int + let name:String + let food:Food? + + init(id:Int, name:String, food:Food?) + { + self.id = id + self.name = name + self.food = food + } + } +} +extension UpdateNested.Ape +{ + enum CodingKey:String, Sendable + { + case id = "_id" + case name + case food + } +} +extension UpdateNested.Ape:BSONDocumentEncodable +{ + func encode(to bson:inout BSON.DocumentEncoder) + { + bson[.id] = self.id + bson[.name] = self.name + bson[.food] = self.food + } +} +extension UpdateNested.Ape:BSONDocumentDecodable +{ + init(bson:BSON.DocumentDecoder) throws + { + self.init( + id: try bson[.id].decode(), + name: try bson[.name].decode(), + food: try bson[.food]?.decode()) + } +} diff --git a/Sources/MongoDBTests/Update/UpdateNested.swift b/Sources/MongoDBTests/Update/UpdateNested.swift new file mode 100644 index 00000000..0ceb7e61 --- /dev/null +++ b/Sources/MongoDBTests/Update/UpdateNested.swift @@ -0,0 +1,200 @@ +import MongoDB +import MongoTesting + +struct UpdateNested:MongoTestBattery where Configuration:MongoTestConfiguration +{ + static + func run(tests:TestGroup, pool:Mongo.SessionPool, database:Mongo.Database) async throws + { + let session:Mongo.Session = try await .init(from: pool) + + // This test is based on the tutorial from: + // https://www.mongodb.com/docs/manual/reference/command/update/#examples + + let collection:Mongo.Collection = "apes" + let states:([Ape], [Ape], [Ape]) + + states.0 = + [ + .init(id: 1, + name: "Harambe", + food: .init(expires: .init(123), type: "Banana")), + + .init(id: 2, + name: "George", + food: .init(expires: .init(456), type: "Watermelon")), + ] + + states.1 = + [ + .init(id: 1, + name: "Harambe", + food: .init(expires: .init(123), type: "Banana")), + + .init(id: 2, + name: "George", + food: .init(expires: nil, type: "Watermelon")), + ] + + states.2 = + [ + .init(id: 1, + name: "Harambe", + food: .init(expires: nil, type: "Watermelon")), + + .init(id: 2, + name: "George", + food: .init(expires: nil, type: "Watermelon")), + ] + + await tests.do + { + let expected:Mongo.InsertResponse = .init(inserted: 2) + let response:Mongo.InsertResponse = try await session.run( + command: Mongo.Insert.init(collection, encoding: states.0), + against: database) + + tests.expect(response ==? expected) + } + + do + { + let tests:TestGroup = tests ! "SetField" + + await tests.do + { + let expected:Mongo.UpdateResponse = .init(selected: 1, modified: 1) + let response:Mongo.UpdateResponse = try await session.run( + command: Mongo.Update.init(collection, + writeConcern: .majority) + { + $0[.ordered] = false + } + updates: + { + $0 + { + $0[.q] = .init + { + $0["name"] = "George" + } + $0[.u] + { + $0[.set] + { + $0["food"] = Ape.Food.init(expires: nil, + type: "Watermelon") + } + } + } + }, + against: database) + + tests.expect(response ==? expected) + } + await tests.do + { + let apes:[Ape] = try await session.run( + command: Mongo.Find>.init(collection, + limit: 10), + against: database) + + tests.expect(apes **? states.1) + } + } + do + { + let tests:TestGroup = tests ! "SetFieldWithPipeline" + + await tests.do + { + /// This update should have no effect, because aggregation `$set` behaves + /// differently than the update `$set`. + let expected:Mongo.UpdateResponse = .init(selected: 1, modified: 0) + let response:Mongo.UpdateResponse = try await session.run( + command: Mongo.Update.init(collection, + writeConcern: .majority) + { + $0[.ordered] = false + } + updates: + { + $0 + { + $0[.q] = .init + { + $0["name"] = "Harambe" + } + $0[.u] + { + $0[stage: .set] = .init + { + $0["food"] = Ape.Food.init(expires: nil, type: "Banana") + } + } + } + }, + against: database) + + tests.expect(response ==? expected) + } + await tests.do + { + let apes:[Ape] = try await session.run( + command: Mongo.Find>.init(collection, + limit: 10), + against: database) + + tests.expect(apes **? states.1) + } + } + do + { + let tests:TestGroup = tests ! "ReplaceFieldWithPipeline" + + await tests.do + { + let expected:Mongo.UpdateResponse = .init(selected: 1, modified: 1) + let response:Mongo.UpdateResponse = try await session.run( + command: Mongo.Update.init(collection, + writeConcern: .majority) + { + $0[.ordered] = false + } + updates: + { + $0 + { + $0[.q] = .init + { + $0["name"] = "Harambe" + } + $0[.u] + { + $0[stage: .set] = .init + { + $0["food"] = .expr + { + $0[.literal] = Ape.Food.init(expires: nil, + type: "Watermelon") + } + } + } + } + }, + against: database) + + tests.expect(response ==? expected) + } + await tests.do + { + let apes:[Ape] = try await session.run( + command: Mongo.Find>.init(collection, + limit: 10), + against: database) + + tests.expect(apes **? states.2) + } + } + } +} diff --git a/Sources/MongoQL/Commands/Update/Mongo.UpdateEncoder.swift b/Sources/MongoQL/Commands/Update/Mongo.UpdateEncoder.swift index af7c8b9a..45f9b30a 100644 --- a/Sources/MongoQL/Commands/Update/Mongo.UpdateEncoder.swift +++ b/Sources/MongoQL/Commands/Update/Mongo.UpdateEncoder.swift @@ -31,3 +31,33 @@ extension Mongo.UpdateEncoder in: BSON.DocumentFrame.self]) } } +extension Mongo.UpdateEncoder +{ + /// A shorthand for ``update(_:upsert:)`` with `upsert` set to false. + @inlinable public mutating + func replace( + _ element:some BSONDocumentEncodable & Identifiable) + { + self.update(element, upsert: false) + } + /// A shorthand for ``update(_:upsert:)`` with `upsert` set to true. + @inlinable public mutating + func upsert( + _ element:some BSONDocumentEncodable & Identifiable) + { + self.update(element, upsert: true) + } + /// Upserts or replaces a document by its ``Identifiable/id``. + @inlinable mutating + func update( + _ element:some BSONDocumentEncodable & Identifiable, + upsert:Bool) + { + self + { + $0[.upsert] = upsert + $0[.q] = .init { $0["_id"] = element.id } + $0[.u] = element + } + } +} diff --git a/Sources/MongoQL/Commands/Update/Mongo.UpdateStatement.swift b/Sources/MongoQL/Commands/Update/Mongo.UpdateStatement.swift index 041521d3..0a8fbb39 100644 --- a/Sources/MongoQL/Commands/Update/Mongo.UpdateStatement.swift +++ b/Sources/MongoQL/Commands/Update/Mongo.UpdateStatement.swift @@ -40,14 +40,19 @@ extension Mongo.UpdateStatement get { nil } set (value) { value?.encode(to: &self.bson[with: key]) } } - +} +extension Mongo.UpdateStatement +{ @inlinable public subscript(key:Q) -> Mongo.PredicateDocument? { get { nil } set (value) { value?.encode(to: &self.bson[with: key]) } } - +} +extension Mongo.UpdateStatement +{ + @available(*, deprecated, message: "Use the functional subscript instead.") @inlinable public subscript(key:U) -> Mongo.UpdateDocument? { @@ -55,27 +60,37 @@ extension Mongo.UpdateStatement set (value) { value?.encode(to: &self.bson[with: key]) } } + @available(*, deprecated, message: "Use the functional subscript instead.") @inlinable public - subscript(key:U, yield:(inout Mongo.PipelineEncoder) -> ()) -> Void + subscript(key:U) -> Mongo.Pipeline? + { + get { nil } + set (value) { value?.encode(to: &self.bson[with: key]) } + } + + @inlinable public + subscript(key:U, yield:(inout Mongo.UpdateDocumentEncoder) -> ()) -> Void { mutating - get { yield(&self.bson[with: key][as: Mongo.PipelineEncoder.self]) } + get { yield(&self.bson[with: key][as: Mongo.UpdateDocumentEncoder.self]) } } + @inlinable public - subscript(key:U) -> Mongo.Pipeline? + subscript(key:U, yield:(inout Mongo.PipelineEncoder) -> ()) -> Void { - get { nil } - set (value) { value?.encode(to: &self.bson[with: key]) } + mutating + get { yield(&self.bson[with: key][as: Mongo.PipelineEncoder.self]) } } @inlinable public - subscript(key:U) -> Replacement? - where Replacement:BSONEncodable + subscript(key:U) -> Replacement? where Replacement:BSONEncodable { get { nil } set (value) { value?.encode(to: &self.bson[with: key]) } } - +} +extension Mongo.UpdateStatement +{ @inlinable public subscript(key:ArrayFilters, yield:(inout Mongo.PredicateListEncoder) -> ()) -> Void {