Repository: apple/swift-nio
File: Sources/NIOPosix/NonBlockingFileIO.swift (Swift)

Code before:
    /// - returns: An `EventLoopFuture` containing link target.
    public func readlink(path: String, eventLoop: EventLoop) -> EventLoopFuture<String> {
        return self.threadPool.runIfActive(eventLoop: eventLoop) {
            let maxLength = Int(PATH_MAX)
            let pointer = UnsafeMutableBufferPointer<CChar>.allocate(capacity: maxLength)
            defer {
                pointer.deallocate()
            }
            let length = try Posix.readlink(pathname: path, outPath: pointer.baseAddress!, outPathSize: maxLength)
            return String(decoding: UnsafeRawBufferPointer(pointer).prefix(length), as: UTF8.self)
        }
    }

    /// Removes symbolic link at `path` on a private thread pool which is separate from any `EventLoop` thread.
    ///
    /// - parameters:
    ///     - path: The path of the link to remove.
    ///     - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.
    /// - returns: An `EventLoopFuture` which is fulfilled if the rename was successful or fails on error.
    public func unlink(path: String, eventLoop: EventLoop) -> EventLoopFuture<Void> {
        return self.threadPool.runIfActive(eventLoop: eventLoop) {
            try Posix.unlink(pathname: path)
        }
    }

    public struct DirectoryEntry {
        // File number of entry
        var ino: UInt64
        // File type
        var type: UInt8
        // File name
        var name: String
    }

    /// List contents of the directory at `path` on a private thread pool which is separate from any `EventLoop` thread.
    ///
    /// - parameters:
    ///     - path: The path of the directory to list the content of.
    ///     - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.
    /// - returns: An `EventLoopFuture` containing the file list.
    public func listDirectory(path: String, eventLoop: EventLoop) -> EventLoopFuture<[DirectoryEntry]> {
        return self.threadPool.runIfActive(eventLoop: eventLoop) {
            let dir = try Posix.opendir(pathname: path)
            var entries: [DirectoryEntry] = []
            do {
                while let entry = try Posix.readdir(dir: dir) {
                    let name = withUnsafeBytes(of: entry.pointee.d_name) { pointer -> String in
                        // Per man readdir(3):
                        // struct dirent {
                        //  char d_name[256]; /* Null-terminated filename */
                        #if os(Linux)

Review comment (suggestion):
This type needs a doc comment, both on the type and on the properties. All the properties need to be public, we need a public memberwise initializer, and this should probably be `Hashable` too.

Code after:
    /// - returns: An `EventLoopFuture` containing link target.
    public func readlink(path: String, eventLoop: EventLoop) -> EventLoopFuture<String> {
        return self.threadPool.runIfActive(eventLoop: eventLoop) {
            let maxLength = Int(PATH_MAX)
            let pointer = UnsafeMutableBufferPointer<CChar>.allocate(capacity: maxLength)
            defer {
                pointer.deallocate()
            }
            let length = try Posix.readlink(pathname: path, outPath: pointer.baseAddress!, outPathSize: maxLength)
            return String(decoding: UnsafeRawBufferPointer(pointer).prefix(length), as: UTF8.self)
        }
    }

    /// Removes symbolic link at `path` on a private thread pool which is separate from any `EventLoop` thread.
    ///
    /// - parameters:
    ///     - path: The path of the link to remove.
    ///     - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.
    /// - returns: An `EventLoopFuture` which is fulfilled if the rename was successful or fails on error.
    public func unlink(path: String, eventLoop: EventLoop) -> EventLoopFuture<Void> {
        return self.threadPool.runIfActive(eventLoop: eventLoop) {
            try Posix.unlink(pathname: path)
        }
    }

    /// List contents of the directory at `path` on a private thread pool which is separate from any `EventLoop` thread.
    ///
    /// - parameters:
    ///     - path: The path of the directory to list the content of.
    ///     - eventLoop: The `EventLoop` on which the returned `EventLoopFuture` will fire.
    /// - returns: An `EventLoopFuture` containing the directory entries.
    public func listDirectory(path: String, eventLoop: EventLoop) -> EventLoopFuture<[NIODirectoryEntry]> {
        return self.threadPool.runIfActive(eventLoop: eventLoop) {
            let dir = try Posix.opendir(pathname: path)
            var entries: [NIODirectoryEntry] = []
            do {
                while let entry = try Posix.readdir(dir: dir) {
                    let name = withUnsafeBytes(of: entry.pointee.d_name) { pointer -> String in
                        let ptr = pointer.baseAddress!.assumingMemoryBound(to: CChar.self)
                        return String(cString: ptr)
                    }
                    entries.append(NIODirectoryEntry(ino: UInt64(entry.pointee.d_ino), type: entry.pointee.d_type, name: name))
                }
                try? Posix.closedir(dir: dir)
            } catch {
                try? Posix.closedir(dir: dir)
                throw error
            }
            return entries
        }
    }