-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
added docs for IO interface #41291
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
base: master
Are you sure you want to change the base?
added docs for IO interface #41291
Changes from all commits
eeb82f6
7126a22
3526ea6
eb8ca17
ca0630a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -737,6 +737,69 @@ yields a `SparseMatStyle`, and anything of higher dimensionality falls back to t | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| These rules allow broadcasting to keep the sparse representation for operations that result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| in one or two dimensional outputs, but produce an `Array` for any other dimensionality. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## [IO Stream](@id man-interface-iostream) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Required methods | Brief description | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |:----------------------------------------- |:----------------------------------------------------------------------------------------------- | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `unsafe_read(io, ::Ptr{UInt8}, ::UInt)` | Copy bytes from the `IO` to a pointer. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `unsafe_write(io, ::Ptr{UInt8}, ::UInt)` | Copy bytes from a pointer to the `IO`. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `eof(io)` | Whether the IO stream is at the end. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Optional methods | Brief description | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |:----------------------------------------- |:----------------------------------------------------------------------------------------------- | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `read(io, ::Type{UInt8})` | Read a byte from the stream. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `write(io, ::UInt8)` | Write a byte to the stream. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `close(io)` | Close the stream. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `seek(io, ::Integer)` | Seek to a specific position. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `position(io)` | Return the current position of the stream. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `seekstart(io)` | Seek to beginning of stream. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `seekend(io)` | Seek to the end of the stream. | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+748
to
+756
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| To implement an `IO` object it is required to define the low-level methods `unsafe_read` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| and `unsafe_write` which enable copying of data between the `IO` and a location given by a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pointer. Additionally, `eof` is required and should return `true` if reading from the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `IO` is valid, else `false`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+759
to
+762
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| An `IO` that only defines `unsafe_read`, `unsafe_write` and `eof` can have most `isbits` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| types written or read to or from it, but the `read(io, ::Type{UInt8})` and `write(io, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ::UInt8)` methods must be defined to enable reading and writing individual bytes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the ordering of thoughts here is a bit is a bit confusing, but also I am not very familiar with the IO interface (and am grateful that you're documenting it!) My expectation from reading this is that But perhaps more importantly, this doesn't exactly match the exploration I just did, which tl;dr suggests that it could be okay to just define To probe the system: julia> struct MyIO <: IO
end
julia> write(MyIO(), 1 + 2*im)
ERROR: MyIO does not support byte I/O
Stacktrace:
[1] error(::Type, ::String)
@ Base ./error.jl:42
[2] write(s::MyIO, x::UInt8)
@ Base ./io.jl:224
[3] unsafe_write
@ ./io.jl:238 [inlined]
[4] unsafe_write
@ ./io.jl:646 [inlined]
[5] unsafe_write(s::MyIO, p::Base.RefValue{Int64}, n::Int64)
@ Base ./io.jl:644
[6] write
@ ./io.jl:647 [inlined]
[7] write
@ ./io.jl:650 [inlined]
[8] write
@ ./io.jl:637 [inlined]
[9] write(s::MyIO, z::Complex{Int64})
@ Base ./complex.jl:221
[10] top-level scope
@ REPL[11]:1The stacktrace is a bit uninformative, but here is the sequence that I can tell.
So in this case it would be sufficient to just define I thought I might get a bit more understanding by looking to see some of those definitions of julia> _fieldtype(x, i) = try
fieldtypes(x)[i]
catch
missing
end
_fieldtype (generic function with 1 method)
julia> filter(m -> _fieldtype(m.sig, 3) === UInt8, methods(write).ms)
[1] write(io::Union{Core.CoreSTDERR, Core.CoreSTDOUT}, x::UInt8) in Base at coreio.jl:26
[2] write(to::Base.GenericIOBuffer, a::UInt8) in Base at iobuffer.jl:445
[3] write(io::Base.AbstractPipe, byte::UInt8) in Base at io.jl:360
[4] write(pipe::Base64.Base64EncodePipe, x::UInt8) in Base64 at /Applications/Julia-1.6.app/Contents/Resources/julia/share/julia/stdlib/v1.6/Base64/src/encode.jl:101
[5] write(io::Base.SecretBuffer, b::UInt8) in Base at secretbuffer.jl:112
[6] write(s::Base.BufferStream, b::UInt8) in Base at stream.jl:1351
[7] write(s::Base.LibuvStream, b::UInt8) in Base at stream.jl:1091
[8] write(s::IOStream, b::UInt8) in Base at iostream.jl:366
[9] write(::Base.DevNull, ::UInt8) in Base at coreio.jl:16
[10] write(f::Base.Filesystem.File, c::UInt8) in Base.Filesystem at filesystem.jl:136
[11] write(s::IO, x::UInt8) in Base at io.jl:224There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be honest, I find your wording much more confusing than mine, maybe somebody else wants to come along and suggest a 3rd alternative? (I'm not attached to my original wording, I'm just unsure what to change.) As far as defining only
Comment on lines
+764
to
+766
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Methods which affect the mutable state of the `IO` stream such as `close` and `seek` are | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| optional. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+768
to
+769
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Example | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The below example implements an `IO` "recorder" which writes all data read from it to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| an extra buffer. It defines `read` and `write` methods for `UInt8`, so it supports | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reading and writing of any object which can be written or read from an `IOBuffer`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```julia | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct IORecorder{ℐ<:IO} <: IO | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| io::ℐ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r::IOBuffer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IORecorder(io::IO) = IORecorder{typeof(io)}(io, IOBuffer()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function Base.read(io::IORecorder, ::Type{UInt8}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| x = read(io.io, UInt8) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| write(io.r, x) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| x | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function Base.unsafe_read(io::IORecorder, p::Ptr{UInt8}, n::UInt) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i ∈ 1:n | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| x = read(io, UInt8) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unsafe_store!(p, x, i) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nothing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+788
to
+794
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe this is necessary
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Base.write(io::IORecorder, x::UInt8) = write(io.io, x) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Base.unsafe_write(io::IORecorder, p::Ptr{UInt8}, n::UInt) = unsafe_write(io.io, p, n) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Base.eof(io::IORecorder) = eof(io.io) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Base.close(io::IORecorder) = (close(io.io); close(io.r); io) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ======= | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## [Instance Properties](@id man-instance-properties) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Methods to implement | Default definition | Brief description | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -882,5 +945,4 @@ julia> ceil(x) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Interval{Float64}(2.0, 3.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| julia> trunc(x) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Interval{Float64}(1.0, 2.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Interval{Float64}(1.0, 2.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wait... I'm very confused, I tested with only
readandwriteand it didn't work, that's why I have theunsafe_methods (obviously being able to usereadandwriteis vastly preferable. Am I missing something here? If you are convinced this should work, I can probably figure out a MWE and show you.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably doesn't get much testing currently, but your
IORecordertype seems like a candidate to also run as a test (or doctest)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that sounds good, but what about
unsafe_readandunsafe_write? Like I said, it didnt' work for me, but all your comments suggest that it should.Btw, if I'm right and it doesn't work, it really should, but it seems unlikely we'd be able to fix this until 2.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested with
IORecorder(stdin), and it worked