sio

package module
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 3, 2026 License: MIT Imports: 16 Imported by: 0

README ΒΆ

sio

Go Version License Go Report Card

Stream I/O made simple. Zero surprises, predictable memory, automatic cleanup.

sio is a Go library that brings sanity to file processing. Whether you're handling uploads from HTTP requests, processing files from disk, fetching content from URLs, or working with in-memory dataβ€”sio gives you a unified interface with predictable resource usage and automatic cleanup.

Table of Contents


Why sio?

The Problem:

When building production services that process files, you face a maze of decisions:

  • Where do temporary files go? Who cleans them up?
  • How do I avoid memory explosions on large uploads?
  • How do I handle files, bytes, URLs, and multipart uploads consistently?
  • How do I prevent resource leaks when errors occur?

The Solution:

sio provides a simple, composable API that handles all of this for you:

// Process a file upload with automatic cleanup
output, err := sio.Process(ctx,
    sio.NewMultipartReader(fileHeader),
    sio.Out(sio.Pdf),
    func(ctx context.Context, r io.Reader, w io.Writer) error {
        // Your processing logic here
        return processDocument(r, w)
    },
)
// Temp files cleaned up automatically when session ends

Key Features

πŸ”„ Unified Interface

Work with files, bytes, URLs, and multipart uploads through a single StreamReader interface. No more switching between different APIs.

πŸ’Ύ Flexible Storage

Choose between disk-backed or in-memory storage. Need speed? Use memory. Processing large files? Use disk. Mix and match per operation.

🧹 Automatic Cleanup

Temporary files are tracked and cleaned up automatically. No more leaked temp files filling up your disk.

πŸ“Š Predictable Memory

Control exactly how your data flows. Stream large files without loading everything into memory.

⚑ Production Ready

Built for real-world use: handles errors gracefully, supports concurrent sessions, and integrates seamlessly with popular frameworks.


Quick Start

Installation
go get github.com/dreamph/sio
Basic Example
package main

import (
    "context"
    "fmt"
    "io"
    "log"
    "path/filepath"

    "github.com/dreamph/sio"
)

func main() {
    ctx := context.Background()

    // Create a manager (handles temp directory)
    ioManager, _ := sio.NewIoManager(filepath.Join(sio.DefaultBaseTempDir, "myapp"))
    defer ioManager.Cleanup()

    // Create a session (isolated workspace)
    ses, _ := ioManager.NewSession()
    defer ses.Cleanup()

    ctx = sio.WithSession(ctx, ses)

    // Process data from any source
    src := sio.NewBytesReader([]byte("hello world"))
    output, err := sio.Process(ctx, src, sio.Out(sio.Text),
        func(ctx context.Context, r io.Reader, w io.Writer) error {
            _, err := io.Copy(w, r)
            return err
        },
    )

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Output: %s\n", output.Path())
}

Real-World Example: HTTP File Upload

Here's how to handle file uploads in a web server with automatic cleanup:

app.Post("/convert", func(c *fiber.Ctx) error {
    // Get uploaded file
    fileHeader, err := c.FormFile("document")
    if err != nil {
        return fiber.NewError(fiber.StatusBadRequest, "missing file")
    }

    // Create isolated session for this request
    ses, _ := ioManager.NewSession()
    defer ses.Cleanup() // Auto-cleanup when request ends

    ctx := sio.WithSession(c.UserContext(), ses)

    // Process the upload
    output, err := sio.Process(ctx,
        sio.NewMultipartReader(fileHeader),
        sio.Out(sio.Pdf),
        func(ctx context.Context, r io.Reader, w io.Writer) error {
            // Your conversion logic
            return convertToPDF(r, w)
        },
    )

    if err != nil {
        return err
    }

    // Stream result back to client
    reader, _ := sio.NewDownloadReaderCloser(output.Reader())
    c.Set("Content-Type", "application/pdf")
    return c.SendStream(reader)
})

See the full example: example/main.go


Common Use Cases

