github.com/haraldrudell/parl@v0.4.176/pio/context-reader.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pio 7 8 import ( 9 "context" 10 "io" 11 ) 12 13 // ContextReader is an [io.ReadCloser] that aborts on context cancel 14 // - on context cancel, Read returns error [context.Canceled] 15 // - If the runtime type of reader implements [io.Close], it ContextReader can close it 16 type ContextReader struct { 17 reader io.Reader // Read() 18 // idempotent pannic-free closer if reader implemented [io.Closer] 19 // - Close() IsClosable() 20 ContextCloser 21 ctx context.Context 22 } 23 24 var _ io.ReadCloser = &ContextReader{} 25 26 // NewContextReader returns an [io.ReadCloser] that aborts on context cancel 27 // - on context cancel, Read returns error [context.Canceled] 28 // - If the runtime type of reader implements [io.Close], it can be closed 29 func NewContextReader(reader io.Reader, ctx context.Context) (contextReader *ContextReader) { 30 var closer, _ = reader.(io.Closer) 31 return &ContextReader{ 32 reader: reader, 33 ContextCloser: *NewContextCloser(closer), 34 ctx: ctx, 35 } 36 } 37 38 var _ = context.Canceled 39 40 // Read is like [io.Reader.Read] but cancels if the context is canceled 41 // - on context cancel, the error returned is [context.Canceled] 42 func (c *ContextReader) Read(p []byte) (n int, err error) { 43 if err = c.ctx.Err(); err != nil { 44 return 45 } 46 return c.reader.Read(p) 47 }