1#![doc = include_str!("flex_data/README.md")]
2
3use crate::{
4 buffer::{BufferMut, Ump},
5 detail::{
6 property::{Property, ReadProperty, WriteProperty},
7 BitOps,
8 },
9};
10
11mod packet;
12mod text;
13
14mod set_chord_name;
15mod set_key_signature;
16mod set_metronome;
17mod set_tempo;
18mod set_time_signature;
19mod tonic;
20mod unknown_metadata_text;
21mod project_name {
22 use crate::{detail::common_properties, flex_data};
23
24 const BANK: u8 = super::METADATA_TEXT_BANK;
25 const STATUS: u8 = 0x1;
26
27 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
31 struct ProjectName {
32 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
33 ump_type: (),
34 #[property(flex_data::GroupProperty)]
35 group: crate::ux::u4,
36 #[property(flex_data::OptionalChannelProperty)]
37 optional_channel: Option<crate::ux::u4>,
38 #[property(flex_data::BankProperty<BANK>)]
39 bank: (),
40 #[property(flex_data::StatusProperty<{STATUS}>)]
41 status: (),
42 #[property(flex_data::ConsistentFormatsProperty)]
43 #[readonly]
44 consisten_formats: (),
45 #[property(flex_data::text::TextWriteStrProperty)]
46 #[writeonly]
47 #[resize]
48 text: &str,
49 #[property(flex_data::text::TextReadBytesProperty)]
50 #[readonly]
51 text_bytes: flex_data::text::TextBytesIterator,
52 #[property(flex_data::text::TextReadStringProperty)]
53 #[readonly]
54 #[std]
55 text: std::string::String,
56 }
57
58 impl<B: crate::buffer::Ump> crate::traits::Size<B> for ProjectName<B> {
59 fn size(&self) -> usize {
60 flex_data::flex_data_dyn_size(&self.0)
61 }
62 }
63 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for ProjectName<B> {}
64}
65mod composition_name {
66 use crate::{detail::common_properties, flex_data};
67
68 const BANK: u8 = super::METADATA_TEXT_BANK;
69 const STATUS: u8 = 0x2;
70
71 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
75 struct CompositionName {
76 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
77 ump_type: (),
78 #[property(flex_data::GroupProperty)]
79 group: crate::ux::u4,
80 #[property(flex_data::OptionalChannelProperty)]
81 optional_channel: Option<crate::ux::u4>,
82 #[property(flex_data::BankProperty<BANK>)]
83 bank: (),
84 #[property(flex_data::StatusProperty<{STATUS}>)]
85 status: (),
86 #[property(flex_data::ConsistentFormatsProperty)]
87 #[readonly]
88 consisten_formats: (),
89 #[property(flex_data::text::TextWriteStrProperty)]
90 #[writeonly]
91 #[resize]
92 text: &str,
93 #[property(flex_data::text::TextReadBytesProperty)]
94 #[readonly]
95 text_bytes: flex_data::text::TextBytesIterator,
96 #[property(flex_data::text::TextReadStringProperty)]
97 #[readonly]
98 #[std]
99 text: std::string::String,
100 }
101
102 impl<B: crate::buffer::Ump> crate::traits::Size<B> for CompositionName<B> {
103 fn size(&self) -> usize {
104 flex_data::flex_data_dyn_size(&self.0)
105 }
106 }
107 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for CompositionName<B> {}
108}
109mod midi_clip_name {
110 use crate::{detail::common_properties, flex_data};
111
112 const BANK: u8 = super::METADATA_TEXT_BANK;
113 const STATUS: u8 = 0x3;
114
115 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
119 struct MidiClipName {
120 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
121 ump_type: (),
122 #[property(flex_data::GroupProperty)]
123 group: crate::ux::u4,
124 #[property(flex_data::OptionalChannelProperty)]
125 optional_channel: Option<crate::ux::u4>,
126 #[property(flex_data::BankProperty<BANK>)]
127 bank: (),
128 #[property(flex_data::StatusProperty<{STATUS}>)]
129 status: (),
130 #[property(flex_data::ConsistentFormatsProperty)]
131 #[readonly]
132 consisten_formats: (),
133 #[property(flex_data::text::TextWriteStrProperty)]
134 #[writeonly]
135 #[resize]
136 text: &str,
137 #[property(flex_data::text::TextReadBytesProperty)]
138 #[readonly]
139 text_bytes: flex_data::text::TextBytesIterator,
140 #[property(flex_data::text::TextReadStringProperty)]
141 #[readonly]
142 #[std]
143 text: std::string::String,
144 }
145
146 impl<B: crate::buffer::Ump> crate::traits::Size<B> for MidiClipName<B> {
147 fn size(&self) -> usize {
148 flex_data::flex_data_dyn_size(&self.0)
149 }
150 }
151 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for MidiClipName<B> {}
152}
153mod copyright_notice {
154 use crate::{detail::common_properties, flex_data};
155
156 const BANK: u8 = super::METADATA_TEXT_BANK;
157 const STATUS: u8 = 0x4;
158
159 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
163 struct CopyrightNotice {
164 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
165 ump_type: (),
166 #[property(flex_data::GroupProperty)]
167 group: crate::ux::u4,
168 #[property(flex_data::OptionalChannelProperty)]
169 optional_channel: Option<crate::ux::u4>,
170 #[property(flex_data::BankProperty<BANK>)]
171 bank: (),
172 #[property(flex_data::StatusProperty<{STATUS}>)]
173 status: (),
174 #[property(flex_data::ConsistentFormatsProperty)]
175 #[readonly]
176 consisten_formats: (),
177 #[property(flex_data::text::TextWriteStrProperty)]
178 #[writeonly]
179 #[resize]
180 text: &str,
181 #[property(flex_data::text::TextReadBytesProperty)]
182 #[readonly]
183 text_bytes: flex_data::text::TextBytesIterator,
184 #[property(flex_data::text::TextReadStringProperty)]
185 #[readonly]
186 #[std]
187 text: std::string::String,
188 }
189
190 impl<B: crate::buffer::Ump> crate::traits::Size<B> for CopyrightNotice<B> {
191 fn size(&self) -> usize {
192 flex_data::flex_data_dyn_size(&self.0)
193 }
194 }
195 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for CopyrightNotice<B> {}
196}
197mod composer_name {
198 use crate::{detail::common_properties, flex_data};
199
200 const BANK: u8 = super::METADATA_TEXT_BANK;
201 const STATUS: u8 = 0x5;
202
203 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
207 struct ComposerName {
208 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
209 ump_type: (),
210 #[property(flex_data::GroupProperty)]
211 group: crate::ux::u4,
212 #[property(flex_data::OptionalChannelProperty)]
213 optional_channel: Option<crate::ux::u4>,
214 #[property(flex_data::BankProperty<BANK>)]
215 bank: (),
216 #[property(flex_data::StatusProperty<{STATUS}>)]
217 status: (),
218 #[property(flex_data::ConsistentFormatsProperty)]
219 #[readonly]
220 consisten_formats: (),
221 #[property(flex_data::text::TextWriteStrProperty)]
222 #[writeonly]
223 #[resize]
224 name: &str,
225 #[property(flex_data::text::TextReadBytesProperty)]
226 #[readonly]
227 name_bytes: flex_data::text::TextBytesIterator,
228 #[property(flex_data::text::TextReadStringProperty)]
229 #[readonly]
230 #[std]
231 name: std::string::String,
232 }
233
234 impl<B: crate::buffer::Ump> crate::traits::Size<B> for ComposerName<B> {
235 fn size(&self) -> usize {
236 flex_data::flex_data_dyn_size(&self.0)
237 }
238 }
239 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for ComposerName<B> {}
240}
241mod lyricist_name {
242 use crate::{detail::common_properties, flex_data};
243
244 const BANK: u8 = super::METADATA_TEXT_BANK;
245 const STATUS: u8 = 0x6;
246
247 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
251 struct LyricistName {
252 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
253 ump_type: (),
254 #[property(flex_data::GroupProperty)]
255 group: crate::ux::u4,
256 #[property(flex_data::OptionalChannelProperty)]
257 optional_channel: Option<crate::ux::u4>,
258 #[property(flex_data::BankProperty<BANK>)]
259 bank: (),
260 #[property(flex_data::StatusProperty<{STATUS}>)]
261 status: (),
262 #[property(flex_data::ConsistentFormatsProperty)]
263 #[readonly]
264 consisten_formats: (),
265 #[property(flex_data::text::TextWriteStrProperty)]
266 #[writeonly]
267 #[resize]
268 text: &str,
269 #[property(flex_data::text::TextReadBytesProperty)]
270 #[readonly]
271 text_bytes: flex_data::text::TextBytesIterator,
272 #[property(flex_data::text::TextReadStringProperty)]
273 #[readonly]
274 #[std]
275 text: std::string::String,
276 }
277
278 impl<B: crate::buffer::Ump> crate::traits::Size<B> for LyricistName<B> {
279 fn size(&self) -> usize {
280 flex_data::flex_data_dyn_size(&self.0)
281 }
282 }
283 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for LyricistName<B> {}
284}
285mod arranger_name {
286 use crate::{detail::common_properties, flex_data};
287
288 const BANK: u8 = super::METADATA_TEXT_BANK;
289 const STATUS: u8 = 0x7;
290
291 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
295 struct ArrangerName {
296 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
297 ump_type: (),
298 #[property(flex_data::GroupProperty)]
299 group: crate::ux::u4,
300 #[property(flex_data::OptionalChannelProperty)]
301 optional_channel: Option<crate::ux::u4>,
302 #[property(flex_data::BankProperty<BANK>)]
303 bank: (),
304 #[property(flex_data::StatusProperty<{STATUS}>)]
305 status: (),
306 #[property(flex_data::ConsistentFormatsProperty)]
307 #[readonly]
308 consisten_formats: (),
309 #[property(flex_data::text::TextWriteStrProperty)]
310 #[writeonly]
311 #[resize]
312 text: &str,
313 #[property(flex_data::text::TextReadBytesProperty)]
314 #[readonly]
315 text_bytes: flex_data::text::TextBytesIterator,
316 #[property(flex_data::text::TextReadStringProperty)]
317 #[readonly]
318 #[std]
319 text: std::string::String,
320 }
321
322 impl<B: crate::buffer::Ump> crate::traits::Size<B> for ArrangerName<B> {
323 fn size(&self) -> usize {
324 flex_data::flex_data_dyn_size(&self.0)
325 }
326 }
327 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for ArrangerName<B> {}
328}
329mod publisher_name {
330 use crate::{detail::common_properties, flex_data};
331
332 const BANK: u8 = super::METADATA_TEXT_BANK;
333 const STATUS: u8 = 0x8;
334
335 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
339 struct PublisherName {
340 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
341 ump_type: (),
342 #[property(flex_data::GroupProperty)]
343 group: crate::ux::u4,
344 #[property(flex_data::OptionalChannelProperty)]
345 optional_channel: Option<crate::ux::u4>,
346 #[property(flex_data::BankProperty<BANK>)]
347 bank: (),
348 #[property(flex_data::StatusProperty<{STATUS}>)]
349 status: (),
350 #[property(flex_data::ConsistentFormatsProperty)]
351 #[readonly]
352 consisten_formats: (),
353 #[property(flex_data::text::TextWriteStrProperty)]
354 #[writeonly]
355 #[resize]
356 text: &str,
357 #[property(flex_data::text::TextReadBytesProperty)]
358 #[readonly]
359 text_bytes: flex_data::text::TextBytesIterator,
360 #[property(flex_data::text::TextReadStringProperty)]
361 #[readonly]
362 #[std]
363 text: std::string::String,
364 }
365
366 impl<B: crate::buffer::Ump> crate::traits::Size<B> for PublisherName<B> {
367 fn size(&self) -> usize {
368 flex_data::flex_data_dyn_size(&self.0)
369 }
370 }
371 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for PublisherName<B> {}
372}
373mod primary_performer_name {
374 use crate::{detail::common_properties, flex_data};
375
376 const BANK: u8 = super::METADATA_TEXT_BANK;
377 const STATUS: u8 = 0x9;
378
379 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
383 struct PrimaryPerformerName {
384 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
385 ump_type: (),
386 #[property(flex_data::GroupProperty)]
387 group: crate::ux::u4,
388 #[property(flex_data::OptionalChannelProperty)]
389 optional_channel: Option<crate::ux::u4>,
390 #[property(flex_data::BankProperty<BANK>)]
391 bank: (),
392 #[property(flex_data::StatusProperty<{STATUS}>)]
393 status: (),
394 #[property(flex_data::ConsistentFormatsProperty)]
395 #[readonly]
396 consisten_formats: (),
397 #[property(flex_data::text::TextWriteStrProperty)]
398 #[writeonly]
399 #[resize]
400 text: &str,
401 #[property(flex_data::text::TextReadBytesProperty)]
402 #[readonly]
403 text_bytes: flex_data::text::TextBytesIterator,
404 #[property(flex_data::text::TextReadStringProperty)]
405 #[readonly]
406 #[std]
407 text: std::string::String,
408 }
409
410 impl<B: crate::buffer::Ump> crate::traits::Size<B> for PrimaryPerformerName<B> {
411 fn size(&self) -> usize {
412 flex_data::flex_data_dyn_size(&self.0)
413 }
414 }
415 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for PrimaryPerformerName<B> {}
416}
417mod accompanying_performer_name {
418 use crate::{detail::common_properties, flex_data};
419
420 const BANK: u8 = super::METADATA_TEXT_BANK;
421 const STATUS: u8 = 0xA;
422
423 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
427 struct AccompanyingPerformerName {
428 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
429 ump_type: (),
430 #[property(flex_data::GroupProperty)]
431 group: crate::ux::u4,
432 #[property(flex_data::OptionalChannelProperty)]
433 optional_channel: Option<crate::ux::u4>,
434 #[property(flex_data::BankProperty<BANK>)]
435 bank: (),
436 #[property(flex_data::StatusProperty<{STATUS}>)]
437 status: (),
438 #[property(flex_data::ConsistentFormatsProperty)]
439 #[readonly]
440 consisten_formats: (),
441 #[property(flex_data::text::TextWriteStrProperty)]
442 #[writeonly]
443 #[resize]
444 text: &str,
445 #[property(flex_data::text::TextReadBytesProperty)]
446 #[readonly]
447 text_bytes: flex_data::text::TextBytesIterator,
448 #[property(flex_data::text::TextReadStringProperty)]
449 #[readonly]
450 #[std]
451 text: std::string::String,
452 }
453
454 impl<B: crate::buffer::Ump> crate::traits::Size<B> for AccompanyingPerformerName<B> {
455 fn size(&self) -> usize {
456 flex_data::flex_data_dyn_size(&self.0)
457 }
458 }
459 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for AccompanyingPerformerName<B> {}
460}
461mod recording_date {
462 use crate::{detail::common_properties, flex_data};
463
464 const BANK: u8 = super::METADATA_TEXT_BANK;
465 const STATUS: u8 = 0xB;
466
467 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
471 struct RecordingDate {
472 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
473 ump_type: (),
474 #[property(flex_data::GroupProperty)]
475 group: crate::ux::u4,
476 #[property(flex_data::OptionalChannelProperty)]
477 optional_channel: Option<crate::ux::u4>,
478 #[property(flex_data::BankProperty<BANK>)]
479 bank: (),
480 #[property(flex_data::StatusProperty<{STATUS}>)]
481 status: (),
482 #[property(flex_data::ConsistentFormatsProperty)]
483 #[readonly]
484 consisten_formats: (),
485 #[property(flex_data::text::TextWriteStrProperty)]
486 #[writeonly]
487 #[resize]
488 text: &str,
489 #[property(flex_data::text::TextReadBytesProperty)]
490 #[readonly]
491 text_bytes: flex_data::text::TextBytesIterator,
492 #[property(flex_data::text::TextReadStringProperty)]
493 #[readonly]
494 #[std]
495 text: std::string::String,
496 }
497
498 impl<B: crate::buffer::Ump> crate::traits::Size<B> for RecordingDate<B> {
499 fn size(&self) -> usize {
500 flex_data::flex_data_dyn_size(&self.0)
501 }
502 }
503 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for RecordingDate<B> {}
504}
505mod recording_location {
506 use crate::{detail::common_properties, flex_data};
507
508 const BANK: u8 = super::METADATA_TEXT_BANK;
509 const STATUS: u8 = 0xC;
510
511 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
515 struct RecordingLocation {
516 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
517 ump_type: (),
518 #[property(flex_data::GroupProperty)]
519 group: crate::ux::u4,
520 #[property(flex_data::OptionalChannelProperty)]
521 optional_channel: Option<crate::ux::u4>,
522 #[property(flex_data::BankProperty<BANK>)]
523 bank: (),
524 #[property(flex_data::StatusProperty<{STATUS}>)]
525 status: (),
526 #[property(flex_data::ConsistentFormatsProperty)]
527 #[readonly]
528 consisten_formats: (),
529 #[property(flex_data::text::TextWriteStrProperty)]
530 #[writeonly]
531 #[resize]
532 text: &str,
533 #[property(flex_data::text::TextReadBytesProperty)]
534 #[readonly]
535 text_bytes: flex_data::text::TextBytesIterator,
536 #[property(flex_data::text::TextReadStringProperty)]
537 #[readonly]
538 #[std]
539 text: std::string::String,
540 }
541
542 impl<B: crate::buffer::Ump> crate::traits::Size<B> for RecordingLocation<B> {
543 fn size(&self) -> usize {
544 flex_data::flex_data_dyn_size(&self.0)
545 }
546 }
547 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for RecordingLocation<B> {}
548}
549mod unknown_performance_text {
550 use crate::{detail::common_properties, flex_data};
551
552 const BANK: u8 = super::PERFORMANCE_TEXT_BANK;
553 const STATUS: u8 = 0x0;
554
555 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
559 struct UnknownPerformanceText {
560 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
561 ump_type: (),
562 #[property(flex_data::GroupProperty)]
563 group: crate::ux::u4,
564 #[property(flex_data::OptionalChannelProperty)]
565 optional_channel: Option<crate::ux::u4>,
566 #[property(flex_data::BankProperty<BANK>)]
567 bank: (),
568 #[property(flex_data::StatusProperty<{STATUS}>)]
569 status: (),
570 #[property(flex_data::ConsistentFormatsProperty)]
571 #[readonly]
572 consisten_formats: (),
573 #[property(flex_data::text::TextWriteStrProperty)]
574 #[writeonly]
575 #[resize]
576 text: &str,
577 #[property(flex_data::text::TextReadBytesProperty)]
578 #[readonly]
579 text_bytes: flex_data::text::TextBytesIterator,
580 #[property(flex_data::text::TextReadStringProperty)]
581 #[readonly]
582 #[std]
583 text: std::string::String,
584 }
585
586 impl<B: crate::buffer::Ump> crate::traits::Size<B> for UnknownPerformanceText<B> {
587 fn size(&self) -> usize {
588 flex_data::flex_data_dyn_size(&self.0)
589 }
590 }
591 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for UnknownPerformanceText<B> {}
592}
593mod lyrics {
594 use crate::{detail::common_properties, flex_data};
595
596 const BANK: u8 = super::PERFORMANCE_TEXT_BANK;
597 const STATUS: u8 = 0x1;
598
599 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
603 struct Lyrics {
604 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
605 ump_type: (),
606 #[property(flex_data::GroupProperty)]
607 group: crate::ux::u4,
608 #[property(flex_data::OptionalChannelProperty)]
609 optional_channel: Option<crate::ux::u4>,
610 #[property(flex_data::BankProperty<BANK>)]
611 bank: (),
612 #[property(flex_data::StatusProperty<{STATUS}>)]
613 status: (),
614 #[property(flex_data::ConsistentFormatsProperty)]
615 #[readonly]
616 consisten_formats: (),
617 #[property(flex_data::text::TextWriteStrProperty)]
618 #[writeonly]
619 #[resize]
620 text: &str,
621 #[property(flex_data::text::TextReadBytesProperty)]
622 #[readonly]
623 text_bytes: flex_data::text::TextBytesIterator,
624 #[property(flex_data::text::TextReadStringProperty)]
625 #[readonly]
626 #[std]
627 text: std::string::String,
628 }
629
630 impl<B: crate::buffer::Ump> crate::traits::Size<B> for Lyrics<B> {
631 fn size(&self) -> usize {
632 flex_data::flex_data_dyn_size(&self.0)
633 }
634 }
635 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for Lyrics<B> {}
636}
637mod lyrics_language {
638 use crate::{detail::common_properties, flex_data};
639
640 const BANK: u8 = super::PERFORMANCE_TEXT_BANK;
641 const STATUS: u8 = 0x2;
642
643 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
647 struct LyricsLanguage {
648 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
649 ump_type: (),
650 #[property(flex_data::GroupProperty)]
651 group: crate::ux::u4,
652 #[property(flex_data::OptionalChannelProperty)]
653 optional_channel: Option<crate::ux::u4>,
654 #[property(flex_data::BankProperty<BANK>)]
655 bank: (),
656 #[property(flex_data::StatusProperty<{STATUS}>)]
657 status: (),
658 #[property(flex_data::ConsistentFormatsProperty)]
659 #[readonly]
660 consisten_formats: (),
661 #[property(flex_data::text::TextWriteStrProperty)]
662 #[writeonly]
663 #[resize]
664 text: &str,
665 #[property(flex_data::text::TextReadBytesProperty)]
666 #[readonly]
667 text_bytes: flex_data::text::TextBytesIterator,
668 #[property(flex_data::text::TextReadStringProperty)]
669 #[readonly]
670 #[std]
671 text: std::string::String,
672 }
673
674 impl<B: crate::buffer::Ump> crate::traits::Size<B> for LyricsLanguage<B> {
675 fn size(&self) -> usize {
676 flex_data::flex_data_dyn_size(&self.0)
677 }
678 }
679 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for LyricsLanguage<B> {}
680}
681mod ruby {
682 use crate::{detail::common_properties, flex_data};
683
684 const BANK: u8 = super::PERFORMANCE_TEXT_BANK;
685 const STATUS: u8 = 0x3;
686
687 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
691 struct Ruby {
692 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
693 ump_type: (),
694 #[property(flex_data::GroupProperty)]
695 group: crate::ux::u4,
696 #[property(flex_data::OptionalChannelProperty)]
697 optional_channel: Option<crate::ux::u4>,
698 #[property(flex_data::BankProperty<BANK>)]
699 bank: (),
700 #[property(flex_data::StatusProperty<{STATUS}>)]
701 status: (),
702 #[property(flex_data::ConsistentFormatsProperty)]
703 #[readonly]
704 consisten_formats: (),
705 #[property(flex_data::text::TextWriteStrProperty)]
706 #[writeonly]
707 #[resize]
708 text: &str,
709 #[property(flex_data::text::TextReadBytesProperty)]
710 #[readonly]
711 text_bytes: flex_data::text::TextBytesIterator,
712 #[property(flex_data::text::TextReadStringProperty)]
713 #[readonly]
714 #[std]
715 text: std::string::String,
716 }
717
718 impl<B: crate::buffer::Ump> crate::traits::Size<B> for Ruby<B> {
719 fn size(&self) -> usize {
720 flex_data::flex_data_dyn_size(&self.0)
721 }
722 }
723 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for Ruby<B> {}
724}
725mod ruby_language {
726 use crate::{detail::common_properties, flex_data};
727
728 const BANK: u8 = super::PERFORMANCE_TEXT_BANK;
729 const STATUS: u8 = 0x4;
730
731 #[midi2_proc::generate_message(Via(crate::flex_data::FlexData), MinSizeUmp(4))]
735 struct RubyLanguage {
736 #[property(common_properties::UmpMessageTypeProperty<{flex_data::UMP_MESSAGE_TYPE}>)]
737 ump_type: (),
738 #[property(flex_data::GroupProperty)]
739 group: crate::ux::u4,
740 #[property(flex_data::OptionalChannelProperty)]
741 optional_channel: Option<crate::ux::u4>,
742 #[property(flex_data::BankProperty<BANK>)]
743 bank: (),
744 #[property(flex_data::StatusProperty<{STATUS}>)]
745 status: (),
746 #[property(flex_data::ConsistentFormatsProperty)]
747 #[readonly]
748 consisten_formats: (),
749 #[property(flex_data::text::TextWriteStrProperty)]
750 #[writeonly]
751 #[resize]
752 text: &str,
753 #[property(flex_data::text::TextReadBytesProperty)]
754 #[readonly]
755 text_bytes: flex_data::text::TextBytesIterator,
756 #[property(flex_data::text::TextReadStringProperty)]
757 #[readonly]
758 #[std]
759 text: std::string::String,
760 }
761
762 impl<B: crate::buffer::Ump> crate::traits::Size<B> for RubyLanguage<B> {
763 fn size(&self) -> usize {
764 flex_data::flex_data_dyn_size(&self.0)
765 }
766 }
767 impl<B: crate::buffer::Ump> flex_data::FlexDataMessage<B> for RubyLanguage<B> {}
768}
769
770pub use accompanying_performer_name::*;
771pub use arranger_name::*;
772pub use composer_name::*;
773pub use composition_name::*;
774pub use copyright_notice::*;
775pub use lyricist_name::*;
776pub use lyrics::*;
777pub use lyrics_language::*;
778pub use midi_clip_name::*;
779pub use packet::{Format, Packet};
780pub use primary_performer_name::*;
781pub use project_name::*;
782pub use publisher_name::*;
783pub use recording_date::*;
784pub use recording_location::*;
785pub use ruby::*;
786pub use ruby_language::*;
787pub use set_chord_name::{
788 Alteration, ChordType, SetChordName, SharpsFlats as SetChordNameSharpsFlats,
789};
790pub use set_key_signature::{SetKeySignature, SharpsFlats as SetKeySignatureSharpsFlats};
791pub use set_metronome::*;
792pub use set_tempo::*;
793pub use set_time_signature::*;
794pub use text::TextBytesIterator;
795pub use tonic::Tonic;
796pub use unknown_metadata_text::*;
797pub use unknown_performance_text::*;
798
799pub(crate) const UMP_MESSAGE_TYPE: u8 = 0xD;
800pub(crate) const COMPLETE_FORMAT: u8 = 0x0;
801pub(crate) const START_FORMAT: u8 = 0x1;
802pub(crate) const CONTINUE_FORMAT: u8 = 0x2;
803pub(crate) const END_FORMAT: u8 = 0x3;
804pub(crate) const SETUP_AND_PERFORMANCE_BANK: u8 = 0x0;
805pub(crate) const METADATA_TEXT_BANK: u8 = 0x1;
806pub(crate) const PERFORMANCE_TEXT_BANK: u8 = 0x2;
807
808#[derive(
809 derive_more::From,
810 midi2_proc::Data,
811 midi2_proc::Packets,
812 midi2_proc::Grouped,
813 midi2_proc::RebufferFrom,
814 midi2_proc::TryRebufferFrom,
815 Clone,
816 Copy,
817 Debug,
818 PartialEq,
819 Eq,
820)]
821#[non_exhaustive]
822pub enum FlexData<B: crate::buffer::Ump> {
823 SetChordName(set_chord_name::SetChordName<B>),
824 SetKeySignature(set_key_signature::SetKeySignature<B>),
825 SetMetronome(set_metronome::SetMetronome<B>),
826 SetTempo(set_tempo::SetTempo<B>),
827 SetTimeSignature(set_time_signature::SetTimeSignature<B>),
828 UnknownMetadataText(unknown_metadata_text::UnknownMetadataText<B>),
829 ProjectName(project_name::ProjectName<B>),
830 CompositionName(composition_name::CompositionName<B>),
831 MidiClipName(midi_clip_name::MidiClipName<B>),
832 CopyrightNotice(copyright_notice::CopyrightNotice<B>),
833 ComposerName(composer_name::ComposerName<B>),
834 LyricistName(lyricist_name::LyricistName<B>),
835 ArrangerName(arranger_name::ArrangerName<B>),
836 PublisherName(publisher_name::PublisherName<B>),
837 PrimaryPerformerName(primary_performer_name::PrimaryPerformerName<B>),
838 AccompanyingPerformerName(accompanying_performer_name::AccompanyingPerformerName<B>),
839 RecordingDate(recording_date::RecordingDate<B>),
840 RecordingLocation(recording_location::RecordingLocation<B>),
841 UnknownPerformanceText(unknown_performance_text::UnknownPerformanceText<B>),
842 Lyrics(lyrics::Lyrics<B>),
843 LyricsLanguage(lyrics_language::LyricsLanguage<B>),
844 Ruby(ruby::Ruby<B>),
845 RubyLanguage(ruby_language::RubyLanguage<B>),
846}
847
848impl<'a> TryFrom<&'a [u32]> for FlexData<&'a [u32]> {
849 type Error = crate::error::InvalidData;
850 fn try_from(value: &'a [u32]) -> Result<Self, Self::Error> {
851 use FlexData::*;
852 if value.is_empty() {
853 return Err(crate::error::InvalidData(
854 crate::detail::common_err_strings::ERR_SLICE_TOO_SHORT,
855 ));
856 };
857 Ok(match value[0].word(1) {
858 0x00_00 => SetTempo(set_tempo::SetTempo::try_from(value)?),
859 0x00_01 => SetTimeSignature(set_time_signature::SetTimeSignature::try_from(value)?),
860 0x00_02 => SetMetronome(set_metronome::SetMetronome::try_from(value)?),
861 0x00_05 => SetKeySignature(set_key_signature::SetKeySignature::try_from(value)?),
862 0x00_06 => SetChordName(set_chord_name::SetChordName::try_from(value)?),
863 0x01_00 => {
864 UnknownMetadataText(unknown_metadata_text::UnknownMetadataText::try_from(value)?)
865 }
866 0x01_01 => ProjectName(project_name::ProjectName::try_from(value)?),
867 0x01_02 => CompositionName(composition_name::CompositionName::try_from(value)?),
868 0x01_03 => MidiClipName(midi_clip_name::MidiClipName::try_from(value)?),
869 0x01_04 => CopyrightNotice(copyright_notice::CopyrightNotice::try_from(value)?),
870 0x01_05 => ComposerName(composer_name::ComposerName::try_from(value)?),
871 0x01_06 => LyricistName(lyricist_name::LyricistName::try_from(value)?),
872 0x01_07 => ArrangerName(arranger_name::ArrangerName::try_from(value)?),
873 0x01_08 => PublisherName(publisher_name::PublisherName::try_from(value)?),
874 0x01_09 => PrimaryPerformerName(
875 primary_performer_name::PrimaryPerformerName::try_from(value)?,
876 ),
877 0x01_10 => AccompanyingPerformerName(
878 accompanying_performer_name::AccompanyingPerformerName::try_from(value)?,
879 ),
880 0x01_11 => RecordingDate(recording_date::RecordingDate::try_from(value)?),
881 0x01_12 => RecordingLocation(recording_location::RecordingLocation::try_from(value)?),
882 0x02_00 => UnknownPerformanceText(
883 unknown_performance_text::UnknownPerformanceText::try_from(value)?,
884 ),
885 0x02_01 => Lyrics(lyrics::Lyrics::try_from(value)?),
886 0x02_02 => LyricsLanguage(lyrics_language::LyricsLanguage::try_from(value)?),
887 0x02_03 => Ruby(ruby::Ruby::try_from(value)?),
888 0x02_04 => RubyLanguage(ruby_language::RubyLanguage::try_from(value)?),
889 _ => Err(crate::error::InvalidData(
890 "Couldn't interpret flex data status / bank fields",
891 ))?,
892 })
893 }
894}
895
896impl<B: Ump> FlexDataMessage<B> for FlexData<B> {}
897
898#[derive(Debug, Clone, Copy, PartialEq, Eq)]
899pub enum Bank {
900 SetupAndPerformance,
901 MetadataText,
902 PerformanceText,
903}
904
905pub trait FlexDataMessage<B: crate::buffer::Ump>: crate::traits::Data<B> {
906 fn bank(&self) -> Bank {
907 use Bank::*;
908 match (self.data()[0] & 0x0000_FF00) >> 8 {
909 0x0 => SetupAndPerformance,
910 0x1 => MetadataText,
911 0x2 => PerformanceText,
912 _ => panic!(),
913 }
914 }
915 fn status(&self) -> u8 {
916 self.data()[0].octet(3)
917 }
918}
919
920struct StatusProperty<const STATUS: u8>;
921
922impl<const STATUS: u8, B: Ump> Property<B> for StatusProperty<STATUS> {
923 type Type = ();
924}
925
926impl<'a, const STATUS: u8, B: Ump> ReadProperty<'a, B> for StatusProperty<STATUS> {
927 fn read(_buffer: &'a B) -> Self::Type {}
928 fn validate(buffer: &B) -> Result<(), crate::error::InvalidData> {
929 if buffer
930 .buffer()
931 .chunks_exact(4)
932 .all(|packet| packet[0].octet(3) == STATUS)
933 {
934 Ok(())
935 } else {
936 Err(crate::error::InvalidData("Incorrect message status"))
937 }
938 }
939}
940
941impl<const STATUS: u8, B: Ump + BufferMut> WriteProperty<B> for StatusProperty<STATUS> {
942 fn write(buffer: &mut B, _v: Self::Type) {
943 buffer.buffer_mut()[0].set_octet(3, STATUS);
944 }
945 fn validate(_v: &Self::Type) -> Result<(), crate::error::InvalidData> {
946 Ok(())
947 }
948 fn default() -> Self::Type {}
949}
950
951struct BankProperty<const BANK: u8>;
952
953impl<const BANK: u8, B: Ump> Property<B> for BankProperty<BANK> {
954 type Type = ();
955}
956
957impl<'a, const BANK: u8, B: Ump> ReadProperty<'a, B> for BankProperty<BANK> {
958 fn read(_buffer: &'a B) -> Self::Type {}
959 fn validate(buffer: &B) -> Result<(), crate::error::InvalidData> {
960 if buffer
961 .buffer()
962 .chunks_exact(4)
963 .all(|packet| packet[0].octet(2) == BANK)
964 {
965 Ok(())
966 } else {
967 Err(crate::error::InvalidData("Incorrect message bank"))
968 }
969 }
970}
971
972impl<const BANK: u8, B: Ump + BufferMut> WriteProperty<B> for BankProperty<BANK> {
973 fn write(buffer: &mut B, _v: Self::Type) {
974 buffer.buffer_mut()[0].set_octet(2, BANK);
975 }
976 fn validate(_v: &Self::Type) -> Result<(), crate::error::InvalidData> {
977 Ok(())
978 }
979 fn default() -> Self::Type {}
980}
981
982struct FormatProperty<const FORMAT: u8>;
983
984impl<const FORMAT: u8, B: Ump> Property<B> for FormatProperty<FORMAT> {
985 type Type = ();
986}
987
988impl<'a, const FORMAT: u8, B: Ump> ReadProperty<'a, B> for FormatProperty<FORMAT> {
989 fn read(_buffer: &'a B) -> Self::Type {}
990 fn validate(buffer: &B) -> Result<(), crate::error::InvalidData> {
991 if FORMAT == u8::from(buffer.buffer()[0].crumb(4)) {
992 Ok(())
993 } else {
994 Err(crate::error::InvalidData("Incorrect message format"))
995 }
996 }
997}
998
999impl<const FORMAT: u8, B: Ump + BufferMut> WriteProperty<B> for FormatProperty<FORMAT> {
1000 fn write(buffer: &mut B, _v: Self::Type) {
1001 buffer.buffer_mut()[0].set_crumb(4, crate::ux::u2::new(FORMAT));
1002 }
1003 fn validate(_v: &Self::Type) -> Result<(), crate::error::InvalidData> {
1004 Ok(())
1005 }
1006 fn default() -> Self::Type {}
1007}
1008
1009struct OptionalChannelProperty;
1010
1011impl<B: Ump> Property<B> for OptionalChannelProperty {
1012 type Type = Option<crate::ux::u4>;
1013}
1014
1015impl<'a, B: Ump> ReadProperty<'a, B> for OptionalChannelProperty {
1016 fn read(buffer: &'a B) -> Self::Type {
1017 optional_channel_from_slice(buffer.buffer())
1018 }
1019 fn validate(_buffer: &B) -> Result<(), crate::error::InvalidData> {
1020 Ok(())
1021 }
1022}
1023
1024impl<B: Ump + BufferMut> WriteProperty<B> for OptionalChannelProperty {
1025 fn write(buffer: &mut B, v: Self::Type) {
1026 let buffer_slice = buffer.buffer_mut();
1027 let data = buffer_slice;
1028 optional_channel_to_slice(data, v);
1029 }
1030 fn validate(_v: &Self::Type) -> Result<(), crate::error::InvalidData> {
1031 Ok(())
1032 }
1033 fn default() -> Self::Type {
1034 Default::default()
1035 }
1036}
1037
1038fn optional_channel_to_slice(data: &mut [u32], channel: Option<crate::ux::u4>) {
1039 use crate::ux::{u2, u4};
1040 match channel {
1041 Some(channel) => {
1042 data[0].set_crumb(5, u2::new(0x0));
1043 data[0].set_nibble(3, channel);
1044 }
1045 None => {
1046 data[0].set_crumb(5, u2::new(0x1));
1047 data[0].set_nibble(3, u4::new(0x0));
1048 }
1049 }
1050}
1051
1052fn optional_channel_from_slice(data: &[u32]) -> Option<ux::u4> {
1053 if data[0].crumb(5) == ux::u2::new(0x0) {
1054 Some(data[0].nibble(3))
1055 } else {
1056 None
1057 }
1058}
1059
1060struct NoChannelProperty;
1061
1062impl<B: Ump> Property<B> for NoChannelProperty {
1063 type Type = ();
1064}
1065
1066impl<'a, B: Ump> ReadProperty<'a, B> for NoChannelProperty {
1067 fn read(_buffer: &'a B) -> Self::Type {}
1068 fn validate(buffer: &B) -> Result<(), crate::error::InvalidData> {
1069 use crate::ux::u2;
1070 if buffer.buffer()[0].crumb(5) != u2::new(0x0) {
1071 Ok(())
1072 } else {
1073 Err(crate::error::InvalidData(
1074 "Address field should be non zero.",
1075 ))
1076 }
1077 }
1078}
1079
1080impl<B: Ump + BufferMut> WriteProperty<B> for NoChannelProperty {
1081 fn write(buffer: &mut B, _: Self::Type) {
1082 use crate::ux::u2;
1083 use crate::ux::u4;
1084
1085 let data = buffer.buffer_mut();
1086 data[0].set_crumb(5, u2::new(0x1));
1087 data[0].set_nibble(3, u4::new(0x0));
1088 }
1089 fn validate(_v: &Self::Type) -> Result<(), crate::error::InvalidData> {
1090 Ok(())
1091 }
1092 fn default() -> Self::Type {
1093 Default::default()
1094 }
1095}
1096
1097struct ConsistentFormatsProperty;
1098
1099impl<B: Ump> Property<B> for ConsistentFormatsProperty {
1100 type Type = ();
1101}
1102
1103impl<'a, B: Ump> ReadProperty<'a, B> for ConsistentFormatsProperty {
1104 fn read(_buffer: &'a B) -> Self::Type {}
1105
1106 fn validate(buffer: &B) -> Result<(), crate::error::InvalidData> {
1107 use crate::detail::helpers::validate_sysex_group_statuses;
1108
1109 validate_sysex_group_statuses(
1110 buffer.buffer(),
1111 |p| u8::from(p[0].crumb(4)) == COMPLETE_FORMAT,
1112 |p| u8::from(p[0].crumb(4)) == START_FORMAT,
1113 |p| u8::from(p[0].crumb(4)) == CONTINUE_FORMAT,
1114 |p| u8::from(p[0].crumb(4)) == END_FORMAT,
1115 4,
1116 crate::ux::u4::new(UMP_MESSAGE_TYPE),
1117 )
1118 }
1119}
1120
1121struct GroupProperty;
1122
1123impl<B: Ump> Property<B> for GroupProperty {
1124 type Type = crate::ux::u4;
1125}
1126
1127impl<'a, B: Ump> ReadProperty<'a, B> for GroupProperty {
1128 fn read(buffer: &'a B) -> Self::Type {
1129 buffer.buffer()[0].nibble(1)
1130 }
1131 fn validate(buffer: &B) -> Result<(), crate::error::InvalidData> {
1132 use crate::detail::helpers::sysex_group_consistent_groups;
1133 sysex_group_consistent_groups(buffer.buffer(), 4, crate::ux::u4::new(UMP_MESSAGE_TYPE))
1134 }
1135}
1136
1137impl<B: Ump + BufferMut> WriteProperty<B> for GroupProperty {
1138 fn write(buffer: &mut B, group: Self::Type) {
1139 for packet in buffer
1140 .buffer_mut()
1141 .chunks_exact_mut(4)
1142 .take_while(|packet| u8::from(packet[0].nibble(0)) == UMP_MESSAGE_TYPE)
1143 {
1144 packet[0].set_nibble(1, group);
1145 }
1146 }
1147 fn validate(_v: &Self::Type) -> Result<(), crate::error::InvalidData> {
1148 Ok(())
1149 }
1150 fn default() -> Self::Type {
1151 Default::default()
1152 }
1153}
1154
1155fn flex_data_dyn_size<B: crate::buffer::Ump>(buffer: &B) -> usize {
1156 buffer
1157 .buffer()
1158 .chunks_exact(4)
1159 .position(|p| {
1160 let status: u8 = p[0].crumb(4).into();
1161 status == COMPLETE_FORMAT || status == END_FORMAT
1162 })
1163 .expect("Message is in an invalid state. Couldn't find end packet.")
1164 * 4
1165 + 4
1166}
1167
1168fn bank_from_buffer(buffer: &[u32]) -> u8 {
1169 buffer[0].octet(2)
1170}
1171
1172fn status_from_buffer(buffer: &[u32]) -> u8 {
1173 buffer[0].octet(3)
1174}
1175
1176fn bank_to_buffer(buffer: &mut [u32], bank: u8) {
1177 buffer[0].set_octet(2, bank);
1178}
1179
1180fn status_to_buffer(buffer: &mut [u32], status: u8) {
1181 buffer[0].set_octet(3, status);
1182}
1183
1184fn clear_payload(buffer: &mut [u32]) {
1185 for packet in buffer.chunks_exact_mut(4) {
1186 packet[1] = 0x0;
1187 packet[2] = 0x0;
1188 packet[3] = 0x0;
1189 }
1190}
1191
1192#[cfg(test)]
1193mod tests {
1194 use super::*;
1195
1196 #[test]
1197 fn try_from_empty() {
1198 let buffer = [];
1199 assert_eq!(
1200 FlexData::try_from(&buffer[..]),
1201 Err(crate::error::InvalidData("Slice is too short")),
1202 );
1203 }
1204
1205 #[test]
1206 fn try_from_text() {
1207 let buffer = [
1208 0xD050_0106,
1209 0x4769_6D6D,
1210 0x6520_736F,
1211 0x6D65_2073,
1212 0xD0D0_0106,
1213 0x6967_6E61,
1214 0x6C21_0000,
1215 0x0000_0000,
1216 ];
1217 assert_eq!(
1218 FlexData::try_from(&buffer[..]),
1219 Ok(FlexData::LyricistName(
1220 lyricist_name::LyricistName::try_from(&buffer[..]).unwrap()
1221 ))
1222 );
1223 }
1224
1225 #[test]
1226 fn try_from_set_tempo() {
1227 let buffer = [0xD710_0000_u32, 0xF751_FE05];
1228 assert_eq!(
1229 FlexData::try_from(&buffer[..]),
1230 Ok(FlexData::SetTempo(
1231 set_tempo::SetTempo::try_from(&buffer[..]).unwrap()
1232 ))
1233 );
1234 }
1235
1236 #[test]
1237 fn read_bank() {
1238 assert_eq!(
1239 FlexData::try_from(&[0xD710_0000_u32, 0xF751_FE05][..])
1240 .unwrap()
1241 .bank(),
1242 Bank::SetupAndPerformance,
1243 );
1244 }
1245
1246 #[test]
1247 fn packets() {
1248 use crate::Packets;
1249
1250 let message = FlexData::try_from(
1251 &[
1252 0xD050_0106,
1253 0x4769_6D6D,
1254 0x6520_736F,
1255 0x6D65_2073,
1256 0xD0D0_0106,
1257 0x6967_6E61,
1258 0x6C21_0000,
1259 0x0000_0000,
1260 ][..],
1261 )
1262 .unwrap();
1263 let mut packets = message.packets();
1264
1265 assert_eq!(
1266 &*packets.next().unwrap(),
1267 &[0xD050_0106, 0x4769_6D6D, 0x6520_736F, 0x6D65_2073,][..],
1268 );
1269 assert_eq!(
1270 &*packets.next().unwrap(),
1271 &[0xD0D0_0106, 0x6967_6E61, 0x6C21_0000, 0x0000_0000,][..],
1272 );
1273 assert_eq!(packets.next(), None);
1274 }
1275
1276 #[test]
1277 fn try_from_set_chord_name_data() {
1278 let message = FlexData::try_from(&[0xD70B_0006, 0xF703_3519, 0x4B00_0000, 0x110A_0020][..]);
1279 message.expect("Valid data");
1280 }
1281}