πŸ“€ Process File Uploads
src := sio.NewMultipartReader(fileHeader)
output, _ := sio.Process(ctx, src, sio.Out(sio.Jpg), processImage)
🌐 Fetch and Process URLs
src := sio.NewURLReader("https://example.com/data.csv")
output, _ := sio.Process(ctx, src, sio.Out(sio.Xlsx), convertToExcel)
πŸ’Ύ Transform Local Files
src := sio.NewFileReader("/path/to/input.txt")
output, _ := sio.Process(ctx, src, sio.Out(sio.Pdf), generatePDF)
🧠 Work with In-Memory Data
src := sio.NewBytesReader(data)
output, _ := sio.Process(ctx, src, sio.Out(sio.Zip), compress)
⚑ Force Memory Storage for Speed
// Process small files entirely in memory for max performance
output, _ := sio.Process(ctx, src,
    sio.Out(sio.Json, sio.Memory), // Force in-memory storage
    transform,
)

API Overview

Core Components
Component Purpose
Manager Manages the root temp directory and creates isolated sessions
Session Isolated workspace for processing streams with automatic cleanup
StreamReader Unified interface for files, bytes, URLs, and multipart uploads
Output Result of a processing operationβ€”can be read, saved, or streamed
Storage Modes
// Disk-backed (default) - for large files
ioManager, _ := sio.NewIoManager("/tmp/myapp", sio.File)

// Memory-only - for small, fast operations
ioManager, _ := sio.NewIoManager("", sio.Memory)

// Override per operation
output, _ := sio.Process(ctx, src,
    sio.Out(sio.Pdf, sio.Memory), // Force memory for this output
    process,
)
Common Patterns

Read without creating output:

err := sio.Read(ctx, src, func(ctx context.Context, r io.Reader) error {
    // Just read, no output file created
    return processStream(r)
})

Process multiple inputs:

sources := []sio.StreamReader{
    sio.NewFileReader("file1.txt"),
    sio.NewFileReader("file2.txt"),
}
output, _ := sio.ProcessList(ctx, sources, sio.Out(sio.Zip), mergeFiles)

Save output permanently:

output, _ := sio.Process(ctx, src, sio.Out(sio.Pdf), convert)
output.SaveAs("/permanent/location/result.pdf")

Keep output beyond session cleanup:

output, _ := sio.Process(ctx, src, sio.Out(sio.Pdf), convert)
output.Keep() // Won't be deleted when session.Cleanup() runs

Advanced Features

Stream from URLs with Options
src := sio.NewURLReader("https://api.example.com/data",
    sio.URLReaderOptions{}.
        WithTimeout(60 * time.Second).
        WithInsecureTLS(true),
)
Read Line by Line
err := sio.ReadLines(ctx, src, func(line string) error {
    // Process each line
    return handleLine(line)
})
Convert to ReaderAt
result, _ := output.AsReaderAt(ctx,
    sio.WithMaxMemoryBytes(10 << 20), // Keep up to 10MB in memory
)
defer result.Cleanup()
// Use result.ReaderAt() with libraries that need random access
Bind Multiple Streams
output, _ := sio.BindProcess(ctx, sio.Out(sio.Zip),
    func(ctx context.Context, b *sio.Binder, w io.Writer) error {
        file1, _ := b.Use(sio.NewFileReader("doc1.txt"))
        file2, _ := b.Use(sio.NewFileReader("doc2.txt"))
        return createZip(w, file1, file2)
    },
)

Best Practices

Always Use defer for Cleanup
// Manager cleanup
ioManager, _ := sio.NewIoManager("/tmp/myapp")
defer ioManager.Cleanup() // Always defer!

// Session cleanup
ses, _ := ioManager.NewSession()
defer ses.Cleanup() // Clean up after each request
Handle Errors Properly
output, err := sio.Process(ctx, src, sio.Out(sio.Pdf), convert)
if err != nil {
    // Error already triggered cleanup
    return fmt.Errorf("processing failed: %w", err)
}
// Output is valid and can be used
Choose the Right Storage Mode
// Small files (< 10MB) - use Memory for speed
output, _ := sio.Process(ctx, src,
    sio.Out(sio.Json, sio.Memory),
    processSmall,
)

// Large files (> 10MB) - use File to avoid memory pressure
output, _ := sio.Process(ctx, src,
    sio.Out(sio.Pdf, sio.File),
    processLarge,
)
One Session Per Request
// Good: Each HTTP request gets its own session
app.Post("/upload", func(c *fiber.Ctx) error {
    ses, _ := ioManager.NewSession()
    defer ses.Cleanup()

    ctx := sio.WithSession(c.UserContext(), ses)
    // Process files...
})

