lazy_reader.go 978 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package splithttp
  2. import (
  3. "io"
  4. "sync"
  5. "github.com/xtls/xray-core/common/errors"
  6. )
  7. type LazyReader struct {
  8. readerSync sync.Mutex
  9. CreateReader func() (io.ReadCloser, error)
  10. reader io.ReadCloser
  11. readerError error
  12. }
  13. func (r *LazyReader) getReader() (io.ReadCloser, error) {
  14. r.readerSync.Lock()
  15. defer r.readerSync.Unlock()
  16. if r.reader != nil {
  17. return r.reader, nil
  18. }
  19. if r.readerError != nil {
  20. return nil, r.readerError
  21. }
  22. reader, err := r.CreateReader()
  23. if err != nil {
  24. r.readerError = err
  25. return nil, err
  26. }
  27. r.reader = reader
  28. return reader, nil
  29. }
  30. func (r *LazyReader) Read(b []byte) (int, error) {
  31. reader, err := r.getReader()
  32. if err != nil {
  33. return 0, err
  34. }
  35. n, err := reader.Read(b)
  36. return n, err
  37. }
  38. func (r *LazyReader) Close() error {
  39. r.readerSync.Lock()
  40. defer r.readerSync.Unlock()
  41. var err error
  42. if r.reader != nil {
  43. err = r.reader.Close()
  44. r.reader = nil
  45. r.readerError = errors.New("closed reader")
  46. }
  47. return err
  48. }