diff --git a/serial.go b/serial.go index e072d42..7b83d27 100644 --- a/serial.go +++ b/serial.go @@ -199,3 +199,50 @@ func (e PortError) Error() string { func (e PortError) Code() PortErrorCode { return e.code } + +// ModeFromString uses a string description of a serial mode (such as "8N1") +// to partially populate a Mode structure. +// See https://en.wikipedia.org/wiki/8-N-1 for details +func ModeFromString(smode string, mode *Mode) error { + if len(smode) > 0 { + switch smode[0] { + case '8': + mode.DataBits = 8 + case '7': + mode.DataBits = 7 + case '6': + mode.DataBits = 6 + case '5': + mode.DataBits = 5 + default: + return &PortError{code: InvalidDataBits} + } + } + if len(smode) > 1 { + switch smode[1] { + case 'E': + mode.Parity = EvenParity + case 'N': + mode.Parity = NoParity + case 'O': + mode.Parity = OddParity + case 'M': + mode.Parity = MarkParity + case 'S': + mode.Parity = SpaceParity + default: + return &PortError{code: InvalidParity} + } + } + if len(smode) > 2 { + switch smode[2] { + case '1': + mode.StopBits = OneStopBit + case '2': + mode.StopBits = TwoStopBits + default: + return &PortError{code: InvalidStopBits} + } + } + return nil +} diff --git a/serial_test.go b/serial_test.go new file mode 100644 index 0000000..af2b3ad --- /dev/null +++ b/serial_test.go @@ -0,0 +1,39 @@ +package serial + +import ( + "reflect" + "testing" +) + +func TestModeFromString(t *testing.T) { + good_cases := map[string]*Mode{ + "8N1": {DataBits: 8, Parity: NoParity, StopBits: OneStopBit}, + "7S2": {DataBits: 7, Parity: SpaceParity, StopBits: TwoStopBits}, + } + + bad_cases := map[string]*PortError{ + "9N1": {code: InvalidDataBits}, + "8N3": {code: InvalidStopBits}, + "8R1": {code: InvalidParity}, + } + + for s, m := range good_cases { + mode := &Mode{} + err := ModeFromString(s, mode) + if err != nil { + t.Errorf("Failed to convert mode %q: %s", s, err) + } else if !reflect.DeepEqual(mode, m) { + t.Errorf("Mode %q should convert to %+v, got %+v", s, m, mode) + } + } + + for s, e := range bad_cases { + mode := &Mode{} + err := ModeFromString(s, mode) + if err == nil { + t.Errorf("Mode %q should be invalid, got %v", s, mode) + } else if pe, ok := err.(*PortError); !ok || pe.code != e.code { + t.Errorf("Mode %q should fail with %v, got %v", s, e, err) + } + } +}