 		case array               = 0x04
 		
 		/**
-		`NSData`.
-		Special internal type used by MongoDB replication and sharding.
+		`Data`. Special internal type used by MongoDB replication and sharding.
 		First 4 bytes are an increment, second 4 are a timestamp. */
 		case timestamp           = 0x11
-		/** `NSData`. Raw value is an Int32, followed by a subtype (1 byte) then
-		the actual bytes. */
+		/** `Data`. Raw value is an Int32, followed by a subtype (1 byte) then the
+		actual bytes. */
 		case binary              = 0x05
-		/** `NSData`. 12 bytes, used by MongoDB. */
+		/** `Data`. 12 bytes, used by MongoDB. */
 		case objectId            = 0x07
 		/** `String`. */
 		case javascript          = 0x0D
 		/**
-		`(String, NSDictionary)`. Raw value is an Int32 representing the length of
+		`(String, Dictionary)`. Raw value is an Int32 representing the length of
 		the whole raw value, then a string, then an embedded BSON doc.
 		
 		The document is a mapping from identifiers to values, representing the

		/** An invalid element was found. The element is given in argument to this
		enum case. */
		case invalidElementType(CUnsignedChar)
		
		/** Invalid UTF8 string found. The raw data forming the invalid UTF8
		string is given in argument to this enum case. */

			}
			
			let key = try readCString(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
			switch BSONElementType(rawValue: currentElementType) {
			case .null?:
				ret[key] = NSNull()
				
			case .boolean?:
				let valAsInt8 = try readDataFromBuffer(dataSize: 1, alwaysCopyBytes: false, buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream).first!
				switch valAsInt8 {
				case 0: ret[key] = false
				case 1: ret[key] = true
				default: throw BSONSerializationError.invalidBooleanValue(valAsInt8)
				}
				
			case .int32Bits?:
				let val: Int32 = try readType(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				ret[key] = val
				
			case .int64Bits?:
				let val: Int64 = try readType(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				ret[key] = val
				
			case .double64Bits?:
				let val: Double = try readType(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				ret[key] = val
				
			case .double128Bits?:
				ret[key] = try readDataFromBuffer(dataSize: 16, alwaysCopyBytes: true, buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				
			case .utcDateTime?:
				let timestamp: Int64 = try readType(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				ret[key] = Date(timeIntervalSince1970: TimeInterval(timestamp))
				
			case .regularExpression?:
				fatalError("Not Implemented")
				
			case .utf8String?:
				ret[key] = try readString(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				
			case .dictionary?:
				fatalError("Not Implemented")
				
			case .array?:
				fatalError("Not Implemented")
				
			case .timestamp?:
				ret[key] = try readDataFromBuffer(dataSize: 8, alwaysCopyBytes: true, buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				
			case .binary?:
				fatalError("Not Implemented")
				
			case .objectId?:
				ret[key] = try readDataFromBuffer(dataSize: 12, alwaysCopyBytes: true, buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				
			case .javascript?:
				ret[key] = try readString(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				
			case .javascriptWithScope?:
				fatalError("Not Implemented")
				
			case .minKey?:
				fatalError("Not Implemented")
				
			case .maxKey?:
				fatalError("Not Implemented")
				
			case .undefined?:
				fatalError("Not Implemented")
				
			case .dbPointer?:
				fatalError("Not Implemented")
				
			case .symbol?:
				ret[key] = try readString(buffer: buffer, bufferStartPos: &posInBuffer, bufferValidLength: &bufferSize, maxBufferSize: maxBufferSize, totalNReadBytes: &totalBytesRead, stream: stream)
				
			case nil: throw BSONSerializationError.invalidElementType(currentElementType)
			case .endOfDocument?: fatalError() /* Guarded before the switch */
			}
		}
		guard totalBytesRead == length else {throw BSONSerializationError.invalidLength}
