package sysfs

import (
	
	

	experimentalsys 
	
	socketapi 
	
)

// NewTCPListenerFile creates a socketapi.TCPSock for a given *net.TCPListener.
func ( *net.TCPListener) socketapi.TCPSock {
	return newTCPListenerFile()
}

// baseSockFile implements base behavior for all TCPSock, TCPConn files,
// regardless the platform.
type baseSockFile struct {
	experimentalsys.UnimplementedFile
}

var _ experimentalsys.File = (*baseSockFile)(nil)

// IsDir implements the same method as documented on File.IsDir
func (*baseSockFile) () (bool, experimentalsys.Errno) {
	// We need to override this method because WASI-libc prestats the FD
	// and the default impl returns ENOSYS otherwise.
	return false, 0
}

// Stat implements the same method as documented on File.Stat
func ( *baseSockFile) () ( sys.Stat_t,  experimentalsys.Errno) {
	// The mode is not really important, but it should be neither a regular file nor a directory.
	.Mode = os.ModeIrregular
	return
}

var _ socketapi.TCPSock = (*tcpListenerFile)(nil)

type tcpListenerFile struct {
	baseSockFile

	tl       *net.TCPListener
	closed   bool
	nonblock bool
}

// newTCPListenerFile is a constructor for a socketapi.TCPSock.
//
// The current strategy is to wrap a net.TCPListener
// and invoking raw syscalls using syscallConnControl:
// this internal calls RawConn.Control(func(fd)), making sure
// that the underlying file descriptor is valid throughout
// the duration of the syscall.
func newDefaultTCPListenerFile( *net.TCPListener) socketapi.TCPSock {
	return &tcpListenerFile{tl: }
}

// Close implements the same method as documented on experimentalsys.File
func ( *tcpListenerFile) () experimentalsys.Errno {
	if !.closed {
		return experimentalsys.UnwrapOSError(.tl.Close())
	}
	return 0
}

// Addr is exposed for testing.
func ( *tcpListenerFile) () *net.TCPAddr {
	return .tl.Addr().(*net.TCPAddr)
}

// IsNonblock implements the same method as documented on fsapi.File
func ( *tcpListenerFile) () bool {
	return .nonblock
}

// Poll implements the same method as documented on fsapi.File
func ( *tcpListenerFile) ( fsapi.Pflag,  int32) ( bool,  experimentalsys.Errno) {
	return false, experimentalsys.ENOSYS
}

var _ socketapi.TCPConn = (*tcpConnFile)(nil)

type tcpConnFile struct {
	baseSockFile

	tc *net.TCPConn

	// nonblock is true when the underlying connection is flagged as non-blocking.
	// This ensures that reads and writes return experimentalsys.EAGAIN without blocking the caller.
	nonblock bool
	// closed is true when closed was called. This ensures proper experimentalsys.EBADF
	closed bool
}

func newTcpConn( *net.TCPConn) socketapi.TCPConn {
	return &tcpConnFile{tc: }
}

// Read implements the same method as documented on experimentalsys.File
func ( *tcpConnFile) ( []byte) ( int,  experimentalsys.Errno) {
	if len() == 0 {
		return 0, 0 // Short-circuit 0-len reads.
	}
	if nonBlockingFileReadSupported && .IsNonblock() {
		,  = syscallConnControl(.tc, func( uintptr) (int, experimentalsys.Errno) {
			,  := readSocket(, )
			 = experimentalsys.UnwrapOSError()
			 = fileError(, .closed, )
			return , 
		})
	} else {
		,  = read(.tc, )
	}
	if  != 0 {
		// Defer validation overhead until we've already had an error.
		 = fileError(, .closed, )
	}
	return
}

// Write implements the same method as documented on experimentalsys.File
func ( *tcpConnFile) ( []byte) ( int,  experimentalsys.Errno) {
	if nonBlockingFileWriteSupported && .IsNonblock() {
		return syscallConnControl(.tc, func( uintptr) (int, experimentalsys.Errno) {
			,  := writeSocket(, )
			 = experimentalsys.UnwrapOSError()
			 = fileError(, .closed, )
			return , 
		})
	} else {
		,  = write(.tc, )
	}
	if  != 0 {
		// Defer validation overhead until we've already had an error.
		 = fileError(, .closed, )
	}
	return
}

// Recvfrom implements the same method as documented on socketapi.TCPConn
func ( *tcpConnFile) ( []byte,  int) ( int,  experimentalsys.Errno) {
	if  != MSG_PEEK {
		 = experimentalsys.EINVAL
		return
	}
	return syscallConnControl(.tc, func( uintptr) (int, experimentalsys.Errno) {
		,  := recvfrom(, , MSG_PEEK)
		 = experimentalsys.UnwrapOSError()
		 = fileError(, .closed, )
		return , 
	})
}

// Close implements the same method as documented on experimentalsys.File
func ( *tcpConnFile) () experimentalsys.Errno {
	return .close()
}

func ( *tcpConnFile) () experimentalsys.Errno {
	if .closed {
		return 0
	}
	.closed = true
	return .Shutdown(socketapi.SHUT_RDWR)
}

// SetNonblock implements the same method as documented on fsapi.File
func ( *tcpConnFile) ( bool) ( experimentalsys.Errno) {
	.nonblock = 
	_,  = syscallConnControl(.tc, func( uintptr) (int, experimentalsys.Errno) {
		return 0, experimentalsys.UnwrapOSError(setNonblockSocket(, ))
	})
	return
}

// IsNonblock implements the same method as documented on fsapi.File
func ( *tcpConnFile) () bool {
	return .nonblock
}

// Poll implements the same method as documented on fsapi.File
func ( *tcpConnFile) ( fsapi.Pflag,  int32) ( bool,  experimentalsys.Errno) {
	return false, experimentalsys.ENOSYS
}