Skip to content

Commit

Permalink
- contents(atPath:) to use Range instead of offset-length pair
Browse files Browse the repository at this point in the history
- write(data:) parameter is DataProtocol
- Updated Readme
- Refactoring obj-c layer
  • Loading branch information
amosavian committed Apr 26, 2019
1 parent 1a9c121 commit 8beedae
Show file tree
Hide file tree
Showing 5 changed files with 300 additions and 190 deletions.
4 changes: 4 additions & 0 deletions AMSMB2.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
790FA33920B2CC5600578C8A /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 790FA33820B2CC5600578C8A /* Extensions.swift */; };
7957E1F220F1EEB100F96CE4 /* Fsctl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7957E1F120F1EEB100F96CE4 /* Fsctl.swift */; };
7966DC4D2273A5CA00BBC39D /* ObjCCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7966DC4C2273A5CA00BBC39D /* ObjCCompat.swift */; };
79B5EDBD210FE1DB00449EF6 /* MSRPC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79B5EDBC210FE1DB00449EF6 /* MSRPC.swift */; };
79FDFE5E20AD439F00749FB5 /* AMSMB2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79FDFE5420AD439F00749FB5 /* AMSMB2.framework */; };
79FDFE6320AD439F00749FB5 /* AMSMB2Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FDFE6220AD439F00749FB5 /* AMSMB2Tests.swift */; };
Expand All @@ -33,6 +34,7 @@
/* Begin PBXFileReference section */
790FA33820B2CC5600578C8A /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
7957E1F120F1EEB100F96CE4 /* Fsctl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fsctl.swift; sourceTree = "<group>"; };
7966DC4C2273A5CA00BBC39D /* ObjCCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjCCompat.swift; sourceTree = "<group>"; };
79B5EDBC210FE1DB00449EF6 /* MSRPC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MSRPC.swift; sourceTree = "<group>"; };
79FDFE5420AD439F00749FB5 /* AMSMB2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AMSMB2.framework; sourceTree = BUILT_PRODUCTS_DIR; };
79FDFE5720AD439F00749FB5 /* AMSMB2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AMSMB2.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -92,6 +94,7 @@
79FDFE5820AD439F00749FB5 /* Info.plist */,
79FDFE5720AD439F00749FB5 /* AMSMB2.h */,
79FDFE6E20AD45C100749FB5 /* AMSMB2.swift */,
7966DC4C2273A5CA00BBC39D /* ObjCCompat.swift */,
79FDFE7B20AD545D00749FB5 /* Context.swift */,
79B5EDBC210FE1DB00449EF6 /* MSRPC.swift */,
7957E1F120F1EEB100F96CE4 /* Fsctl.swift */,
Expand Down Expand Up @@ -235,6 +238,7 @@
790FA33920B2CC5600578C8A /* Extensions.swift in Sources */,
79FDFE6F20AD45C100749FB5 /* AMSMB2.swift in Sources */,
79B5EDBD210FE1DB00449EF6 /* MSRPC.swift in Sources */,
7966DC4D2273A5CA00BBC39D /* ObjCCompat.swift in Sources */,
7957E1F220F1EEB100F96CE4 /* Fsctl.swift in Sources */,
79FDFE7A20AD541500749FB5 /* URL.swift in Sources */,
79FDFF0120AD852200749FB5 /* FileHandle.swift in Sources */,
Expand Down
185 changes: 44 additions & 141 deletions AMSMB2/AMSMB2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect

