diff --git a/AUTHORS b/AUTHORS index 935d269..670ddbf 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,3 +3,4 @@ Daniel Iglesia (@monkeyswarm) Jeff Mikels (@jeffmikels) Dan Zink (@dzink) +Josh Reich (@i2pi) diff --git a/lib/src/convert.dart b/lib/src/convert.dart index 0fcca61..6498f99 100644 --- a/lib/src/convert.dart +++ b/lib/src/convert.dart @@ -25,7 +25,7 @@ abstract class DataCodec extends Codec> { // send it explicitly, so `floatCodec` should be ahead of it. static final List> codecs = List>.unmodifiable( - >[blobCodec, intCodec, floatCodec, stringCodec, doubleCodec]); + >[blobCodec, intCodec, floatCodec, stringCodec, booleanTrueCodec, booleanFalseCodec, doubleCodec]); final String typeTag; @@ -266,6 +266,73 @@ class StringEncoder extends DataEncoder { } } +/// Boolean codecs for OSC booleans ('T' = true, 'F' = false). +const BooleanTrueCodec booleanTrueCodec = BooleanTrueCodec(); +const BooleanFalseCodec booleanFalseCodec = BooleanFalseCodec(); + +class BooleanTrueCodec extends DataCodec { + const BooleanTrueCodec() : super(typeTag: 'T'); + + @override + bool appliesTo(Object? value) => value == true; + + @override + Converter, bool> get decoder => const _BooleanTrueDecoder(); + + @override + Converter> get encoder => const _BooleanTrueEncoder(); + + @override + int length(bool value) => 0; + + @override + bool toValue(String string) => true; +} + +class _BooleanTrueDecoder extends DataDecoder { + const _BooleanTrueDecoder(); + @override + bool convert(List value) => true; +} + +class _BooleanTrueEncoder extends DataEncoder { + const _BooleanTrueEncoder(); + @override + List convert(bool value) => []; +} + +class BooleanFalseCodec extends DataCodec { + const BooleanFalseCodec() : super(typeTag: 'F'); + + @override + bool appliesTo(Object? value) => value == false; + + @override + Converter, bool> get decoder => const _BooleanFalseDecoder(); + + @override + Converter> get encoder => const _BooleanFalseEncoder(); + + @override + int length(bool value) => 0; + + @override + bool toValue(String string) => false; +} + +class _BooleanFalseDecoder extends DataDecoder { + const _BooleanFalseDecoder(); + @override + bool convert(List value) => false; +} + +class _BooleanFalseEncoder extends DataEncoder { + const _BooleanFalseEncoder(); + @override + List convert(bool value) => []; +} + + class OSCMessageBuilder { final _builder = BytesBuilder(); diff --git a/test/convert_test.dart b/test/convert_test.dart index f6b2e33..2ae6462 100644 --- a/test/convert_test.dart +++ b/test/convert_test.dart @@ -100,5 +100,71 @@ void main() { expect(stringCodec.encoder.convert('foo'), [102, 111, 111, 0]); }); }); + + group('booleans', () { + test('true decode', () { + expect(booleanTrueCodec.decoder.convert([]), true); + }); + + test('true encode', () { + expect(booleanTrueCodec.encoder.convert(true), []); + }); + + test('false decode', () { + expect(booleanFalseCodec.decoder.convert([]), false); + }); + + test('false encode', () { + expect(booleanFalseCodec.encoder.convert(false), []); + }); + + test('true typeTag', () { + expect(booleanTrueCodec.typeTag, 'T'); + }); + + test('false typeTag', () { + expect(booleanFalseCodec.typeTag, 'F'); + }); + + test('true appliesTo', () { + expect(booleanTrueCodec.appliesTo(true), isTrue); + expect(booleanTrueCodec.appliesTo(false), isFalse); + }); + + test('false appliesTo', () { + expect(booleanFalseCodec.appliesTo(false), isTrue); + expect(booleanFalseCodec.appliesTo(true), isFalse); + }); + + test('length is zero', () { + expect(booleanTrueCodec.length(true), 0); + expect(booleanFalseCodec.length(false), 0); + }); + }); + + group('boolean messages', () { + test('encode true', () { + final message = OSCMessage('/bool', arguments: [true]); + final encoded = oscMessageCodec.encode(message); + final decoded = oscMessageCodec.decode(encoded); + expect(decoded.address, '/bool'); + expect(decoded.arguments, [true]); + }); + + test('encode false', () { + final message = OSCMessage('/bool', arguments: [false]); + final encoded = oscMessageCodec.encode(message); + final decoded = oscMessageCodec.decode(encoded); + expect(decoded.address, '/bool'); + expect(decoded.arguments, [false]); + }); + + test('encode mixed', () { + final message = OSCMessage('/mixed', arguments: [true, false, true]); + final encoded = oscMessageCodec.encode(message); + final decoded = oscMessageCodec.decode(encoded); + expect(decoded.arguments, [true, false, true]); + }); + }); }); }