6.55. kink/io/INPUT¶
Companion mod for input vals.
6.55.1. type input¶
`input` is an input port of bytes from the underlying source such as files.
An `input` provides sequential forward access to the underlying source. It does not provide random access operations such as seek.
6.55.1.1. Input.read(Max_size ...[$config={}])¶
`read` reads bytes from the stream. `read` blocks until one or more bytes are read, the end-of-file is detected, or an IO error occurs.
Config methods:
• C.on_success($success): default = VAL.identity
• C.on_eof($eof): default = fun which raises an exception
• C.on_error($error): default = fun which raises an exception
If one or more bytes are read, `read` tail-calls $success with a `bin` val of the bytes. The size of the `bin` val does not exceed `Max_size`.
If the end-of-file is detected, `read` tail-calls $eof with no arg.
If an IO error occurs, `read` tail-calls $error with an `exception`.
Preconditions
`Max_size` must be an int `num` which is bigger than or equal to 1.
$success must be a fun which takes a `bin`.
$eof must be a fun which takes no arg.
$error must be a fun which takes an `exception`.
Example
:BIN.require_from('kink/')
:BIN_INPUT.require_from('kink/io/')
:In <- BIN_INPUT.new(BIN.of(1 2 3))
:loop <- {(:Vec)
In.read(2){(:C)
C.on_success{(:Bin) loop(Vec + [Bin]) }
C.on_eof{ Vec }
}
}
:Result <- loop([])
stdout.print_line(Result.repr) # => [(bin 0x01 0x02) (bin 0x03)]
Example: IO error
:FILE.require_from('kink/io/')
:CONTROL.require_from('kink/')
:In <- FILE.open_to_read('/etc/passwd')
In.close
In.read(10){(:C)
C.on_error{(:Exc)
stderr.print_line(Exc.message)
}
}
# => already closed
In.read(10)
# Output:
# -- main exception
# [..root..]
# {..call by host..}
# ,,,
# {builtin:kink-mods/kink/EXCEPTION.kn L117 C13 current_traces} { TRACE.-->current_traces }
# already closed
6.55.1.2. Input.read_all(...[$config={}])¶
`read_all` reads bytes until it reaches the end-of-file, or an IO error occurs.
Config methods:
• C.on_success($success): default = VAL.identity
• C.on_error($error): default = {(:Exc) Exc.raise }
If one or more bytes are read with no IO error, `read_all` tail-calls $success with a `bin` of the bytes.
If no byte is read, `read_all` tail-calls $success with an empty `bin`.
If an IO error occurs, `read_all` tail-calls $error with an `exception`.
Precondition
$success must be a fun which takes a `bin`
$error must be a fun which takes an `exception`
Example
:BIN.require_from('kink/')
:BIN_INPUT.require_from('kink/io/')
:INPUT.require_from('kink/io/')
:In <- BIN_INPUT.new(BIN.of(1 2 3))
stdout.print_line(In.read_all.repr) # => (bin 0x01 0x02 0x03)
stdout.print_line(In.read_all.repr) # => (bin)
stdout.print_line(In.read_all.repr) # => (bin)
See also
INPUT.mixin: it provides a generic implementation of `read_all`.
6.55.1.3. Input.close(...[$config={}])¶
`close` closes the resource of the underlying source of bytes.
Config methods:
• C.on_success($success): default = {}
• C.on_error($error): default = a fun which raises an exception
If the resource is closed with no error, `close` tail-calls $success with no arg.
If an IO error occurs, `close` tail-calls $error with an `exception`.
Preconditions
$success must be a fun which takes no arg
$error must be a fun which takes an `exception`
6.55.2. INPUT.is?(Val)¶
`is?` returns whether `Val` is an `input`.
6.55.3. INPUT.mixin¶
``mixin`` returns a mixin trait which provides an implementation of Input.read_all. `read_all` will be implemented using `read` method.
Example
:CONTROL.require_from('kink/')
:INPUT.require_from('kink/io/')
:FILE.require_from('kink/io/')
:Trait <- [
... INPUT.mixin
'read' {[:In](:Args.rest)
stderr.print_line('Called: read')
In.Wrapped.read(... Args)
}
'close' {[:In](:Args.rest)
stderr.print_line('Called: close')
In.Wrapped.close(... Args)
}
]
:new_logging_input <- {(:Wrapped)
new_val(
... Trait
'Wrapped' Wrapped
)
}
:main <- {
:Bin = CONTROL.with_finally{(:finally)
:In = new_logging_input(FILE.open_to_read('/etc/passwd'))
finally{ In.close }
In.read_all
}
stdout.write(Bin)
}
# Output:
# Called: read
# Called: read
# Called: close
# root:x:0:0:root:/root:/bin/bash
# daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# bin:x:2:2:bin:/bin:/usr/sbin/nologin
# sys:x:3:3:sys:/dev:/usr/sbin/nologin
# ,,,