Skip to content

Commit

Permalink
Merge pull request #4901 from asterite/feature/io-as-class
Browse files Browse the repository at this point in the history
Make IO a class
  • Loading branch information
asterite authored Oct 14, 2017
2 parents e8d9019 + 3fc150d commit bc412dc
Show file tree
Hide file tree
Showing 37 changed files with 355 additions and 358 deletions.
2 changes: 1 addition & 1 deletion samples/conway.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct ANSI
end
end

module IO
class IO
def ansi
ANSI.new self
end
Expand Down
10 changes: 5 additions & 5 deletions spec/compiler/codegen/module_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -318,19 +318,19 @@ describe "Code gen: module" do
end
end
module IO2
module Moo
end
module IO2::Sub
include IO2
module Moo::Sub
include Moo
end
class File2
include IO2::Sub
include Moo::Sub
end
file = File2.new
file2 = file.as(IO2)
file2 = file.as(Moo)
file.method(file2)
)).to_i.should eq(1)
Expand Down
4 changes: 1 addition & 3 deletions spec/std/file_utils_spec.cr
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
require "spec"
require "file_utils"

private class OneByOneIO
include IO

private class OneByOneIO < IO
@bytes : Bytes

def initialize(string)
Expand Down
8 changes: 2 additions & 6 deletions spec/std/http/server/server_spec.cr
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
require "spec"
require "http/server"

private class RaiseErrno
private class RaiseErrno < IO
def initialize(@value : Int32)
end

include IO

def read(slice : Bytes)
Errno.value = @value
raise Errno.new "..."
Expand All @@ -17,9 +15,7 @@ private class RaiseErrno
end
end

private class ReverseResponseOutput
include IO

private class ReverseResponseOutput < IO
@output : IO

def initialize(@output : IO)
Expand Down
2 changes: 1 addition & 1 deletion spec/std/io/buffered_spec.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "spec"

private class BufferedWrapper
private class BufferedWrapper < IO
include IO::Buffered

getter called_unbuffered_read
Expand Down
4 changes: 1 addition & 3 deletions spec/std/io/delimited_spec.cr
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
require "spec"

private class PartialReaderIO
include IO

private class PartialReaderIO < IO
@slice : Bytes

def initialize(data : String)
Expand Down
4 changes: 1 addition & 3 deletions spec/std/io/io_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ require "base64"
# This is a non-optimized version of IO::Memory so we can test
# raw IO. Optimizations for specific IOs are tested separately
# (for example in buffered_io_spec)
private class SimpleIOMemory
include IO

private class SimpleIOMemory < IO
getter buffer : UInt8*
getter bytesize : Int32
@capacity : Int32
Expand Down
4 changes: 1 addition & 3 deletions spec/std/io/sized_spec.cr
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
require "spec"

private class NoPeekIO
include IO

private class NoPeekIO < IO
def read(bytes : Bytes)
0
end
Expand Down
2 changes: 1 addition & 1 deletion src/file/preader.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# :nodoc:
class File::PReader
class File::PReader < IO
include IO::Buffered

getter? closed = false
Expand Down
4 changes: 1 addition & 3 deletions src/flate/reader.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
# Instances of this class wrap another IO object. When you read from this instance
# instance, it reads data from the underlying IO, decompresses it, and returns
# it to the caller.
class Flate::Reader
include IO

class Flate::Reader < IO
# If `#sync_close?` is `true`, closing this IO will close the underlying IO.
property? sync_close : Bool

Expand Down
4 changes: 1 addition & 3 deletions src/flate/writer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
#
# NOTE: unless created with a block, `close` must be invoked after all
# data has been written to a Flate::Writer instance.
class Flate::Writer
include IO

class Flate::Writer < IO
# If `#sync_close?` is `true`, closing this IO will close the underlying IO.
property? sync_close : Bool

Expand Down
4 changes: 1 addition & 3 deletions src/gzip/reader.cr
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@
# end
# string # => "abc"
# ```
class Gzip::Reader
include IO

class Gzip::Reader < IO
# Whether to close the enclosed `IO` when closing this reader.
property? sync_close = false

Expand Down
4 changes: 1 addition & 3 deletions src/gzip/writer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
# end
# end
# ```
class Gzip::Writer
include IO

class Gzip::Writer < IO
# Whether to close the enclosed `IO` when closing this writer.
property? sync_close = false

Expand Down
6 changes: 2 additions & 4 deletions src/http/content.cr
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ module HTTP
end

# :nodoc:
class UnknownLengthContent
include IO
class UnknownLengthContent < IO
include Content

def initialize(@io : IO)
Expand Down Expand Up @@ -46,8 +45,7 @@ module HTTP
end

# :nodoc:
class ChunkedContent
include IO
class ChunkedContent < IO
include Content
@chunk_remaining : Int32

Expand Down
6 changes: 2 additions & 4 deletions src/http/server/response.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ class HTTP::Server
# are written and the connection `IO` (a socket) is yielded to the given block.
# The block must invoke `close` afterwards, the server won't do it in this case.
# This is useful to implement protocol upgrades, such as websockets.
class Response
include IO

