Skip to content

Commit

Permalink
rewrite projection API to use ProjectionEncoder and ProjectionEncodable
Browse files Browse the repository at this point in the history
  • Loading branch information
tayloraswift committed May 17, 2024
1 parent a67e2cd commit 377202e
Show file tree
Hide file tree
Showing 18 changed files with 423 additions and 180 deletions.
31 changes: 8 additions & 23 deletions Snippets/ExampleProjectionDocuments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,15 @@ func ExampleProjectionDocuments()
{
let _:Mongo.ProjectionDocument = .init
{
$0["expression"] = .expr
$0["expression"] { $0[.abs] = "$field" }
$0["key1"] = true
$0["key2"] { $0[.literal] = 1 }
$0["a"] { $0[.slice] = 1 }
$0["b"] { $0[.slice] = (1, 1) }
$0["c"] { $0[.meta] = .indexKey }
$0["d"]
{
$0[.abs] = "$field"
}
$0["key1"] = 1
$0["key2"] = .expr
{
$0[.literal] = 1
}
$0["a"] = .init
{
$0[.slice] = 1
}
$0["b"] = .init
{
$0[.slice] = (1, 1)
}
$0["c"] = .init
{
$0[.meta] = .indexKey
}
$0["d"] = .init
{
$0[.first] = .init
$0[.first]
{
$0[.or]
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extension Mongo
{
public
protocol PredicateEncodable
{
func encode(to predicate:inout PredicateEncoder)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MongoABI
extension Mongo
{
@frozen public
struct ProjectionDocument:Mongo.EncodableDocument, Sendable
struct ProjectionDocument:Sendable
{
public
var bson:BSON.Document
Expand All @@ -16,35 +16,8 @@ extension Mongo
}
}
}
extension Mongo.ProjectionDocument
extension Mongo.ProjectionDocument:Mongo.EncodableDocument
{
/// Encodes a ``ProjectionOperator``.
///
/// This does not require [`@_disfavoredOverload`](), because
/// ``ProjectionOperator`` has no subscripts that accept string
/// literals, so it will never conflict with ``BSON.Document``.
@inlinable public
subscript(path:Mongo.AnyKeyPath) -> Mongo.ProjectionOperator?
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: path.stem])
}
}
@inlinable public
subscript<Encodable>(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: path.stem])
}
}
public
typealias Encoder = Mongo.ProjectionEncoder
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extension Mongo
{
public
protocol ProjectionEncodable
{
func encode(to projection:inout ProjectionEncoder)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import BSON
import MongoABI

extension Mongo
{
@frozen public
struct ProjectionEncoder:Sendable
{
@usableFromInline
var bson:BSON.DocumentEncoder<Mongo.AnyKeyPath>

@inlinable internal
init(bson:BSON.DocumentEncoder<Mongo.AnyKeyPath>)
{
self.bson = bson
}
}
}
extension Mongo.ProjectionEncoder: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.ProjectionEncoder
{
@available(*, unavailable, message: "Use the boolean subscript instead.")
@inlinable public
subscript(path:Mongo.AnyKeyPath) -> Int?
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: path])
}
}

@inlinable public
subscript(path:Mongo.AnyKeyPath) -> Bool?
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: path])
}
}

/// Encodes a nested projection document.
@inlinable public
subscript(path:Mongo.AnyKeyPath, yield:(inout Mongo.ProjectionEncoder) -> ()) -> Void
{
mutating get
{
yield(&self.bson[with: path][as: Mongo.ProjectionEncoder.self])
}
}

/// Encodes a projection expression.
@inlinable public
subscript(path:Mongo.AnyKeyPath, yield:(inout Mongo.ExpressionEncoder) -> ()) -> Void
{
mutating get
{
yield(&self.bson[with: path][as: Mongo.ExpressionEncoder.self])
}
}

/// Encodes a projection operator.
@inlinable public
subscript(path:Mongo.AnyKeyPath,
yield:(inout Mongo.ProjectionOperatorEncoder) -> ()) -> Void
{
mutating get
{
yield(&self.bson[with: path][as: Mongo.ProjectionOperatorEncoder.self])
}
}

/// Encodes a projection operator from a model type.
@inlinable public
subscript<Operator>(path:Mongo.AnyKeyPath) -> Operator?
where Operator:Mongo.ProjectionOperatorEncodable
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: path][as: Mongo.ProjectionOperatorEncoder.self])
}
}
}
@available(*, deprecated)
extension Mongo.ProjectionEncoder
{
/// Encodes a ``ProjectionOperator``.
///
/// This does not require `@_disfavoredOverload`, because ``ProjectionOperator`` has no
/// subscripts that accept string literals, so it will never conflict with
/// ``BSON.Document``.
@inlinable public
subscript(path:Mongo.AnyKeyPath) -> Mongo.ProjectionOperator?
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: path.stem])
}
}
@inlinable public
subscript<Encodable>(path:Mongo.AnyKeyPath) -> Encodable? where Encodable:BSONEncodable
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: path.stem])
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import BSON

extension Mongo
{
@frozen public
enum ProjectionMetadata:String, Hashable, Sendable
{
case textScore
case indexKey
}
}
extension Mongo.ProjectionMetadata:BSONDecodable, BSONEncodable
{
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import BSON
extension Mongo
{
@frozen public
struct ProjectionOperator:Mongo.EncodableDocument, Sendable
struct ProjectionOperator:Sendable
{
public
var bson:BSON.Document
Expand All @@ -15,74 +15,8 @@ extension Mongo
}
}
}
extension Mongo.ProjectionOperator
extension Mongo.ProjectionOperator:Mongo.EncodableDocument
{
@inlinable public
subscript(key:First) -> Mongo.PredicateDocument?
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: key])
}
}
}
extension Mongo.ProjectionOperator
{
@inlinable public
subscript(key:Meta) -> Metadata?
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: key])
}
}
}
extension Mongo.ProjectionOperator
{
@inlinable public
subscript<Distance>(key:Slice) -> Distance?
where Distance:BSONEncodable
{
get
{
nil
}
set(value)
{
value?.encode(to: &self.bson[with: key])
}
}
@inlinable public
subscript<Index, Count>(key:Slice) -> (at:Index?, count:Count?)
where Index:BSONEncodable, Count:BSONEncodable
{
get
{
(nil, nil)
}
set(value)
{
guard let count:Count = value.count
else
{
return
}

{
if let index:Index = value.at
{
$0.append(index)
}
$0.append(count)
} (&self.bson[with: key][as: BSON.ListEncoder.self])
}
}
public
typealias Encoder = Mongo.ProjectionOperatorEncoder
}
Loading

0 comments on commit 377202e

Please sign in to comment.