// Bad: Reusing session across requests
var globalSession sio.IoSession // DON'T DO THIS
Use Keep() or SaveAs() for Persistent Files
// Temporary processing - auto cleanup
output, _ := sio.Process(ctx, src, sio.Out(sio.ToExt("tmp")), process)
// File deleted when session.Cleanup() runs

// Keep for later use
output, _ := sio.Process(ctx, src, sio.Out(sio.Pdf), process)
output.Keep() // Won't be deleted

// Save to permanent location
output, _ := sio.Process(ctx, src, sio.Out(sio.Pdf), process)
output.SaveAs("/permanent/files/result.pdf")

Performance Tips

Memory vs Disk Trade-offs
// Fast but uses memory - good for small files
ioManager, _ := sio.NewIoManager("", sio.Memory)

// Slower but handles unlimited size - good for large files
ioManager, _ := sio.NewIoManager("/tmp/myapp", sio.File)

// Best of both: Default to disk, override for small operations
ioManager, _ := sio.NewIoManager("/tmp/myapp", sio.File)
// Use Memory for specific small operations
output, _ := sio.Process(ctx, src, sio.Out(sio.Json, sio.Memory), fn)
Streaming for Large Files
// Don't load entire file into memory
err := sio.Read(ctx, src, func(ctx context.Context, r io.Reader) error {
    // Process in chunks
    scanner := bufio.NewScanner(r)
    for scanner.Scan() {
        processLine(scanner.Text())
    }
    return scanner.Err()
})
Reuse Managers
// Good: Create once, reuse for all requests
var ioManager sio.IoManager

func init() {
    ioManager, _ = sio.NewIoManager("/tmp/myapp")
}

// Bad: Creating manager per request
func handler() {
    mgr, _ := sio.NewIoManager("/tmp/myapp") // Expensive!
}
URL Downloads with Timeouts
// Set appropriate timeouts for external resources
src := sio.NewURLReader("https://slow-api.com/data",
    sio.URLReaderOptions{}.
        WithTimeout(60 * time.Second), // Prevent hanging
)
Concurrent Processing
// Safe: Each goroutine gets its own session
var wg sync.WaitGroup
for _, file := range files {
    wg.Add(1)
    go func(f string) {
        defer wg.Done()

        ses, _ := ioManager.NewSession() // Isolated session
        defer ses.Cleanup()

        ctx := sio.WithSession(context.Background(), ses)
        sio.Process(ctx, sio.NewFileReader(f), sio.Out(sio.Pdf), convert)
    }(file)
}
wg.Wait()

FAQ

How do I process files larger than available RAM?

Use file-based storage (default) and stream the data:

ioManager, _ := sio.NewIoManager("/tmp/myapp", sio.File)
// Files are written to disk, not loaded into memory
Is sio safe for concurrent use?

Yes! Each session is isolated. Just create a new session per request/goroutine:

// Thread-safe: Each goroutine gets its own session
ses, _ := ioManager.NewSession()
defer ses.Cleanup()
What happens if I forget to call Cleanup()?

Temporary files will remain on disk until the program exits or the OS cleans them up. Always use defer:

ses, _ := ioManager.NewSession()
defer ses.Cleanup() // Always!
Can I mix file and memory storage?

Yes! You can override storage per operation:

ioManager, _ := sio.NewIoManager("/tmp/myapp", sio.File)

// This operation uses memory
output1, _ := sio.Process(ctx, src, sio.Out(sio.Json, sio.Memory), fn)

// This operation uses disk
output2, _ := sio.Process(ctx, src, sio.Out(sio.Pdf, sio.File), fn)
How do I handle errors during processing?

If your processing function returns an error, the output is automatically cleaned up:

output, err := sio.Process(ctx, src, sio.Out(sio.Pdf), func(ctx context.Context, r io.Reader, w io.Writer) error {
    if err := validate(r); err != nil {
        return err // Output is cleaned up automatically
    }
    return process(r, w)
})
if err != nil {
    // Output was already cleaned up
    return err
}
// Output is valid
Can I use sio with standard library functions?

Absolutely! StreamReader produces standard io.Reader:

err := sio.Read(ctx, src, func(ctx context.Context, r io.Reader) error {
    // r is io.Reader - use with any stdlib function
    return json.NewDecoder(r).Decode(&data)
})
How do I download from URLs with authentication?

Use a custom HTTP client:

