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