mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Caption support (#2462)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
121
vendor/github.com/asticode/go-astikit/io.go
generated
vendored
Normal file
121
vendor/github.com/asticode/go-astikit/io.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
package astikit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Copy is a copy with a context
|
||||
func Copy(ctx context.Context, dst io.Writer, src io.Reader) (int64, error) {
|
||||
return io.Copy(dst, NewCtxReader(ctx, src))
|
||||
}
|
||||
|
||||
type nopCloser struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (nopCloser) Close() error { return nil }
|
||||
|
||||
// NopCloser returns a WriteCloser with a no-op Close method wrapping
|
||||
// the provided Writer w.
|
||||
func NopCloser(w io.Writer) io.WriteCloser {
|
||||
return nopCloser{w}
|
||||
}
|
||||
|
||||
// CtxReader represents a reader with a context
|
||||
type CtxReader struct {
|
||||
ctx context.Context
|
||||
reader io.Reader
|
||||
}
|
||||
|
||||
// NewCtxReader creates a reader with a context
|
||||
func NewCtxReader(ctx context.Context, r io.Reader) *CtxReader {
|
||||
return &CtxReader{
|
||||
ctx: ctx,
|
||||
reader: r,
|
||||
}
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface
|
||||
func (r *CtxReader) Read(p []byte) (n int, err error) {
|
||||
// Check context
|
||||
if err = r.ctx.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Read
|
||||
return r.reader.Read(p)
|
||||
}
|
||||
|
||||
// WriterAdapter represents an object that can adapt a Writer
|
||||
type WriterAdapter struct {
|
||||
buffer *bytes.Buffer
|
||||
o WriterAdapterOptions
|
||||
}
|
||||
|
||||
// WriterAdapterOptions represents WriterAdapter options
|
||||
type WriterAdapterOptions struct {
|
||||
Callback func(i []byte)
|
||||
Split []byte
|
||||
}
|
||||
|
||||
// NewWriterAdapter creates a new WriterAdapter
|
||||
func NewWriterAdapter(o WriterAdapterOptions) *WriterAdapter {
|
||||
return &WriterAdapter{
|
||||
buffer: &bytes.Buffer{},
|
||||
o: o,
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the adapter properly
|
||||
func (w *WriterAdapter) Close() error {
|
||||
if w.buffer.Len() > 0 {
|
||||
w.write(w.buffer.Bytes())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements the io.Writer interface
|
||||
func (w *WriterAdapter) Write(i []byte) (n int, err error) {
|
||||
// Update n to avoid broken pipe error
|
||||
defer func() {
|
||||
n = len(i)
|
||||
}()
|
||||
|
||||
// Split
|
||||
if len(w.o.Split) > 0 {
|
||||
// Split bytes are not present, write in buffer
|
||||
if !bytes.Contains(i, w.o.Split) {
|
||||
w.buffer.Write(i)
|
||||
return
|
||||
}
|
||||
|
||||
// Loop in split items
|
||||
items := bytes.Split(i, w.o.Split)
|
||||
for i := 0; i < len(items)-1; i++ {
|
||||
// If this is the first item, prepend the buffer
|
||||
if i == 0 {
|
||||
items[i] = append(w.buffer.Bytes(), items[i]...)
|
||||
w.buffer.Reset()
|
||||
}
|
||||
|
||||
// Write
|
||||
w.write(items[i])
|
||||
}
|
||||
|
||||
// Add remaining to buffer
|
||||
w.buffer.Write(items[len(items)-1])
|
||||
return
|
||||
}
|
||||
|
||||
// By default, forward the bytes
|
||||
w.write(i)
|
||||
return
|
||||
}
|
||||
|
||||
func (w *WriterAdapter) write(i []byte) {
|
||||
if w.o.Callback != nil {
|
||||
w.o.Callback(i)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user