github.com/jordan-bonecutter/can-go@v0.0.0-20230901155856-d83995b18e50/pkg/socketcan/receiver.go (about) 1 package socketcan 2 3 import ( 4 "bufio" 5 "io" 6 7 "go.einride.tech/can" 8 ) 9 10 type ReceiverOption func(*receiverOpts) 11 12 type receiverOpts struct { 13 frameInterceptor FrameInterceptor 14 } 15 16 type Receiver struct { 17 opts receiverOpts 18 rc io.ReadCloser 19 sc *bufio.Scanner 20 frame frame 21 } 22 23 func NewReceiver(rc io.ReadCloser, opt ...ReceiverOption) *Receiver { 24 opts := receiverOpts{} 25 for _, f := range opt { 26 f(&opts) 27 } 28 sc := bufio.NewScanner(rc) 29 sc.Split(scanFrames) 30 return &Receiver{ 31 rc: rc, 32 opts: opts, 33 sc: sc, 34 } 35 } 36 37 func scanFrames(data []byte, _ bool) (int, []byte, error) { 38 if len(data) < lengthOfFrame { 39 // not enough data for a full frame 40 return 0, nil, nil 41 } 42 return lengthOfFrame, data[0:lengthOfFrame], nil 43 } 44 45 func (r *Receiver) Receive() bool { 46 ok := r.sc.Scan() 47 r.frame = frame{} 48 if ok { 49 r.frame.unmarshalBinary(r.sc.Bytes()) 50 if r.opts.frameInterceptor != nil { 51 r.opts.frameInterceptor(r.frame.decodeFrame()) 52 } 53 } 54 return ok 55 } 56 57 func (r *Receiver) HasErrorFrame() bool { 58 return r.frame.isError() 59 } 60 61 func (r *Receiver) Frame() can.Frame { 62 return r.frame.decodeFrame() 63 } 64 65 func (r *Receiver) ErrorFrame() ErrorFrame { 66 return r.frame.decodeErrorFrame() 67 } 68 69 func (r *Receiver) Err() error { 70 return r.sc.Err() 71 } 72 73 func (r *Receiver) Close() error { 74 return r.rc.Close() 75 } 76 77 // ReceiverFrameInterceptor returns a ReceiverOption that sets the FrameInterceptor for the 78 // receiver. Only one frame interceptor can be installed. 79 func ReceiverFrameInterceptor(i FrameInterceptor) ReceiverOption { 80 return func(o *receiverOpts) { 81 o.frameInterceptor = i 82 } 83 }