1 module osc.bundle; 2 import std.datetime; 3 import osc.oscstring; 4 import osc.timetag; 5 import osc.message; 6 7 /++ 8 +/ 9 struct Bundle { 10 public{ 11 /// 12 this(BundleElement[] bundleElements, in SysTime utcSysTime, in bool isImmediately = false){ 13 _timeTag = TimeTag(utcSysTime, isImmediately); 14 _elements = bundleElements; 15 } 16 17 /// 18 this(in ubyte[] bundle){ 19 _timeTag = TimeTag(bundle[8..16]); 20 21 ubyte[] elements = bundle[16..$].dup; 22 do{ 23 import std.bitmanip; 24 size_t size_n = elements[0..4].peek!uint; 25 26 _elements ~= BundleElement(elements[0..4+size_n]); 27 elements = elements[4+size_n..$]; 28 }while(elements != []); 29 } 30 unittest{ 31 ubyte[] buffer = [35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 32, 47, 111, 115, 99, 105, 108, 108, 97, 116, 111, 114, 47, 52, 47, 102, 114, 101, 113, 117, 101, 110, 99, 121, 0, 44, 102, 0, 0, 67, 222, 0, 0]; 32 auto bundle = Bundle(buffer); 33 } 34 35 /// 36 string toString()const{ 37 return _opCast!string; 38 } 39 40 /// 41 ubyte[] opCast(T:ubyte[])()const{ 42 return _opCast!T; 43 } 44 45 /// 46 size_t size()const{ 47 import std.conv; 48 import std.algorithm; 49 return _header.size + 50 _timeTag.size + 51 _elements.map!(e => e.size) 52 .sum; 53 } 54 55 /// 56 const(BundleElement)[] elements()const{ 57 return _elements[]; 58 } 59 }//public 60 61 private{ 62 immutable OscString!('\0') _header = OscString("#bundle"); 63 const TimeTag _timeTag; 64 BundleElement[] _elements; 65 66 T _opCast(T)()const{ 67 import std.conv; 68 import std.algorithm; 69 return _header.to!T ~ 70 _timeTag.to!T ~ 71 _elements.map!(e => e.to!T) 72 .reduce!"a~b"; 73 } 74 }//private 75 }//struct Bundle 76 77 unittest{ 78 ubyte[] b = [35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 32, 47, 111, 115, 99, 105, 108, 108, 97, 116, 111, 114, 47, 52, 47, 102, 114, 101, 113, 117, 101, 110, 99, 121, 0, 44, 102, 0, 0, 67, 222, 0, 0]; 79 auto bundle = Bundle(b); 80 81 import osc.addresspattern; 82 assert(bundle.elements[0].message.addressPattern == [AddressPart("oscillator"), AddressPart("4"), AddressPart("frequency")]); 83 import osc.typetagstring; 84 assert(bundle.elements[0].message.typeTagString == TypeTagString("f")); 85 import std.conv; 86 assert(bundle.elements[0].message.arg!float(0) == 444.0f); 87 } 88 89 /++ 90 +/ 91 struct BundleElement { 92 public{ 93 /// 94 this(in Message message){ 95 _hasMessage = true; 96 _message = message; 97 _size = message.size; 98 99 import std.conv; 100 import std.bitmanip; 101 ubyte[] buffer = [0, 0, 0, 0]; 102 buffer.write!int(message.size.to!int, 0); 103 _sizeUbyte = buffer; 104 } 105 106 /// 107 this(in Bundle bundle){ 108 _hasBundle = true; 109 _bundle = bundle; 110 _size = bundle.size; 111 112 import std.conv; 113 import std.bitmanip; 114 ubyte[] buffer = [0, 0, 0, 0]; 115 buffer.write!int(bundle.size.to!int, 0); 116 _sizeUbyte = buffer; 117 } 118 119 /// 120 this(in ubyte[] bundleElement){ 121 _size = bundleElement.length-4; 122 123 _hasBundle = bundleElement[4] == 0x23; 124 _hasMessage = bundleElement[4] != 0x23; 125 126 if(_hasBundle){ 127 _bundle = Bundle(bundleElement[4..$]); 128 } 129 if(_hasMessage){ 130 _message = Message(bundleElement[4..$]); 131 } 132 } 133 134 /// 135 string toString()const{ 136 import std.conv:to; 137 import std.algorithm; 138 if(_hasMessage){ 139 return _size.to!string ~ _message.to!string; 140 }else if(_hasBundle){ 141 return _size.to!string ~ _bundle.to!string; 142 }else{ 143 return ""; 144 } 145 } 146 147 /// 148 ubyte[] opCast(T:ubyte[])()const{ 149 import std.conv; 150 if(_hasMessage){ 151 return _sizeUbyte ~ _message.to!(ubyte[]); 152 }else if(_hasBundle){ 153 return _sizeUbyte ~ _bundle.to!(ubyte[]); 154 }else{ 155 return []; 156 } 157 } 158 159 size_t size()const{ 160 return _size; 161 } 162 163 /// 164 const(Message) message()const{ 165 return _message; 166 } 167 168 /// 169 const(Bundle) bundle()const{ 170 return _bundle; 171 } 172 173 /// 174 bool hasMessage()const{ 175 return _hasMessage; 176 } 177 178 /// 179 bool hasBundle()const{ 180 return _hasBundle; 181 } 182 }//public 183 184 private{ 185 size_t _size; 186 ubyte[] _sizeUbyte; 187 bool _hasMessage = true; 188 bool _hasBundle = true; 189 const Message _message; 190 const Bundle _bundle; 191 }//private 192 }//struct BundleElement 193 unittest{ 194 ubyte[] bundle = [35, 98, 117, 110, 100, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 32, 47, 111, 115, 99, 105, 108, 108, 97, 116, 111, 114, 47, 52, 47, 102, 114, 101, 113, 117, 101, 110, 99, 121, 0, 44, 102, 0, 0, 67, 222, 0, 0]; 195 ubyte[] size = [0, 0, 0, 0]; 196 import std.bitmanip; 197 import std.conv; 198 size.write!int(bundle.length.to!int, 0); 199 auto bundleElement = BundleElement(size ~ bundle); 200 201 import osc.addresspattern; 202 assert(bundleElement.bundle.elements[0].message.addressPattern == [AddressPart("oscillator"), AddressPart("4"), AddressPart("frequency")]); 203 }