package io

import (
	
	
)

// NewSafeReadCloser returns a new safeReadCloser that wraps readCloser.
func ( io.ReadCloser) io.ReadCloser {
	 := &safeReadCloser{
		readCloser: ,
	}

	if ,  := .(io.WriterTo);  {
		return &safeWriteToReadCloser{safeReadCloser: }
	}

	return 
}

// safeWriteToReadCloser wraps a safeReadCloser but exposes a WriteTo interface implementation. This will panic
// if the underlying io.ReadClose does not support WriteTo. Use NewSafeReadCloser to ensure the proper handling of this
// type.
type safeWriteToReadCloser struct {
	*safeReadCloser
}

// WriteTo implements the io.WriteTo interface.
func ( *safeWriteToReadCloser) ( io.Writer) (int64, error) {
	.safeReadCloser.mtx.Lock()
	defer .safeReadCloser.mtx.Unlock()

	if .safeReadCloser.closed {
		return 0, io.EOF
	}

	return .safeReadCloser.readCloser.(io.WriterTo).WriteTo()
}

// safeReadCloser wraps a io.ReadCloser and presents an io.ReadCloser interface. When Close is called on safeReadCloser
// the underlying Close method will be executed, and then the reference to the reader will be dropped. This type
// is meant to be used with the net/http library which will retain a reference to the request body for the lifetime
// of a goroutine connection. Wrapping in this manner will ensure that no data race conditions are falsely reported.
// This type is thread-safe.
type safeReadCloser struct {
	readCloser io.ReadCloser
	closed     bool
	mtx        sync.Mutex
}

// Read reads up to len(p) bytes into p from the underlying read. If the reader is closed io.EOF will be returned.
func ( *safeReadCloser) ( []byte) ( int,  error) {
	.mtx.Lock()
	defer .mtx.Unlock()
	if .closed {
		return 0, io.EOF
	}

	return .readCloser.Read()
}

// Close calls the underlying io.ReadCloser's Close method, removes the reference to the reader, and returns any error
// reported from Close. Subsequent calls to Close will always return a nil error.
func ( *safeReadCloser) () error {
	.mtx.Lock()
	defer .mtx.Unlock()
	if .closed {
		return nil
	}

	.closed = true
	 := .readCloser
	.readCloser = nil
	return .Close()
}