1use crate::message::OscMessage;
2use crate::timetag::OscTimeTag;
3use crate::helpers::{self, OscParseError, osc_string_as_bytes};
4
5pub struct OscBundle {
7 pub messages: Vec<OscMessage>,
8 pub time_tag: OscTimeTag
9}
10
11impl OscBundle {
12
13 pub fn from_bytes(bytes: &[u8]) -> Result<Self, OscParseError> {
15
16 if ! helpers::is_bundle(bytes) {
17 return Err(OscParseError::InvalidFormat)
18 }
19
20 let time_tag = OscTimeTag::from_bytes(&bytes[8..16])?;
21
22 let mut messages = vec![];
23 let mut offset = 16;
24
25 while offset < bytes.len() {
26 let size_bytes = bytes.get(offset..offset + 4).ok_or(OscParseError::NotEnoughData)?;
27 let message_size = u32::from_be_bytes(size_bytes.try_into().unwrap()) as usize;
28 offset += 4;
29
30 let message_bytes = bytes.get(offset..offset + message_size).ok_or(OscParseError::NotEnoughData)?;
32 messages.push(OscMessage::from_bytes(message_bytes)?);
33
34 offset += message_size;
35 }
36
37 let bundle = OscBundle {
38 messages,
39 time_tag
40 };
41
42 Ok(bundle)
43 }
44
45 pub fn to_bytes(&self) -> Vec<u8> {
47 let mut bytes = osc_string_as_bytes("#bundle");
48
49 bytes.extend (self.time_tag.to_bytes());
50
51 for message in &self.messages {
52 let message_bytes = message.to_bytes();
53 let message_size = message_bytes.len() as u32;
54 bytes.extend (&message_size.to_be_bytes());
55 bytes.extend (message_bytes);
56 }
57
58 return bytes
59 }
60}
61
62
63#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::argument::OscArgument;
69
70 #[test]
72 fn test_bundle_to_bytes() {
73 let time_tag = OscTimeTag::now();
74
75 let m1 = OscMessage {
76 address: String::from("/oscillator/4/frequency"),
77 arguments: vec![
78 OscArgument::Float32(440.0)
79 ]
80 };
81
82 let m2 = OscMessage {
83 address: String::from("/foo"),
84 arguments: vec![
85 OscArgument::Int32(1000),
86 OscArgument::Int32(-1),
87 OscArgument::String("hello".to_string()),
88 OscArgument::Float32(1.234),
89 OscArgument::Float32(5.678)
90 ]
91 };
92
93 let mut expected_bytes = osc_string_as_bytes("#bundle");
94 expected_bytes.extend(time_tag.to_bytes().to_vec());
95 expected_bytes.extend (32_u32.to_be_bytes());
96 expected_bytes.extend (vec![
97 0x2f, 0x6f, 0x73, 0x63,
98 0x69, 0x6c, 0x6c, 0x61,
99 0x74, 0x6f, 0x72, 0x2f,
100 0x34, 0x2f, 0x66, 0x72,
101 0x65, 0x71, 0x75, 0x65,
102 0x6e, 0x63, 0x79, 0x00,
103 0x2c, 0x66, 0x00, 0x00,
104 0x43, 0xdc, 0x00, 0x00,
105 ]);
106 expected_bytes.extend (40_u32.to_be_bytes());
107 expected_bytes.extend (vec![
108 0x2f, 0x66, 0x6f, 0x6f,
109 0x00, 0x00, 0x00, 0x00,
110 0x2c, 0x69, 0x69, 0x73,
111 0x66, 0x66, 0x00, 0x00,
112 0x00, 0x00, 0x03, 0xe8,
113 0xff, 0xff, 0xff, 0xff,
114 0x68, 0x65, 0x6c, 0x6c,
115 0x6f, 0x00, 0x00, 0x00,
116 0x3f, 0x9d, 0xf3, 0xb6,
117 0x40, 0xb5, 0xb2, 0x2d,
118 ]);
119
120 let bundle = OscBundle {
121 time_tag,
122 messages: vec![
123 m1, m2
124 ]
125 };
126
127 let bytes = bundle.to_bytes();
128 assert_eq!(bytes, expected_bytes);
129
130 }
131
132 #[test]
134 fn test_bundle_from_bytes() {
135 let time_tag = OscTimeTag::now();
136
137 let mut bundle_bytes = osc_string_as_bytes("#bundle");
138 bundle_bytes.extend(time_tag.to_bytes().to_vec());
139 bundle_bytes.extend (32_u32.to_be_bytes());
140 bundle_bytes.extend (vec![
141 0x2f, 0x6f, 0x73, 0x63,
142 0x69, 0x6c, 0x6c, 0x61,
143 0x74, 0x6f, 0x72, 0x2f,
144 0x34, 0x2f, 0x66, 0x72,
145 0x65, 0x71, 0x75, 0x65,
146 0x6e, 0x63, 0x79, 0x00,
147 0x2c, 0x66, 0x00, 0x00,
148 0x43, 0xdc, 0x00, 0x00,
149 ]);
150 bundle_bytes.extend (40_u32.to_be_bytes());
151 bundle_bytes.extend (vec![
152 0x2f, 0x66, 0x6f, 0x6f,
153 0x00, 0x00, 0x00, 0x00,
154 0x2c, 0x69, 0x69, 0x73,
155 0x66, 0x66, 0x00, 0x00,
156 0x00, 0x00, 0x03, 0xe8,
157 0xff, 0xff, 0xff, 0xff,
158 0x68, 0x65, 0x6c, 0x6c,
159 0x6f, 0x00, 0x00, 0x00,
160 0x3f, 0x9d, 0xf3, 0xb6,
161 0x40, 0xb5, 0xb2, 0x2d,
162 ]);
163
164 let result = OscBundle::from_bytes(&bundle_bytes);
165
166 assert!(result.is_ok());
167
168 let bundle = result.unwrap();
169
170 assert_eq!(bundle.messages.len(), 2);
171
172 let r1 = bundle.messages.get(0);
173 let r2 = bundle.messages.get(1);
174
175 assert!(r1.is_some());
176 assert!(r2.is_some());
177
178 let m1 = r1.unwrap();
179 let m2 = r2.unwrap();
180
181 assert_eq!(m1.address, "/oscillator/4/frequency");
182 assert_eq!(m1.arguments.len(), 1);
183 assert_eq!(m1.arguments, vec![OscArgument::Float32(440.0)]);
184
185 assert_eq!(m2.address, "/foo");
186 assert_eq!(m2.arguments.len(), 5);
187 assert_eq!(m2.arguments, vec![
188 OscArgument::Int32(1000),
189 OscArgument::Int32(-1),
190 OscArgument::String("hello".to_string()),
191 OscArgument::Float32(1.234),
192 OscArgument::Float32(5.678)
193 ]);
194
195 }
197}