client := &http.Client{
    Transport: &customTransport{token: "..."},
}
src := sio.NewURLReader("https://api.example.com/data",
    sio.URLReaderOptions{}.WithClient(client),
)
What's the difference between Keep() and SaveAs()?
  • Keep(): Marks the temp file to survive session.Cleanup(), but it stays in the temp directory
  • SaveAs(): Copies the file to a permanent location outside the temp directory
output, _ := sio.Process(ctx, src, sio.Out(sio.Pdf), convert)

// Keep in temp directory but don't delete
output.Keep()

// OR copy to permanent location
output.SaveAs("/permanent/files/result.pdf")

File Extension Constants

sio.Pdf    // ".pdf"
sio.Text   // ".txt"
sio.Csv    // ".csv"
sio.Jpg    // ".jpg"
sio.Png    // ".png"
sio.Xlsx   // ".xlsx"
sio.Docx   // ".docx"
sio.Pptx   // ".pptx"
sio.Zip    // ".zip"
sio.Json   // ".json"
sio.Xml    // ".xml"

// Or create your own
customExt := sio.ToExt("xml") // ".xml"

Requirements

  • Go 1.23 or newer

Design Philosophy

sio follows these principles:

  1. Predictable: Resources are cleaned up automatically and deterministically
  2. Composable: Small, focused components that work together
  3. Practical: Built for real production workloads, not academic exercises
  4. Safe: Proper error handling and resource management built-in
  5. Flexible: Choose the trade-offs that make sense for your use case

License

MIT License. See LICENSE for details.


Support

If you find sio helpful, consider supporting development:

Buy Me a Coffee


Built with ❀️ for Gophers who process files

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

View Source
const (
	Json = ".json"
	Csv  = ".csv"
	Txt  = ".txt"
	Xml  = ".xml"

	Pdf  = ".pdf"
	Docx = ".docx"
	Xlsx = ".xlsx"
	Pptx = ".pptx"

	Jpg  = ".jpg"
	Jpeg = ".jpeg"
	Png  = ".png"

	Zip = ".zip"
)
View Source
const (
	Memory = StorageMemory
	File   = StorageFile
)

Shorthand aliases

View Source
const (
	DefaultBaseTempDir = "./temp"
)

Variables ΒΆ

View Source
var (
	ErrNilSource              = errors.New("sio: nil source")
	ErrOpenFailed             = errors.New("sio: cannot open reader")
	ErrIoManagerClosed        = errors.New("sio: manager is closed")
	ErrIoSessionClosed        = errors.New("sio: session is closed")
	ErrInvalidURL             = errors.New("sio: invalid URL")
	ErrDownloadFailed         = errors.New("sio: download failed")
	ErrNoSession              = errors.New("sio: session is nil")
	ErrFileStorageUnavailable = errors.New("sio: file storage requires directory (manager created with StorageMemory only)")
	ErrInvalidSessionType     = errors.New("sio: invalid session type")
)

Functions ΒΆ

func BindRead ΒΆ added in v0.0.7

func BindRead(ctx context.Context, fn func(ctx context.Context, b *Binder) error) error

BindRead opens multiple StreamReaders lazily through Binder and executes fn. This is standalone (no session required).

func BindReadResult ΒΆ added in v0.0.7

func BindReadResult[T any](ctx context.Context, fn func(ctx context.Context, b *Binder) (*T, error)) (*T, error)

BindReadResult is like BindRead but also returns a result value.

func Configure ΒΆ added in v0.0.5

func Configure(config Config) error

func Copy ΒΆ added in v0.0.5

func Copy(dst io.Writer, src io.Reader) (int64, error)

func NopCloser ΒΆ added in v0.0.7

func NopCloser(r io.Reader) io.ReadCloser

func Read ΒΆ

func Read(ctx context.Context, source StreamReader, fn ReadFunc) error

Read is a convenience wrapper that gets IoSession from context and calls ses.Read(...). If there is no session, it falls back to direct streaming from the StreamReader.

func ReadFileLines ΒΆ added in v0.0.4

func ReadFileLines(ctx context.Context, path string, fn LineFunc) error

func ReadLines ΒΆ added in v0.0.4

func ReadLines(ctx context.Context, src StreamReader, fn LineFunc) error

func ReadList ΒΆ added in v0.0.3

func ReadList(ctx context.Context, sources []StreamReader, fn ReadListFunc) error

ReadList is a convenience wrapper for IoSession.ReadList.

func ReadListResult ΒΆ added in v0.0.3