/**
Disconnects from a share.
- Important: Disconnecting when an operation is in progress may cause disgraceful termination of operation.
*/
@objc(disconnectShare)
open func disconnectShare() {
Expand All @@ -242,11 +244,15 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect

/**
Disconnects from a share.
- Important: Disconnecting when an operation is in progress may cause disgraceful termination of operation.
*/
@objc(disconnectShareWithCompletionHandler:)
open func disconnectShare(completionHandler: SimpleCompletionHandler) {
q.async {
do {
self.connectLock.lock()
defer { self.connectLock.unlock() }
try self.context?.disconnect()
self.context = nil
self.connectedShare = nil
Expand Down Expand Up @@ -310,52 +316,6 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect
}
}

/**
Enumerates shares' list on server.
- Parameters:
- completionHandler: closure will be run after enumerating is completed.
- names: An array of share names. Can be passed to `connectShare()` function.
- comments: An array of share remark name, related to names array with same index. Suitable for displaying shares to user.
- error: `Error` if any occured during enumeration.
*/
@available(swift, obsoleted: 1.0)
@objc(listSharesWithCompletionHandler:)
public func __listShares(completionHandler: @escaping (_ names: [String], _ comments: [String], _ error: Error?) -> Void) {
listShares(enumerateHidden: false) { (result) in
switch result {
case .success(let shares):
completionHandler(shares.map({ $0.name }), shares.map({ $0.comment }), nil)
case .failure(let error):
completionHandler([], [], error)
}
}
}

/**
Enumerates shares' list on server.
- Parameters:
- enumerateHidden: enumrating special/administrative e.g. user directory in macOS or
shares usually ends with `$`, e.g. `C$` or `admin$`.
- completionHandler: closure will be run after enumerating is completed.
- names: An array of share names. Can be passed to `connectShare()` function.
- comments: An array of share remark name, related to names array with same index. Suitable for displaying shares to user.
- error: `Error` if any occured during enumeration.
*/
@available(swift, obsoleted: 1.0)
@objc(listSharesWithEnumerateHidden:completionHandler:)
public func __listShares(enumerateHidden: Bool, completionHandler: @escaping (_ names: [String], _ comments: [String], _ error: Error?) -> Void) {
listShares(enumerateHidden: enumerateHidden) { (result) in
switch result {
case .success(let shares):
completionHandler(shares.map({ $0.name }), shares.map({ $0.comment }), nil)
case .failure(let error):
completionHandler([], [], error)
}
}
}

/**
Enumerates directory contents in the give path.
Expand All @@ -374,23 +334,6 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect
}
}

/**
Enumerates directory contents in the give path.
- Parameters:
- atPath: path of directory to be enumerated.
- completionHandler: closure will be run after enumerating is completed.
- recursive: subdirectories will enumerated if `true`.
- contents: An array of `[URLResourceKey: Any]` which holds files' attributes. file name is stored in `.nameKey`.
- error: `Error` if any occured during enumeration.
*/
@available(swift, obsoleted: 1.0)
@objc(contentsOfDirectoryAtPath:recursive:completionHandler:)
public func __contentsOfDirectory(atPath path: String, recursive: Bool = false,
completionHandler: @escaping (_ contents: [[URLResourceKey: Any]]?, _ error: Error?) -> Void) {
contentsOfDirectory(atPath: path, recursive: recursive, completionHandler: convert(completionHandler))
}

/**
Returns a dictionary that describes the attributes of the mounted file system on which a given path resides.
Expand Down Expand Up @@ -421,23 +364,6 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect
}
}

/**
Returns a dictionary that describes the attributes of the mounted file system on which a given path resides.
- Parameters:
- forPath: Any pathname within the mounted file system.
- completionHandler: closure will be run after fetching attributes is completed.
- attrubutes: A dictionary object that describes the attributes of the mounted file system on which path resides.
See _File-System Attribute Keys_ for a description of the keys available in the dictionary.
- error: `Error` if any occured during enumeration.
*/
@available(swift, obsoleted: 1.0)
@objc(attributesOfFileSystemForPath:completionHandler:)
public func __attributesOfFileSystem(forPath path: String,
completionHandler: @escaping (_ attrubutes: [FileAttributeKey: Any]?, _ error: Error?) -> Void) {
attributesOfFileSystem(forPath: path, completionHandler: convert(completionHandler))
}

/**
Returns the attributes of the item at given path.
Expand All @@ -462,22 +388,6 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect
}
}

/**
Returns the attributes of the item at given path.
- Parameters:
- atPath: path of file to be enumerated.
- completionHandler: closure will be run after enumerating is completed.
- file: An dictionary with `URLResourceKey` as key which holds file's attributes.
- error: `Error` if any occured during enumeration.
*/
@available(swift, obsoleted: 1.0)
@objc(attributesOfItemAtPath:completionHandler:)
public func __attributesOfItem(atPath path: String,
completionHandler: @escaping (_ file: [URLResourceKey: Any]?, _ error: Error?) -> Void) {
attributesOfItem(atPath: path, completionHandler: convert(completionHandler))
}

/**
Creates a new directory at given path.
Expand Down Expand Up @@ -610,51 +520,58 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect
}
}

/**
Fetches whole data contents of a file. With reporting progress on about every 1MiB.
- Parameters:
- atPath: path of file to be fetched.
- progress: reports progress of recieved bytes count read and expected content length.
User must return `true` if they want to continuing or `false` to abort reading.
- bytes: recieved bytes count.
- total: expected content length.
- completionHandler: closure will be run after reading data is completed.
- result: a `Data` object which contains file contents.
*/
open func contents(atPath path: String, progress: SMB2ReadProgressHandler,
completionHandler: @escaping (_ result: Result<Data, Error>) -> Void) {
contents(atPath: path, range: 0..<Int64.max, progress: progress, completionHandler: completionHandler)
}

/**
Fetches data contents of a file from an offset with specified length. With reporting progress
on about every 1MiB.
- Note: If offset is bigger than file's size, an empty `Data will be returned. If length exceeds file, returned data
will be truncated to entire file content from given offset.
- Note: If range's lowerBound is bigger than file's size, an empty `Data` will be returned.
If range's length exceeds file, returned data will be truncated to entire file content from given offset.
- Parameters:
- atPath: path of file to be fetched.
- offset: first byte of file to be read, starting from zero.
- length: length of bytes should be read from offset. If a value.
- range: byte range that should be read, default value is whole file. e.g. `..<10` will read first ten bytes.
- progress: reports progress of recieved bytes count read and expected content length.
User must return `true` if they want to continuing or `false` to abort reading.
- bytes: recieved bytes count.
- total: expected content length.
- completionHandler: closure will be run after reading data is completed.
- contents: a `Data` object which contains file contents.
- error: `Error` if any occured during reading.
- result: a `Data` object which contains file contents.
*/
@objc(contentsAtPath:fromOffset:toLength:progress:completionHandler:)
open func contents(atPath path: String, offset: Int64 = 0, length: Int = -1, progress: SMB2ReadProgressHandler,
completionHandler: @escaping (_ contents: Data?, _ error: Error?) -> Void) {
open func contents<R: RangeExpression>(atPath path: String, range: R? = nil, progress: SMB2ReadProgressHandler,
completionHandler: @escaping (_ result: Result<Data, Error>) -> Void)
where R.Bound: FixedWidthInteger
{
let range: Range<R.Bound> = range?.relative(to: 0..<R.Bound.max) ?? 0..<R.Bound.max
let lower = Int64(exactly: range.lowerBound) ?? Int64.max
let upper = Int64(exactly: range.upperBound) ?? Int64.max
let int64Range = lower..<upper

q.async {
do {
guard offset >= 0 else {
throw POSIXError(.EINVAL, description: "Invalid content offset.")
}

completionHandler(.init(catching: { () -> Data in
let stream = OutputStream.toMemory()
if length > 0 {
try self.read(path: path, range: offset..<(offset + Int64(length)), to: stream, progress: progress)
} else if length < 0 {
try self.read(path: path, range: offset..<Int64.max, to: stream, progress: progress)
} else {
completionHandler(nil, nil)
return
}
try self.read(path: path, range: int64Range, to: stream, progress: progress)
guard let data = stream.property(forKey: .dataWrittenToMemoryStreamKey) as? Data else {
throw POSIXError(.EIO, description: "Data missed from stream")
}

completionHandler(data, nil)
} catch {
completionHandler(nil, error)
}
return data
}))
}
}

Expand Down Expand Up @@ -706,19 +623,18 @@ public class AMSMB2: NSObject, NSSecureCoding, Codable, NSCopying, CustomReflect
- Note: Data saved in server maybe truncated when completion handler returns error.
- Parameters:
- data: data that must be written to file.
- data: data that must be written to file. You can pass either `Data`, `[UInt8]` or `NSData` object.
- toPath: path of file to be written.
- progress: reports progress of written bytes count so far.
User must return `true` if they want to continuing or `false` to abort writing.
- bytes: written bytes count.
- completionHandler: closure will be run after writing is completed.
*/
@objc(writeData:toPath:progress:completionHandler:)
open func write(data: Data, toPath path: String, progress: SMB2WriteProgressHandler,
completionHandler: SimpleCompletionHandler) {
open func write<DataType: DataProtocol>(data: DataType, toPath path: String, progress: SMB2WriteProgressHandler,
completionHandler: SimpleCompletionHandler) {
q.async {
do {
let stream = InputStream(data: data)
let stream = InputStream(data: Data(data))
try self.write(from: stream, toPath: path, chunkSize: 0, progress: progress)
completionHandler?(nil)
} catch {
Expand Down Expand Up @@ -1165,16 +1081,3 @@ extension AMSMB2 {
try file.fsync()
}
}

extension AMSMB2 {
func convert<T>(_ resultCompletion: @escaping (T?, Error?) -> Void) -> ((Result<T, Error>) -> Void) {
return { result in
switch result {
case .success(let val):
resultCompletion(val, nil)
case .failure(let error):
resultCompletion(nil, error)
}
}
}
}
Loading

0 comments on commit 8beedae

Please sign in to comment.