Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -379,14 +379,15 @@ axes:
- id: swift-version
display_name: "Swift"
values:
- id: "4.2"
display_name: "Swift 4.2"
variables:
SWIFT_VERSION: "4.2.4"
- id: "5.0"
display_name: "Swift 5.0"
variables:
SWIFT_VERSION: "5.0"
SWIFT_VERSION: "5.0.3"
# TODO SWIFT-634: uncomment this
# - id: "5.1"
# display_name: "Swift 5.1"
# variables:
# SWIFT_VERSION: "5.1"

- id: ssl
display_name: SSL
Expand Down
2 changes: 1 addition & 1 deletion .evergreen/run-atlas-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set -o errexit # Exit the script with error if any of the commands fail

# variables
PROJECT_DIRECTORY=${PROJECT_DIRECTORY:-$PWD}
SWIFT_VERSION=${SWIFT_VERSION:-4.2}
SWIFT_VERSION=${SWIFT_VERSION:-5.0}
INSTALL_DIR="${PROJECT_DIRECTORY}/opt"
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
EXTRA_FLAGS="-Xlinker -rpath -Xlinker ${INSTALL_DIR}/lib"
Expand Down
2 changes: 1 addition & 1 deletion .evergreen/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -o errexit # Exit the script with error if any of the commands fail
# variables
PROJECT_DIRECTORY=${PROJECT_DIRECTORY:-$PWD}
MONGODB_URI=${MONGODB_URI:-"NO_URI_PROVIDED"}
SWIFT_VERSION=${SWIFT_VERSION:-4.2}
SWIFT_VERSION=${SWIFT_VERSION:-5.0}
INSTALL_DIR="${PROJECT_DIRECTORY}/opt"
TOPOLOGY=${TOPOLOGY:-single}
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
Expand Down
16 changes: 1 addition & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,19 @@ jobs:
- make linuxmain SOURCERY=${PWD}/sourcery/bin/sourcery
- git diff --exit-code Tests/LinuxMain.swift

- stage: tests
os: osx
osx_image: xcode10.1
env: SWIFT_VERSION=4.2.4

- stage: tests
os: osx
osx_image: xcode10.2
env: SWIFT_VERSION=4.2.4

- stage: tests
os: osx
osx_image: xcode10.2
env: SWIFT_VERSION=5.0

- stage: tests
os: linux
env: SWIFT_VERSION=4.2.4

- stage: tests
os: linux
env: SWIFT_VERSION=5.0