func ReadListResult[T any](ctx context.Context, sources []StreamReader, fn func(ctx context.Context, readers []io.Reader) (*T, error)) (*T, error)

func ReadResult ΒΆ added in v0.0.3

func ReadResult[T any](ctx context.Context, source StreamReader, fn func(ctx context.Context, r io.Reader) (*T, error)) (*T, error)

func Size ΒΆ added in v0.0.7

func Size(ctx context.Context, source StreamReader) (int64, error)

func SizeFromPath ΒΆ added in v0.0.7

func SizeFromPath(path string) (int64, error)

func SizeFromReader ΒΆ added in v0.0.7

func SizeFromReader(r io.Reader) int64

func SizeFromStream ΒΆ added in v0.0.7

func SizeFromStream(sr StreamReader) int64

func ToExt ΒΆ added in v0.0.7

func ToExt(format string) string

func WithSession ΒΆ added in v0.0.3

func WithSession(ctx context.Context, ses IoSession) context.Context

WithSession attaches a IoSession into context.

func WriteFile ΒΆ added in v0.0.5

func WriteFile(r io.Reader, path string) (int64, error)

func WriteStreamToFile ΒΆ added in v0.0.5

func WriteStreamToFile(src StreamReader, path string) (int64, error)

Types ΒΆ

type Binder ΒΆ added in v0.0.7

type Binder struct {
	// contains filtered or unexported fields
}

Binder collects StreamReaders and opens them eagerly on registration.

func (*Binder) Err ΒΆ added in v0.0.7

func (b *Binder) Err() error

Err returns any error that occurred during registration.

func (*Binder) Use ΒΆ added in v0.0.7

func (b *Binder) Use(sr StreamReader) (io.Reader, error)

Use is a convenience wrapper around Reader that returns io.Reader directly. If opening fails, Binder.err is set and nil is returned.

type BytesReader ΒΆ

type BytesReader struct {
	// contains filtered or unexported fields
}

BytesReader exposes an in-memory []byte as a StreamReader. Cleanup() optionally clears the underlying buffer.

func NewBytesReader ΒΆ

func NewBytesReader(data []byte) *BytesReader

func (*BytesReader) Cleanup ΒΆ

func (b *BytesReader) Cleanup() error

func (*BytesReader) Data ΒΆ

func (b *BytesReader) Data() []byte

Data returns the underlying byte slice.

func (*BytesReader) Open ΒΆ

func (b *BytesReader) Open() (io.ReadCloser, error)

func (*BytesReader) Size ΒΆ added in v0.0.7

func (b *BytesReader) Size() int64

type Config ΒΆ added in v0.0.5

type Config struct {
	// contains filtered or unexported fields
}

func NewConfig ΒΆ added in v0.0.7

func NewConfig(client *http.Client) Config

NewConfig constructs a Config with a custom HTTP client.

func (Config) WithClient ΒΆ added in v0.0.7

func (c Config) WithClient(client *http.Client) Config

WithClient sets the HTTP client on a Config.

type DownloadReaderCloser ΒΆ

type DownloadReaderCloser interface {
	io.Reader
	io.Closer
}

DownloadReaderCloser is a convenience interface for a read-only stream that also supports Close.

func NewDownloadReaderCloser ΒΆ

func NewDownloadReaderCloser(streamReader StreamReader, cleanup ...func()) (DownloadReaderCloser, error)

NewDownloadReaderCloser wraps a StreamReader as a DownloadReaderCloser.

type FileReader ΒΆ

type FileReader struct {
	// contains filtered or unexported fields
}

FileReader reads from a file path on disk. Cleanup() does NOT remove the original file.

func NewFileReader ΒΆ

func NewFileReader(path string) *FileReader

func (*FileReader) Cleanup ΒΆ

func (f *FileReader) Cleanup() error

func (*FileReader) Open ΒΆ

func (f *FileReader) Open() (io.ReadCloser, error)

func (*FileReader) Path ΒΆ

func (f *FileReader) Path() string

Path returns the underlying file path.

func (*FileReader) Size ΒΆ added in v0.0.7

func (f *FileReader) Size() int64

type GenericReader ΒΆ added in v0.0.7

type GenericReader struct {
	// contains filtered or unexported fields
}

GenericReader wraps an uploaded io.Reader. Cleanup() does nothing because frameworks handle their own temp files.

func NewGenericReader ΒΆ added in v0.0.7

