Skip to content

Commit

Permalink
interp: Move *CtxWriter to ioextra, some comments cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Nov 5, 2021
1 parent ff2077b commit 6cacc9b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 38 deletions.
28 changes: 28 additions & 0 deletions internal/ioextra/ioextra.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ioextra

import (
"context"
"errors"
"io"
)
Expand All @@ -26,3 +27,30 @@ type ReadErrSeeker struct{ io.Reader }
func (r *ReadErrSeeker) Seek(offset int64, whence int) (int64, error) {
return 0, errors.New("seek")
}

type CtxWriter struct {
io.Writer
Ctx context.Context
}

func (o CtxWriter) Write(p []byte) (n int, err error) {
if o.Ctx != nil {
if err := o.Ctx.Err(); err != nil {
return 0, err
}
}
return o.Writer.Write(p)
}

type DiscardCtxWriter struct {
Ctx context.Context
}

func (o DiscardCtxWriter) Write(p []byte) (n int, err error) {
if o.Ctx != nil {
if err := o.Ctx.Err(); err != nil {
return 0, err
}
}
return n, nil
}
7 changes: 4 additions & 3 deletions internal/ioextra/runereader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"unicode/utf8"
)

// ByteRuneReader reads each by as a runes from a io.ReadSeeker
// ex: when used with regexp \u00ff code point will match byte 0xff and not the utf-8 encoded version of 0xff
// ByteRuneReader reads each byte as a rune from a io.ReadSeeker
// ex: when used with regexp \u00ff code point will match byte 0xff and not the
// utf-8 encoded version of 0xff
type ByteRuneReader struct {
RS io.ReadSeeker
}
Expand Down Expand Up @@ -46,7 +47,7 @@ func utf8Bytes(b byte) int {
}
}

// RuneReadSeeker reads runs from a io.ReadSeeker
// RuneReadSeeker reads rune from a io.ReadSeeker
func (brr RuneReadSeeker) ReadRune() (r rune, size int, err error) {
var b [utf8.UTFMax]byte

Expand Down
17 changes: 13 additions & 4 deletions pkg/interp/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,13 @@ func (i *Interp) readline(c interface{}, a []interface{}) interface{} {
}

names, shared, err := func() (newLine []string, shared int, err error) {
// c | opts.Complete(line; pos)
vs, err := i.EvalFuncValues(
completeCtx, c, opts.Complete, []interface{}{line, pos}, DiscardCtxWriter{Ctx: completeCtx},
completeCtx,
c,
opts.Complete,
[]interface{}{line, pos},
ioextra.DiscardCtxWriter{Ctx: completeCtx},
)
if err != nil {
return nil, pos, err
Expand Down Expand Up @@ -519,7 +524,10 @@ func (i *Interp) _open(c interface{}, a []interface{}) interface{} {
return err
}

// TODO: ctxreadseeker might leak
// ctxreadseeker is used to make sure any io calls can be canceled
// TODO: ctxreadseeker might leak if the underlaying call hangs forever

// a regular file should be seekable but fallback below to read whole file if not
if fFI.Mode().IsRegular() {
if rs, ok := f.(io.ReadSeeker); ok {
fRS = ctxreadseeker.New(i.evalContext.ctx, rs)
Expand Down Expand Up @@ -554,7 +562,7 @@ func (i *Interp) _open(c interface{}, a []interface{}) interface{} {
const cacheReadAheadSize = 512 * 1024
aheadRs := aheadreadseeker.New(fRS, cacheReadAheadSize)

// bb -> aheadreadseeker -> progressreadseeker -> ctxreadseeker -> readerseeker
// bitio.Buffer -> aheadreadseeker -> progressreadseeker -> ctxreadseeker -> readseeker

bbf.bb, err = bitio.NewBufferFromReadSeeker(aheadRs)
if err != nil {
Expand All @@ -581,12 +589,13 @@ func (i *Interp) _decode(c interface{}, a []interface{}) interface{} {

if opts.Progress != "" {
evalProgress := func(c interface{}) {
// {approx_read_bytes: 123, total_size: 123} | opts.Progress
_, _ = i.EvalFuncValues(
i.evalContext.ctx,
c,
opts.Progress,
nil,
DiscardCtxWriter{Ctx: i.evalContext.ctx},
ioextra.DiscardCtxWriter{Ctx: i.evalContext.ctx},
)
}
bbf.progressFn = func(approxReadBytes, totalSize int64) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/interp/internal.jq
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def _eval_compile_error_tostring:
"\(.filename // "src"):\(.line):\(.column): \(.error)";
def _eval($expr; $filename; f; on_error; on_compile_error):
try
eval($expr; $filename) | f
eval($expr; $filename) | f
catch
if _eval_is_compile_error then on_compile_error
else on_error
Expand Down
33 changes: 3 additions & 30 deletions pkg/interp/interp.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/wader/fq/internal/ansi"
"github.com/wader/fq/internal/colorjson"
"github.com/wader/fq/internal/ctxstack"
"github.com/wader/fq/internal/ioextra"
"github.com/wader/fq/internal/num"
"github.com/wader/fq/internal/pos"
"github.com/wader/fq/pkg/bitio"
Expand Down Expand Up @@ -110,7 +111,7 @@ type OS interface {
Args() []string
Environ() []string
ConfigDir() (string, error)
// returned Open() io.ReadSeeker can optionally implement io.Closer
// FS.File returned by FS().Open() can optionally implement io.Seeker
FS() fs.FS
Readline(prompt string, complete func(line string, pos int) (newLine []string, shared int)) (string, error)
History() ([]string, error)
Expand Down Expand Up @@ -141,34 +142,6 @@ func (rf FileReader) Stat() (fs.FileInfo, error) { return rf.FileInfo, nil }
func (rf FileReader) Read(p []byte) (int, error) { return rf.R.Read(p) }
func (FileReader) Close() error { return nil }

// TODO: move
type DiscardCtxWriter struct {
Ctx context.Context
}

func (o DiscardCtxWriter) Write(p []byte) (n int, err error) {
if o.Ctx != nil {
if err := o.Ctx.Err(); err != nil {
return 0, err
}
}
return n, nil
}

type CtxWriter struct {
io.Writer
Ctx context.Context
}

func (o CtxWriter) Write(p []byte) (n int, err error) {
if o.Ctx != nil {
if err := o.Ctx.Err(); err != nil {
return 0, err
}
}
return o.Writer.Write(p)
}

type Value interface {
gojq.JQValue

Expand Down Expand Up @@ -711,7 +684,7 @@ func (i *Interp) Eval(ctx context.Context, c interface{}, src string, srcFilenam

runCtx, runCtxCancelFn := i.interruptStack.Push(ctx)
ni.evalContext.ctx = runCtx
ni.evalContext.output = CtxWriter{Writer: output, Ctx: runCtx}
ni.evalContext.output = ioextra.CtxWriter{Writer: output, Ctx: runCtx}
iter := gc.RunWithContext(runCtx, c, variableValues...)

iterWrapper := iterFn(func() (interface{}, bool) {
Expand Down

0 comments on commit 6cacc9b

Please sign in to comment.