Skip to content

Add AsyncBytes, AsyncLineSequence, AsyncCharacterSequence, and AsyncUnicodeScalarSequence #3036

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

Catfish-Man
Copy link
Contributor

Only the local-file versions of AsyncBytes for now

@Catfish-Man Catfish-Man self-assigned this Aug 11, 2021
let fh = try await IOActor.default.createFileHandle(reading: url).bytes.makeAsyncIterator()
buf = fh.buffer
} else {
// TODO: add networking support
Copy link
Contributor

Choose a reason for hiding this comment

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

For future reference: use _NSNonfileURLContentLoader in SCF to load using URLSession if available. Right now it only returns an in-memory NSData after all is done, but it may be sufficient here.

@millenomi
Copy link
Contributor

@swift-ci please test

public struct Iterator: AsyncIteratorProtocol {

@inline(__always) static var bufferSize: Int {
16384
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It occurs to me this should probably be 16384 minus the size of the object header

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or maybe not so the loop can be aligned. Ugh, I'll need to dig into this at some point.

Will follow up on _read after

Co-authored-by: Aura Lily Vulcano <[email protected]>
@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

I missed the change.

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

Ah, never mind, this has merge conflicts.

@millenomi
Copy link
Contributor

@swift-ci please test

1 similar comment
@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

millenomi commented Sep 1, 2021

Waiting for Linux build to pass before correcting the availability annotation for macOS. (Or fail.)

("testSeparatorPrefixAndContinuationWithoutFin", test_seperator_prefix_and_continuation_without_fin)
]

return tests
Copy link
Contributor

Choose a reason for hiding this comment

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

@Catfish-Man Is this what you meant here? This method was missing its termination.

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

A little worried about this patch as we haven't even gotten to making tests run yet. @Catfish-Man do you have some time to shepherd it actively?

@millenomi
Copy link
Contributor

(Hopefully this one is the run that gets to unit tests.)

@millenomi
Copy link
Contributor

The tests aren't running because they weren't listed in the main.

@millenomi
Copy link
Contributor

@swift-ci please test

@millenomi
Copy link
Contributor

@swift-ci please test

Comment on lines +26 to +32
#if canImport(Darwin)
let read = Darwin.read
#elseif canImport(Glibc)
let read = Glibc.read
#elseif canImport(CRT)
let read = CRT._read
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any utility in s-c-f for avoiding doing this everywhere read(2) is used? If not, is there a specific reason otherwise? (Offhand, "want to just use System when possible someday" comes to mind.)

Citation: https://github.com/apple/swift-nio/blob/main/Sources/NIOPosix/System.swift#L60-L80 et al

Copy link
Contributor

Choose a reason for hiding this comment

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

System is a package, which means we would have to lower it into the distribution to use it ourselves :(

@millenomi
Copy link
Contributor

@swift-ci please test

2 similar comments
@millenomi
Copy link
Contributor

@swift-ci please test

@MaxDesiatov
Copy link
Contributor

@swift-ci please test

@Gerzer
Copy link

Gerzer commented Feb 16, 2022

I understand that this pull request is holding up the implementation of the new concurrency APIs in URL and friends. Is there any update on when it might be merged and when work might begin on those new APIs? Is there any need for additional help with these implementations?

@@ -124,6 +124,7 @@ var allTestCases = [
testCase(TestUnitVolume.allTests),
testCase(TestNSLock.allTests),
testCase(TestNSSortDescriptor.allTests),
testCase(TestFileHandleAsync.allTests),
Copy link
Member

@YOCKOW YOCKOW Apr 13, 2022

Choose a reason for hiding this comment

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

(Let me leave a comment before the test logs would be gone.)
Build failure here:
error: invalid conversion from 'async' function of type '() async throws -> ()' to synchronous function type '() throws -> Void'

@waterskier2007
Copy link

waterskier2007 commented Apr 25, 2022

@YOCKOW so it looks like there just needs to be a utility function written to wrap an async test case since the current implementation only takes non-async functions. Is that correct?

@YOCKOW
Copy link
Member

YOCKOW commented Apr 27, 2022

Current implementation here https://github.com/apple/swift-corelibs-foundation/blob/a-sink-eye-oh/Tests/Foundation/Utilities.swift#L14

I think, unfortunately, no. It is used only when DARWIN_COMPATIBILITY_TESTS is defined.
A function testCase is implemented in XCTest, which is open source on Linux:
https://github.com/apple/swift-corelibs-xctest/blob/56501e765303ccac2f104a6e45cfcd6e733cc74e/Sources/XCTest/Public/XCTestCase.swift#L302

@waterskier2007
Copy link

waterskier2007 commented Apr 27, 2022

Alright, so then we need to PR an async version of testCase in XCTest and utilize that in this current PR?

@YOCKOW
Copy link
Member

YOCKOW commented Apr 29, 2022

Alright, so then we need to PR an async version of testCase in XCTest and utilize that in this current PR?

Or, we can use asyncTest.

@MPLew-is
Copy link

MPLew-is commented Jul 7, 2022

Is there anything that a novice community member like me can do to help land this? We're building Lambdas on AWS in Swift and would love to be able to get full AsyncBytes support.

@iCharlesHu
Copy link
Contributor

@swift-ci please test

@parkera
Copy link
Contributor

parkera commented Aug 9, 2022

Is there anything that a novice community member like me can do to help land this? We're building Lambdas on AWS in Swift and would love to be able to get full AsyncBytes support.

The Swift Async Algorithms package has an updated version of this as AsyncBufferedByteIterator.

@MPLew-is
Copy link

@parkera thanks for the link, that should help at least bridge the gap a little - however, it would still be incredibly nice to be able to land this Foundation version, especially for its integration with FileHandle. Right now, doing cross-platform async file I/O is painful since Linux is behind the Mac version.

Comment on lines +47 to +52
// this is not incredibly effecient but it is the best we have
guard let data = try handle.read(upToCount: buffer.count) else {
return 0
}
data.copyBytes(to: buffer)
return data.count

Choose a reason for hiding this comment

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

Is there a specific reason, handle.readabilityHandler isn't used here in conjunction with withUnsafeThrowingContinuation? Since this is still not part of Foundation on Linux, I wanted to include this code in my package for the moment and just wondered if it was better to use readabilityHandler because this function is blocking otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

readabilityHandler is less useful than you'd hope for regular files. They're just always readable.

Choose a reason for hiding this comment

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

But a FileHandle can also be the output of Process, and it may need to wait for new bytes. So the thread will be locked with read(upToCount:). I think readabilityHandler will be a better option that we can wrap into continuation

continue
case _LF..<_CR:
guard let result = yield() else {
continue
Copy link

Choose a reason for hiding this comment

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

Forgive me if I'm oversimplifying... there's a lot going on here. 😊 It looks like this completely removes empty lines, which seems suboptimal, given that...

  1. blank lines are meaningful in countless data applications, and
  2. it's easy enough to add your own isEmpty filter on the sequence if you really do want to strip them out.

Based on this, the default behavior should probably be to include empty lines (i.e., change continue to return "" in the _CR and _LF cases).

Copy link

Choose a reason for hiding this comment

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

If in doubt, please cross-check with Foundation's behavior. It needs to have the same semantics, else we widen the (already large) gap between APPLE and !APPLE.

Copy link

Choose a reason for hiding this comment

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

Ah, yeah, good point. This does match Foundation's behavior, so the issue would be against Apple, not this code. Thanks for the check!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.