func NewGenericReader(r io.Reader) *GenericReader

func NewPartReader ΒΆ added in v0.0.3

func NewPartReader(p *multipart.Part) *GenericReader

NewPartReader wraps multipart.Part as StreamReader (streaming, no buffering).

func (*GenericReader) Cleanup ΒΆ added in v0.0.7

func (m *GenericReader) Cleanup() error

func (*GenericReader) Open ΒΆ added in v0.0.7

func (m *GenericReader) Open() (io.ReadCloser, error)

type InOption ΒΆ added in v0.0.3

type InOption func(*inConfig)

InOption is a functional option for In(...).

func DeleteAfterUse ΒΆ added in v0.0.3

func DeleteAfterUse() InOption

DeleteAfterUse tells In(...) to delete the underlying file after the StreamReader is cleaned up (only works for *FileReader).

type IoManager ΒΆ added in v0.0.3

type IoManager interface {
	NewSession() (IoSession, error)
	Cleanup() error
}

func NewIoManager ΒΆ added in v0.0.3

func NewIoManager(baseDir string, storageType ...StorageType) (IoManager, error)

NewIoManager creates a new IoManager.

  • baseDir == "" β†’ create a temp folder using os.MkdirTemp("", "sio-")
  • baseDir != "" β†’ create/use the provided directory
  • storageType: optional parameter to specify storage strategy (default: StorageFile)

type IoSession ΒΆ added in v0.0.3

type IoSession interface {
	Read(ctx context.Context, source StreamReader, fn ReadFunc) error
	ReadList(ctx context.Context, sources []StreamReader, fn ReadListFunc) error

	Process(ctx context.Context, source StreamReader, out OutConfig, fn ProcessFunc) (*Output, error)
	ProcessList(ctx context.Context, sources []StreamReader, out OutConfig, fn ProcessListFunc) (*Output, error)

	Cleanup() error
}

func Session ΒΆ

func Session(ctx context.Context) IoSession

Session extracts IoSession from context. Returns nil if not found.

type LineFunc ΒΆ added in v0.0.7

type LineFunc func(line string) error

type MultipartReader ΒΆ

type MultipartReader struct {
	// contains filtered or unexported fields
}

MultipartReader wraps an uploaded multipart.FileHeader. Cleanup() does nothing because frameworks handle their own temp files.

func NewMultipartReader ΒΆ

func NewMultipartReader(fh *multipart.FileHeader) *MultipartReader

func (*MultipartReader) Cleanup ΒΆ

func (m *MultipartReader) Cleanup() error

func (*MultipartReader) Open ΒΆ

func (m *MultipartReader) Open() (io.ReadCloser, error)

type OutConfig ΒΆ added in v0.0.7

type OutConfig struct {
	// contains filtered or unexported fields
}

OutConfig configures output behavior

func Out ΒΆ added in v0.0.7

func Out(ext string, opts ...StorageType) OutConfig

Out creates output configuration.

Usage:

sio.Out(".pdf")                        // use session default
sio.Out(".pdf", sio.Memory)            // force memory storage
sio.Out(".pdf", sio.File)              // force file storage
sio.Out(".pdf", sio.Storage("memory")) // from string config

func (OutConfig) Ext ΒΆ added in v0.0.7

func (o OutConfig) Ext() string

Ext returns the output extension.

func (OutConfig) StorageType ΒΆ added in v0.0.7

func (o OutConfig) StorageType() *StorageType

StorageType returns the configured storage type, or nil when unset.

type Output ΒΆ

type Output struct {
	// contains filtered or unexported fields
}

Output represents a file produced by a IoSession.Process call. It can be kept beyond session cleanup via Output.Keep().

func BindProcess ΒΆ added in v0.0.7

func BindProcess(ctx context.Context, out OutConfig, fn func(ctx context.Context, b *Binder, w io.Writer) error) (*Output, error)

BindProcess opens multiple StreamReaders lazily, creates an output, and executes fn. Requires a session in context.

func BindProcessResult ΒΆ added in v0.0.7

func BindProcessResult[T any](ctx context.Context, out OutConfig, fn func(ctx context.Context, b *Binder, w io.Writer) (*T, error)) (*Output, *T, error)

BindProcessResult is like BindProcess but also returns a result value.

func Process ΒΆ

func Process(ctx context.Context, source StreamReader, out OutConfig, fn ProcessFunc) (*Output, error)