class Response < IO
# The response headers (`HTTP::Headers`). These must be set before writing to the response.
getter headers : HTTP::Headers

Expand Down Expand Up @@ -136,7 +134,7 @@ class HTTP::Server
end

# :nodoc:
class Output
class Output < IO
include IO::Buffered

property! response : Response
Expand Down
4 changes: 1 addition & 3 deletions src/http/web_socket/protocol.cr
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ class HTTP::WebSocket::Protocol
@masked = !!masked
end

class StreamIO
include IO

class StreamIO < IO
def initialize(@websocket : Protocol, binary, frame_size)
@opcode = binary ? Opcode::BINARY : Opcode::TEXT
@buffer = Bytes.new(frame_size)
Expand Down
79 changes: 73 additions & 6 deletions src/io.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ require "c/sys/wait"
require "c/errno"
require "c/unistd"

# The `IO` module is the basis for all input and output in Crystal.
# The `IO` class is the basis for all input and output in Crystal.
#
# This module is included by types like `File`, `Socket` and `IO::Memory` and
# This class is inherited by types like `File`, `Socket` and `IO::Memory` and
# provide many useful methods for reading to and writing from an IO, like `print`, `puts`,
# `gets` and `printf`.
#
Expand All @@ -20,9 +20,7 @@ require "c/unistd"
# For example, this is a simple `IO` on top of a `Bytes`:
#
# ```
# class SimpleSliceIO
# include IO
#
# class SimpleSliceIO < IO
# def initialize(@slice : Bytes)
# end
#
Expand Down Expand Up @@ -61,7 +59,7 @@ require "c/unistd"
# Mixing string and byte operations might not give correct results and should be
# avoided, as string operations might need to read extra bytes in order to get characters
# in the given encoding.
module IO
abstract class IO
# Argument to a `seek` operation.
enum Seek
# Seeks to an absolute location
Expand Down Expand Up @@ -1048,6 +1046,75 @@ module IO
@encoding.try(&.name) || "UTF-8"
end

# Seeks to a given *offset* (in bytes) according to the *whence* argument.
#
# The `IO` class raises on this method, but some subclasses, notable
# `IO::FileDescriptor` and `IO::Memory` implement it.
#
# Returns `self`.
#
# ```
# File.write("testfile", "abc")
#
# file = File.new("testfile")
# file.gets(3) # => "abc"
# file.seek(1, IO::Seek::Set)
# file.gets(2) # => "bc"
# file.seek(-1, IO::Seek::Current)
# file.gets(1) # => "c"
# ```
def seek(offset, whence : Seek = Seek::Set)
raise Error.new "Unable to seek"
end

# Returns the current position (in bytes) in this `IO`.
#
# The `IO` class raises on this method, but some subclasses, notable
# `IO::FileDescriptor` and `IO::Memory` implement it.
#
# ```
# File.write("testfile", "hello")
#
# file = File.new("testfile")
# file.pos # => 0
# file.gets(2) # => "he"
# file.pos # => 2
# ```
def pos
raise Error.new "Unable to pos"
end

# Sets the current position (in bytes) in this `IO`.
#
# The `IO` class raises on this method, but some subclasses, notable
# `IO::FileDescriptor` and `IO::Memory` implement it.
#
# ```
# File.write("testfile", "hello")
#
# file = File.new("testfile")
# file.pos = 3
# file.gets_to_end # => "lo"
# ```
def pos=(value)
raise Error.new "Unable to pos="
end

# Same as `pos`.
def tell
pos
end

# Yields an `IO` to read a section inside this IO.
#
# The `IO` class raises on this method, but some subclasses, notable
# `File` and `IO::Memory` implement it.
#
# Mutliple sections can be read concurrently.
def read_at(offset, bytesize, &block)
raise Error.new "Unable to read_at"
end

# Copy all contents from *src* to *dst*.
#
# ```
Expand Down
4 changes: 1 addition & 3 deletions src/io/argf.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# :nodoc:
class IO::ARGF
include IO

class IO::ARGF < IO
@path : String?
@current_io : IO?

Expand Down
4 changes: 1 addition & 3 deletions src/io/buffered.cr
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# The `IO::Buffered` mixin enhances the `IO` module with input/output buffering.
# The `IO::Buffered` mixin enhances an `IO` with input/output buffering.
#
# The buffering behaviour can be turned on/off with the `#sync=` method.
#
# Additionally, several methods, like `#gets`, are implemented in a more
# efficient way.
module IO::Buffered
include IO

BUFFER_SIZE = 8192

@in_buffer_rem = Bytes.empty
Expand Down
2 changes: 1 addition & 1 deletion src/io/console.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require "termios"

class IO::FileDescriptor
class IO::FileDescriptor < IO
# Turn off character echoing for the duration of the given block.
# This will prevent displaying back to the user what they enter on the terminal.
# Only call this when this IO is a TTY, such as a not redirected stdin.
Expand Down
Loading

0 comments on commit bc412dc

Please sign in to comment.