Skip to main content

open_sound_control/
bundle.rs

1use crate::message::OscMessage;
2use crate::timetag::OscTimeTag;
3use crate::helpers::{self, OscParseError, osc_string_as_bytes};
4
5/// Represents an OSC Bundle
6pub struct OscBundle {
7    pub messages: Vec<OscMessage>,
8    pub time_tag: OscTimeTag
9}
10
11impl OscBundle {
12
13  /// Construct an OscBundle from a sequence of bytes
14  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        // check we have enough bytes for the message
31        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  /// Turn an OscBundle into a sequence of bytes
46  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//==================================================================
64// Tests
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use crate::argument::OscArgument;
69
70    //------------------------------------------------------------------
71    #[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    //------------------------------------------------------------------
133    #[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      //assert_eq!(m1.)
196    }
197}