Process is a convenience wrapper for IoSession.Process.

func ProcessList ΒΆ added in v0.0.3

func ProcessList(ctx context.Context, sources []StreamReader, out OutConfig, fn ProcessListFunc) (*Output, error)

ProcessList is a convenience wrapper for IoSession.ProcessList.

func ProcessListResult ΒΆ added in v0.0.3

func ProcessListResult[T any](ctx context.Context, sources []StreamReader, out OutConfig, fn func(ctx context.Context, readers []io.Reader, w io.Writer) (*T, error)) (*Output, *T, error)

func ProcessResult ΒΆ added in v0.0.3

func ProcessResult[T any](ctx context.Context, source StreamReader, out OutConfig, fn func(ctx context.Context, r io.Reader, w io.Writer) (*T, error)) (*Output, *T, error)

func ToOutput ΒΆ added in v0.0.4

func ToOutput(ctx context.Context, src StreamReader, out OutConfig) (*Output, error)

func (*Output) AsReaderAt ΒΆ added in v0.0.7

func (o *Output) AsReaderAt(ctx context.Context, opts ...ToReaderAtOption) (*ReaderAtResult, error)

func (*Output) Bytes ΒΆ

func (o *Output) Bytes() ([]byte, error)

Bytes loads the entire file into memory. Use carefully for very large files.

func (*Output) Data ΒΆ added in v0.0.7

func (o *Output) Data() []byte

Data returns the raw bytes for StorageMemory mode. Returns nil for StorageFile mode. The returned slice is owned by Output - do not modify.

func (*Output) Keep ΒΆ

func (o *Output) Keep() *Output

Keep marks the output file as persistent. IoSession.Cleanup() will NOT delete the file.

func (*Output) OpenReader ΒΆ

func (o *Output) OpenReader() (io.ReadCloser, error)

func (*Output) OpenWriter ΒΆ

func (o *Output) OpenWriter() (io.WriteCloser, error)

func (*Output) Path ΒΆ

func (o *Output) Path() string

func (*Output) Reader ΒΆ added in v0.0.3

func (o *Output) Reader() StreamReader

func (*Output) SaveAs ΒΆ

func (o *Output) SaveAs(path string) error

SaveAs copies the output file to a persistent path outside of the session dir.

func (*Output) StorageType ΒΆ added in v0.0.7

func (o *Output) StorageType() StorageType

StorageType returns the storage type of this output.

func (*Output) WriteTo ΒΆ added in v0.0.7

func (o *Output) WriteTo(w io.Writer) (int64, error)

type ProcessFunc ΒΆ added in v0.0.3

type ProcessFunc func(ctx context.Context, r io.Reader, w io.Writer) error

type ProcessListFunc ΒΆ added in v0.0.3

type ProcessListFunc func(ctx context.Context, readers []io.Reader, w io.Writer) error

type ReadFunc ΒΆ added in v0.0.3

type ReadFunc func(ctx context.Context, r io.Reader) error

type ReadListFunc ΒΆ added in v0.0.3

type ReadListFunc func(ctx context.Context, readers []io.Reader) error

type ReaderAtResult ΒΆ added in v0.0.7

type ReaderAtResult struct {
	// contains filtered or unexported fields
}

func ToReaderAt ΒΆ added in v0.0.7

func ToReaderAt(ctx context.Context, r io.Reader, opts ...ToReaderAtOption) (*ReaderAtResult, error)

ToReaderAt converts any io.Reader into something that supports io.ReaderAt. - If the input already supports ReaderAt β†’ returns it directly. - If it is small enough β†’ keeps it in memory. - If too large β†’ spills to temporary file.

func (*ReaderAtResult) Cleanup ΒΆ added in v0.0.7

func (r *ReaderAtResult) Cleanup() error

Cleanup releases any resources created by ToReaderAt.

func (*ReaderAtResult) ReaderAt ΒΆ added in v0.0.7

func (r *ReaderAtResult) ReaderAt() io.ReaderAt

ReaderAt exposes the underlying ReaderAt.

func (*ReaderAtResult) Size ΒΆ added in v0.0.7

func (r *ReaderAtResult) Size() int64

Size returns the byte size of the underlying data when known.

func (*ReaderAtResult) Source ΒΆ added in v0.0.7

func (r *ReaderAtResult) Source() string

Source reports where the ReaderAt was sourced from.

