github.com/jshiv/can-go@v0.2.1-0.20210224011015-069e90e90bdf/pkg/socketcan/fileconn.go (about)

     1  package socketcan
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  	"os"
     7  	"time"
     8  )
     9  
    10  // file is an interface for mocking file operations performed by fileConn.
    11  type file interface {
    12  	Read([]byte) (int, error)
    13  	Write([]byte) (int, error)
    14  	SetDeadline(time.Time) error
    15  	SetReadDeadline(time.Time) error
    16  	SetWriteDeadline(time.Time) error
    17  	Close() error
    18  }
    19  
    20  // fileConn provides a net.Conn API for file-like types.
    21  type fileConn struct {
    22  	// f is the file to provide a net.Conn API for.
    23  	f file
    24  	// net is the connection's network.
    25  	net string
    26  	// la is the connection's local address, if any.
    27  	la net.Addr
    28  	// ra is the connection's remote address, if any.
    29  	ra net.Addr
    30  }
    31  
    32  var _ net.Conn = &fileConn{}
    33  
    34  func (c *fileConn) Read(b []byte) (int, error) {
    35  	n, err := c.f.Read(b)
    36  	if err != nil {
    37  		return n, &net.OpError{Op: "read", Net: c.net, Source: c.la, Addr: c.ra, Err: unwrapPathError(err)}
    38  	}
    39  	return n, nil
    40  }
    41  
    42  func (c *fileConn) Write(b []byte) (int, error) {
    43  	n, err := c.f.Write(b)
    44  	if err != nil {
    45  		return n, &net.OpError{Op: "write", Net: c.net, Source: c.la, Addr: c.ra, Err: unwrapPathError(err)}
    46  	}
    47  	return n, nil
    48  }
    49  
    50  func (c *fileConn) LocalAddr() net.Addr {
    51  	return c.la
    52  }
    53  
    54  func (c *fileConn) RemoteAddr() net.Addr {
    55  	return c.ra
    56  }
    57  
    58  func (c *fileConn) SetDeadline(t time.Time) error {
    59  	if err := c.f.SetDeadline(t); err != nil {
    60  		return &net.OpError{Op: "set deadline", Net: c.net, Source: c.la, Addr: c.ra, Err: unwrapPathError(err)}
    61  	}
    62  	return nil
    63  }
    64  
    65  func (c *fileConn) SetReadDeadline(t time.Time) error {
    66  	if err := c.f.SetReadDeadline(t); err != nil {
    67  		return &net.OpError{Op: "set read deadline", Net: c.net, Source: c.la, Addr: c.ra, Err: unwrapPathError(err)}
    68  	}
    69  	return nil
    70  }
    71  
    72  func (c *fileConn) SetWriteDeadline(t time.Time) error {
    73  	if err := c.f.SetWriteDeadline(t); err != nil {
    74  		return &net.OpError{Op: "set write deadline", Net: c.net, Source: c.la, Addr: c.ra, Err: unwrapPathError(err)}
    75  	}
    76  	return nil
    77  }
    78  
    79  func (c *fileConn) Close() error {
    80  	if err := c.f.Close(); err != nil {
    81  		return &net.OpError{Op: "close", Net: c.net, Source: c.la, Addr: c.ra, Err: unwrapPathError(err)}
    82  	}
    83  	return nil
    84  }
    85  
    86  // unwrapPathError unwraps one level of *os.PathError from the provided error.
    87  func unwrapPathError(err error) error {
    88  	var pe *os.PathError
    89  	if errors.As(err, &pe) {
    90  		return pe.Err
    91  	}
    92  	return err
    93  }