- stage: post-tests
name: code coverage
os: osx
osx_image: xcode10.1
osx_image: xcode10.2
script: make coverage
after_success: bash <(curl -s https://codecov.io/bash)

Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:4.2
// swift-tools-version:5.0
import PackageDescription
let package = Package(
name: "MongoSwift",
Expand Down
43 changes: 9 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ The official [MongoDB](https://www.mongodb.com/) driver for Swift.
- [Documentation](#documentation)
- [Bugs/Feature Requests](#bugs--feature-requests)
- [Installation](#installation)
- [macOS and Linux](#macos-and-linux)
- [Step 1: Install the MongoDB C Driver](#step-1-install-the-mongodb-c-driver)
- [Step 2: Install MongoSwift](#step-2-install-mongoswift)
- [iOS, tvOS, and watchOS](#ios-tvos-and-watchos)
- [Step 1: Install the MongoDB C Driver](#step-1-install-the-mongodb-c-driver)
- [Step 2: Install MongoSwift](#step-2-install-mongoswift)
- [Example Usage](#example-usage)
- [Connect to MongoDB and Create a Collection](#connect-to-mongodb-and-create-a-collection)
- [Create and Insert a Document](#create-and-insert-a-document)
Expand All @@ -35,13 +33,11 @@ Bug reports in JIRA for all driver projects (i.e. NODE, PYTHON, CSHARP, JAVA) an
Core Server (i.e. SERVER) project are **public**.

## Installation
`MongoSwift` works with Swift 4.2+.
`MongoSwift` works with Swift 5.0+ on MacOS and Linux.

### macOS and Linux
Installation is supported via [Swift Package Manager](https://swift.org/package-manager/).

Installation on macOS and Linux is supported via [Swift Package Manager](https://swift.org/package-manager/).

#### Step 1: Install the MongoDB C Driver
### Step 1: Install the MongoDB C Driver
The driver wraps the MongoDB C driver, and using it requires having the C driver's two components, `libbson` and `libmongoc`, installed on your system. **The minimum required version of the C Driver is 1.15.1**.

*On a Mac*, you can install both components at once using [Homebrew](https://brew.sh/):
Expand All @@ -51,13 +47,13 @@ The driver wraps the MongoDB C driver, and using it requires having the C driver

See example installation from source on Ubuntu in [Docker](https://github.com/mongodb/mongo-swift-driver/tree/master/Examples/Docker).

#### Step 2: Install MongoSwift
### Step 2: Install MongoSwift
*Please follow the instructions in the previous section on installing the MongoDB C Driver before proceeding.*

Add MongoSwift to your dependencies in `Package.swift`:

```swift
// swift-tools-version:4.2
// swift-tools-version:5.0
import PackageDescription

let package = Package(
Expand All @@ -73,27 +69,6 @@ let package = Package(

Then run `swift build` to download, compile, and link all your dependencies.

## iOS, tvOS, and watchOS
Installation is supported via [CocoaPods](https://cocoapods.org/).

The pod includes as a dependency an embedded version of the MongoDB C Driver, meant for use on these OSes.

**Note**: the embedded driver currently does not support SSL. See [#141](https://github.com/mongodb/mongo-swift-driver/issues/141) and [CDRIVER-2850](https://jira.mongodb.org/browse/CDRIVER-2850) for more information.

Add `MongoSwift` to your Podfile as follows:


```ruby
platform :ios, '11.0'
use_frameworks!

target 'MyApp' do
pod 'MongoSwift', '~> VERSION.STRING.HERE'
end
```

Then run `pod install` to install your project's dependencies.

## Example Usage

Note: You should call `cleanupMongoSwift()` exactly once at the end of your application to release all memory and other resources allocated by `libmongoc`.
Expand Down Expand Up @@ -164,8 +139,8 @@ Note that `Document` conforms to `Collection`, so useful methods from
all available. However, runtime guarantees are not yet met for many of these
methods.

### Usage With Kitura and Vapor
The `Examples/` directory contains sample projects that use the driver with [Kitura](https://github.com/mongodb/mongo-swift-driver/tree/master/Examples/Kitura) and [Vapor](https://github.com/mongodb/mongo-swift-driver/tree/master/Examples/Vapor).
### Usage With Kitura, Vapor, and Perfect
The `Examples/` directory contains sample projects that use the driver with [Kitura](https://github.com/mongodb/mongo-swift-driver/tree/master/Examples/Kitura), [Vapor](https://github.com/mongodb/mongo-swift-driver/tree/master/Examples/Vapor), and [Perfect](https://github.com/mongodb/mongo-swift-driver/tree/master/Examples/Perfect).

## Development Instructions

Expand Down
4 changes: 2 additions & 2 deletions Sources/MongoSwift/BSON/BSONEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ private class MutableDictionary: BSONValue {

subscript(key: String) -> BSONValue? {
get {
guard let index = keys.index(of: key) else {
guard let index = keys.firstIndex(of: key) else {
return nil
}
return values[index]
Expand All @@ -779,7 +779,7 @@ private class MutableDictionary: BSONValue {
keys.append(key)
values.append(newValue)
} else {
guard let index = keys.index(of: key) else {
guard let index = keys.firstIndex(of: key) else {
return
}
values.remove(at: index)
Expand Down
33 changes: 25 additions & 8 deletions Sources/MongoSwift/BSON/BSONValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ public struct Binary: BSONValue, Equatable, Codable, Hashable {
public init(from uuid: UUID) throws {
let uuidt = uuid.uuid

let uuidData = Data(bytes: [
let uuidData = Data([
uuidt.0, uuidt.1, uuidt.2, uuidt.3,
uuidt.4, uuidt.5, uuidt.6, uuidt.7,
uuidt.8, uuidt.9, uuidt.10, uuidt.11,
Expand Down Expand Up @@ -509,11 +509,11 @@ public struct Decimal128: BSONNumber, Equatable, Codable, CustomStringConvertibl

public var description: String {
var str = Data(count: Int(BSON_DECIMAL128_STRING))
return str.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<Int8>) in
withUnsafePointer(to: self.decimal128) { ptr in
bson_decimal128_to_string(ptr, bytes)
return str.withUnsafeMutableCStringPointer { strPtr in
withUnsafePointer(to: self.decimal128) { decPtr in
bson_decimal128_to_string(decPtr, strPtr)
}
return String(cString: bytes)
return String(cString: strPtr)
}
}

Expand Down Expand Up @@ -887,11 +887,11 @@ public struct ObjectId: BSONValue, Equatable, CustomStringConvertible, Codable {
/// This `ObjectId`'s data represented as a `String`.
public var hex: String {
var str = Data(count: 25)
return str.withUnsafeMutableBytes { (rawBuffer: UnsafeMutablePointer<Int8>) in
return str.withUnsafeMutableCStringPointer { strPtr in
withUnsafePointer(to: self.oid) { oidPtr in
bson_oid_to_string(oidPtr, rawBuffer)
bson_oid_to_string(oidPtr, strPtr)
}
return String(cString: rawBuffer)
return String(cString: strPtr)
}
}

Expand Down Expand Up @@ -1374,3 +1374,20 @@ internal func getDecodingError<T: BSONValue>(type: T.Type, decoder: Decoder) ->
// Non-BSONDecoders are currently unsupported
return bsonDecodingUnsupportedError(type: T.self, at: decoder.codingPath)
}

extension Data {
/// Gets access to the start of the data buffer in the form of an UnsafeMutablePointer<CChar>. Useful for calling C
/// API methods that expect a location for a string. **You must only call this method on Data instances with
/// count > 0 so that the base address will exist.**
/// Based on https://mjtsai.com/blog/2019/03/27/swift-5-released/
fileprivate mutating func withUnsafeMutableCStringPointer<T>(body: (UnsafeMutablePointer<CChar>) throws -> T)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the old way we were doing this was deprecated

rethrows -> T {
return try self.withUnsafeMutableBytes { (rawPtr: UnsafeMutableRawBufferPointer) in
let bufferPtr = rawPtr.bindMemory(to: CChar.self)
// baseAddress is non-nil as long as Data's count > 0.
// swiftlint:disable:next force_unwrapping
let bytesPtr = bufferPtr.baseAddress!
return try body(bytesPtr)
}
}
}
35 changes: 29 additions & 6 deletions Sources/MongoSwift/BSON/Document.swift
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ extension Document {
* - A `UserError.invalidArgumentError` if the data passed in is invalid JSON.
*/
public init(fromJSON: Data) throws {
self._storage = DocumentStorage(stealing: try fromJSON.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
self._storage = DocumentStorage(stealing: try fromJSON.withUnsafeBytePointer { bytes in
var error = bson_error_t()
guard let bson = bson_new_from_json(bytes, fromJSON.count, &error) else {
if error.domain == BSON_ERROR_JSON {
Expand All @@ -356,11 +356,20 @@ extension Document {
// see https://www.objc.io/blog/2018/02/13/string-to-data-and-back/
try self.init(fromJSON: json.data(using: .utf8)!) // swiftlint:disable:this force_unwrapping
}

/// Constructs a `Document` from raw BSON `Data`.
public init(fromBSON: Data) {
self._storage = DocumentStorage(stealing: fromBSON.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
bson_new_from_data(bytes, fromBSON.count)
/**
* Constructs a `Document` from raw BSON `Data`.
* - Throws:
* - A `UserError.invalidArgumentError` if `bson` is too short or too long to be valid BSON.
* - A `UserError.invalidArgumentError` if the first four bytes of `bson` do not contain `bson.count`.
* - A `UserError.invalidArgumentError` if the final byte of `bson` is not a null byte.
* - SeeAlso: http://bsonspec.org/
*/
public init(fromBSON bson: Data) throws {
self._storage = DocumentStorage(stealing: try bson.withUnsafeBytePointer { bytes in
guard let data = bson_new_from_data(bytes, bson.count) else {
throw UserError.invalidArgumentError(message: "Invalid BSON data")
}
return data
})
}

Expand Down Expand Up @@ -547,3 +556,17 @@ extension Document: Hashable {
hasher.combine(self.rawBSON)
}
}

extension Data {
/// Gets access to the start of the data buffer in the form of an UnsafePointer<UInt8>?. Useful for calling C API
/// methods that expect the location of an uint8_t. The pointer provided to `body` will be null if the `Data` has
/// count == 0.
/// Based on https://mjtsai.com/blog/2019/03/27/swift-5-released/
fileprivate func withUnsafeBytePointer<T>(body: (UnsafePointer<UInt8>?) throws -> T) rethrows -> T {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the old way we were doing this was deprecated

return try self.withUnsafeBytes { (rawPtr: UnsafeRawBufferPointer) in
let bufferPtr = rawPtr.bindMemory(to: UInt8.self)
let bytesPtr = bufferPtr.baseAddress
return try body(bytesPtr)
}
}
}
1 change: 1 addition & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ extension DocumentTests {
("testDateDecodingStrategies", testDateDecodingStrategies),
("testDataCodingStrategies", testDataCodingStrategies),
("testIntegerRetrieval", testIntegerRetrieval),
("testInvalidBSON", testInvalidBSON),
]
}

Expand Down
Loading