type ReaderList ΒΆ added in v0.0.3

type ReaderList struct {
	// contains filtered or unexported fields
}

ReaderList holds opened readers and provides cleanup functionality.

func OpenReaderList ΒΆ added in v0.0.3

func OpenReaderList(sources []StreamReader) (*ReaderList, error)

OpenReaderList opens all StreamReaders and returns a ReaderList.

func (*ReaderList) Close ΒΆ added in v0.0.3

func (rl *ReaderList) Close() error

Close closes all opened readers and cleans up all source StreamReaders.

func (*ReaderList) Readers ΒΆ added in v0.0.3

func (rl *ReaderList) Readers() []io.Reader

Readers returns the list of opened readers.

type StorageType ΒΆ added in v0.0.7

type StorageType int

StorageType defines how the IoManager stores data

const (
	// StorageFile stores data as temporary files on disk (default)
	StorageFile StorageType = iota
	// StorageMemory stores data in memory as byte slices
	StorageMemory
)

func Storage ΒΆ added in v0.0.7

func Storage(s string) StorageType

Storage converts string to StorageType. Supports: "file", "memory"

func (StorageType) String ΒΆ added in v0.0.7

func (s StorageType) String() string

String returns string representation of StorageType

type StreamReader ΒΆ

type StreamReader interface {
	Open() (io.ReadCloser, error)
	Cleanup() error
}

StreamReader represents any input source that can be opened as an io.ReadCloser, and is responsible for cleaning up its own underlying resources (temporary files, buffers, etc.).

func In ΒΆ added in v0.0.3

func In(sr StreamReader, opts ...InOption) StreamReader

In wraps a StreamReader with additional behavior, such as DeleteAfterUse.

type ToReaderAtOption ΒΆ added in v0.0.7

type ToReaderAtOption func(*ToReaderAtOptions)

func WithMaxMemoryBytes ΒΆ added in v0.0.7

func WithMaxMemoryBytes(n int64) ToReaderAtOption

func WithTempDir ΒΆ added in v0.0.7

func WithTempDir(dir string) ToReaderAtOption

func WithTempPattern ΒΆ added in v0.0.7

func WithTempPattern(p string) ToReaderAtOption

type ToReaderAtOptions ΒΆ added in v0.0.7

type ToReaderAtOptions struct {
	// contains filtered or unexported fields
}

type URLReader ΒΆ

type URLReader struct {
	// contains filtered or unexported fields
}

URLReader streams content directly from a URL. Each Open() call creates a new HTTP request. Cleanup() is a no-op since the response body is closed via the returned ReadCloser.

func NewURLReader ΒΆ

func NewURLReader(urlStr string, opts ...URLReaderOptions) *URLReader

func (*URLReader) Cleanup ΒΆ

func (u *URLReader) Cleanup() error

func (*URLReader) Open ΒΆ

func (u *URLReader) Open() (io.ReadCloser, error)

type URLReaderOptions ΒΆ added in v0.0.5

type URLReaderOptions struct {
	// contains filtered or unexported fields
}

func (URLReaderOptions) WithClient ΒΆ added in v0.0.7

func (o URLReaderOptions) WithClient(client *http.Client) URLReaderOptions

WithClient sets a custom HTTP client for URLReaderOptions.

func (URLReaderOptions) WithInsecureTLS ΒΆ added in v0.0.7

func (o URLReaderOptions) WithInsecureTLS(insecure bool) URLReaderOptions

WithInsecureTLS configures TLS verification for URLReaderOptions.

func (URLReaderOptions) WithTimeout ΒΆ added in v0.0.7

func (o URLReaderOptions) WithTimeout(timeout time.Duration) URLReaderOptions

WithTimeout sets the timeout for URLReaderOptions.

type UseReader ΒΆ added in v0.0.7

type UseReader struct {
	// contains filtered or unexported fields
}

UseReader wraps an opened io.Reader from Binder.

func (*UseReader) Err ΒΆ added in v0.0.7

func (ur *UseReader) Err() error

Err returns any error associated with this reader.

func (*UseReader) Read ΒΆ added in v0.0.7

func (ur *UseReader) Read(p []byte) (int, error)

Read implements io.Reader.

func (*UseReader) Unwrap ΒΆ added in v0.0.7

func (ur *UseReader) Unwrap() io.Reader

Unwrap returns underlying io.Reader (nil if error).

Directories ΒΆ

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL