github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/flow/io.gno (about) 1 // 2 // Written by Maxim Khitrov (November 2012) 3 // 4 5 package flow 6 7 import ( 8 "errors" 9 "io" 10 ) 11 12 // ErrLimit is returned by the Writer when a non-blocking write is short due to 13 // the transfer rate limit. 14 var ErrLimit = errors.New("flowrate: flow rate limit exceeded") 15 16 // Limiter is implemented by the Reader and Writer to provide a consistent 17 // interface for monitoring and controlling data transfer. 18 type Limiter interface { 19 Done() int64 20 Status() Status 21 SetTransferSize(bytes int64) 22 SetLimit(new int64) (old int64) 23 SetBlocking(new bool) (old bool) 24 } 25 26 // Reader implements io.ReadCloser with a restriction on the rate of data 27 // transfer. 28 type Reader struct { 29 io.Reader // Data source 30 *Monitor // Flow control monitor 31 32 limit int64 // Rate limit in bytes per second (unlimited when <= 0) 33 block bool // What to do when no new bytes can be read due to the limit 34 } 35 36 // NewReader restricts all Read operations on r to limit bytes per second. 37 func NewReader(r io.Reader, limit int64) *Reader { 38 return &Reader{r, New(0, 0), limit, false} // XXX default false 39 } 40 41 // Read reads up to len(p) bytes into p without exceeding the current transfer 42 // rate limit. It returns (0, nil) immediately if r is non-blocking and no new 43 // bytes can be read at this time. 44 func (r *Reader) Read(p []byte) (n int, err error) { 45 p = p[:r.Limit(len(p), r.limit, r.block)] 46 if len(p) > 0 { 47 n, err = r.IO(r.Reader.Read(p)) 48 } 49 return 50 } 51 52 // SetLimit changes the transfer rate limit to new bytes per second and returns 53 // the previous setting. 54 func (r *Reader) SetLimit(new int64) (old int64) { 55 old, r.limit = r.limit, new 56 return 57 } 58 59 // SetBlocking changes the blocking behavior and returns the previous setting. A 60 // Read call on a non-blocking reader returns immediately if no additional bytes 61 // may be read at this time due to the rate limit. 62 func (r *Reader) SetBlocking(new bool) (old bool) { 63 if new == true { 64 panic("blocking not yet supported") 65 } 66 old, r.block = r.block, new 67 return 68 } 69 70 // Close closes the underlying reader if it implements the io.Closer interface. 71 func (r *Reader) Close() error { 72 defer r.Done() 73 if c, ok := r.Reader.(io.Closer); ok { 74 return c.Close() 75 } 76 return nil 77 } 78 79 // Writer implements io.WriteCloser with a restriction on the rate of data 80 // transfer. 81 type Writer struct { 82 io.Writer // Data destination 83 *Monitor // Flow control monitor 84 85 limit int64 // Rate limit in bytes per second (unlimited when <= 0) 86 block bool // What to do when no new bytes can be written due to the limit 87 } 88 89 // NewWriter restricts all Write operations on w to limit bytes per second. The 90 // transfer rate and the default blocking behavior (true) can be changed 91 // directly on the returned *Writer. 92 func NewWriter(w io.Writer, limit int64) *Writer { 93 return &Writer{w, New(0, 0), limit, false} // XXX default false 94 } 95 96 // Write writes len(p) bytes from p to the underlying data stream without 97 // exceeding the current transfer rate limit. It returns (n, ErrLimit) if w is 98 // non-blocking and no additional bytes can be written at this time. 99 func (w *Writer) Write(p []byte) (n int, err error) { 100 var c int 101 for len(p) > 0 && err == nil { 102 s := p[:w.Limit(len(p), w.limit, w.block)] 103 if len(s) > 0 { 104 c, err = w.IO(w.Writer.Write(s)) 105 } else { 106 return n, ErrLimit 107 } 108 p = p[c:] 109 n += c 110 } 111 return 112 } 113 114 // SetLimit changes the transfer rate limit to new bytes per second and returns 115 // the previous setting. 116 func (w *Writer) SetLimit(new int64) (old int64) { 117 old, w.limit = w.limit, new 118 return 119 } 120 121 // SetBlocking changes the blocking behavior and returns the previous setting. A 122 // Write call on a non-blocking writer returns as soon as no additional bytes 123 // may be written at this time due to the rate limit. 124 func (w *Writer) SetBlocking(new bool) (old bool) { 125 old, w.block = w.block, new 126 return 127 } 128 129 // Close closes the underlying writer if it implements the io.Closer interface. 130 func (w *Writer) Close() error { 131 defer w.Done() 132 if c, ok := w.Writer.(io.Closer); ok { 133 return c.Close() 134 } 135 return nil 136 }