1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
use super::{Pattern, Trig};
use crate::object::pattern::{plock::ParameterLockPool, track::Track};
use serde::de::{
    self, Deserialize, DeserializeSeed, Deserializer, Error, MapAccess, SeqAccess, Visitor,
};
use std::{
    fmt,
    mem::MaybeUninit,
    sync::{Arc, Mutex},
};

impl<'de> Deserialize<'de> for Pattern {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct PatternVisitor;

        impl<'de> Visitor<'de> for PatternVisitor {
            type Value = Pattern;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Pattern")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Pattern, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut sysex_meta = None;
                let mut index = None;
                let mut version = None;
                let mut tracks: Option<[Track; 12]> = None;
                let mut fx_track: Option<Arc<Mutex<Track>>> = None;
                let mut parameter_lock_pool: Option<Arc<Mutex<ParameterLockPool>>> = None;
                let mut master_length = None;
                let mut master_change = None;
                let mut kit_number = None;
                let mut swing_amount = None;
                let mut time_mode = None;
                let mut speed = None;
                let mut global_quantize = None;
                let mut bpm = None;
                let mut pad_scale_per_pattern = None;

                while let Some(key) = map.next_key()? {
                    match key {
                        "sysex_meta" => sysex_meta = Some(map.next_value()?),
                        "index" => index = Some(map.next_value()?),
                        "version" => version = Some(map.next_value()?),
                        "fx_track" => {
                            // Context for the fx_track deserializer
                            let fx_track_seed = TrackDeserializerSeed {
                                fx_track_ref: &None, // fx_track does not have a parent, so pass None
                                parameter_lock_pool: &(parameter_lock_pool.clone()),
                            };
                            fx_track =
                                Some(Arc::new(Mutex::new(map.next_value_seed(fx_track_seed)?)));
                        }
                        "tracks" => {
                            // Context for the tracks array deserializer
                            let tracks_seed = TracksArrayDeserializerSeed {
                                fx_track_ref: &(fx_track.clone()),
                                parameter_lock_pool: &(parameter_lock_pool.clone()),
                            };
                            tracks = Some(map.next_value_seed(tracks_seed)?);
                        }
                        "master_length" => master_length = Some(map.next_value()?),
                        "master_change" => master_change = Some(map.next_value()?),
                        "kit_number" => kit_number = Some(map.next_value()?),
                        "swing_amount" => swing_amount = Some(map.next_value()?),
                        "time_mode" => time_mode = Some(map.next_value()?),
                        "speed" => speed = Some(map.next_value()?),
                        "global_quantize" => global_quantize = Some(map.next_value()?),
                        "bpm" => bpm = Some(map.next_value()?),
                        "pad_scale_per_pattern" => pad_scale_per_pattern = Some(map.next_value()?),
                        "parameter_lock_pool" => {
                            let parameter_lock_pool_value: ParameterLockPool = map.next_value()?;
                            parameter_lock_pool =
                                Some(Arc::new(Mutex::new(parameter_lock_pool_value)));
                        }
                        _ => return Err(V::Error::unknown_field(key, FIELDS)),
                    }
                }

                Ok(Pattern {
                    sysex_meta: sysex_meta.ok_or_else(|| V::Error::missing_field("sysex_meta"))?,
                    index: index.ok_or_else(|| V::Error::missing_field("index"))?,
                    version: version.ok_or_else(|| V::Error::missing_field("version"))?,
                    fx_track: fx_track.ok_or_else(|| V::Error::missing_field("fx_track"))?,
                    tracks: tracks.ok_or_else(|| V::Error::missing_field("tracks"))?,
                    master_length: master_length
                        .ok_or_else(|| V::Error::missing_field("master_length"))?,
                    master_change: master_change
                        .ok_or_else(|| V::Error::missing_field("master_change"))?,
                    kit_number: kit_number.ok_or_else(|| V::Error::missing_field("kit_number"))?,
                    swing_amount: swing_amount
                        .ok_or_else(|| V::Error::missing_field("swing_amount"))?,
                    time_mode: time_mode.ok_or_else(|| V::Error::missing_field("time_mode"))?,
                    speed: speed.ok_or_else(|| V::Error::missing_field("speed"))?,
                    global_quantize: global_quantize
                        .ok_or_else(|| V::Error::missing_field("global_quantize"))?,
                    bpm: bpm.ok_or_else(|| V::Error::missing_field("bpm"))?,
                    pad_scale_per_pattern: pad_scale_per_pattern
                        .ok_or_else(|| V::Error::missing_field("pad_scale_per_pattern"))?,
                    parameter_lock_pool: parameter_lock_pool
                        .ok_or_else(|| V::Error::missing_field("parameter_lock_pool"))?,
                })
            }
        }

        const FIELDS: &[&str] = &[
            "sysex_meta",
            "index",
            "version",
            "tracks",
            "fx_track",
            "parameter_lock_pool",
            "master_length",
            "master_change",
            "kit_number",
            "swing_amount",
            "time_mode",
            "speed",
            "global_quantize",
            "bpm",
            "pad_scale_per_pattern",
        ];

        deserializer.deserialize_struct("Pattern", FIELDS, PatternVisitor)
    }
}

// Tracks array deserializer
// Following the pattern of serde_big_array but with context
struct TracksArrayDeserializerSeed<'a> {
    fx_track_ref: &'a Option<Arc<Mutex<Track>>>,
    parameter_lock_pool: &'a Option<Arc<Mutex<ParameterLockPool>>>,
}

impl<'a, 'de> DeserializeSeed<'de> for TracksArrayDeserializerSeed<'a> {
    type Value = [Track; 12];

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        // Context for the tracks array deserializer
        struct ArrayVisitor<'a> {
            fx_track_ref: &'a Option<Arc<Mutex<Track>>>,
            parameter_lock_pool: &'a Option<Arc<Mutex<ParameterLockPool>>>,
        }

        impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> {
            type Value = [Track; 12];

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("an array of 12 tracks")
            }

            fn visit_seq<A>(self, mut seq: A) -> Result<[Track; 12], A::Error>
            where
                A: SeqAccess<'de>,
            {
                let mut arr = [(); 12].map(|_| MaybeUninit::<Track>::uninit());
                for (i, elem) in arr.iter_mut().enumerate() {
                    // Context for every track deserializer
                    let track_seed = TrackDeserializerSeed {
                        fx_track_ref: self.fx_track_ref,
                        parameter_lock_pool: self.parameter_lock_pool,
                    };
                    *elem = MaybeUninit::new(
                        seq.next_element_seed(track_seed)?
                            .ok_or_else(|| Error::invalid_length(i, &self))?,
                    );
                }
                Ok(unsafe { std::mem::transmute::<_, [Track; 12]>(arr) })
            }
        }

        // Pass the context into every element of the array
        deserializer.deserialize_seq(ArrayVisitor {
            fx_track_ref: self.fx_track_ref,
            parameter_lock_pool: self.parameter_lock_pool,
        })
    }
}

// Context for a single track deserializer
pub struct TrackDeserializerSeed<'a> {
    pub fx_track_ref: &'a Option<Arc<Mutex<Track>>>,
    pub parameter_lock_pool: &'a Option<Arc<Mutex<ParameterLockPool>>>,
}

impl<'a, 'de> de::DeserializeSeed<'de> for TrackDeserializerSeed<'a> {
    type Value = Track;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_struct(
            "Track",
            FIELDS,
            TrackVisitor {
                fx_track_ref: self.fx_track_ref,
                parameter_lock_pool: self.parameter_lock_pool,
            },
        )
    }
}

struct TrackVisitor<'a> {
    fx_track_ref: &'a Option<Arc<Mutex<Track>>>,
    parameter_lock_pool: &'a Option<Arc<Mutex<ParameterLockPool>>>,
}

impl<'a, 'de> de::Visitor<'de> for TrackVisitor<'a> {
    type Value = Track;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("struct Track")
    }

    fn visit_map<V>(self, mut map: V) -> Result<Track, V::Error>
    where
        V: de::MapAccess<'de>,
    {
        // Initialize all Track fields to None or default value
        let mut is_owner_pattern_work_buffer = None;
        let mut owner_pattern_index = None;
        let mut index = None;
        let mut trigs = None;
        let mut default_trig_flags = None;
        let mut default_trig_note = None;
        let mut default_trig_velocity = None;
        let mut default_trig_note_length = None;
        let mut default_trig_probability = None;
        let mut number_of_steps = None;
        let mut quantize_amount = None;
        let mut sends_midi = None;
        let mut speed = None;
        let mut euclidean_mode = None;
        let mut euclidean_pl1 = None;
        let mut euclidean_pl2 = None;
        let mut euclidean_ro1 = None;
        let mut euclidean_ro2 = None;
        let mut euclidean_tro = None;
        let mut pad_scale = None;
        let mut root_note = None;
        let mut __maybe_useful_flag_from_default_trig_note = None;
        let mut __maybe_useful_flags_from_flags_and_speed = None;

        while let Some(key) = map.next_key()? {
            match key {
                "is_owner_pattern_work_buffer" => {
                    is_owner_pattern_work_buffer = Some(map.next_value()?)
                }
                "owner_pattern_index" => owner_pattern_index = Some(map.next_value()?),
                "index" => index = Some(map.next_value()?),
                "trigs" => {
                    // Pass context into the trigs array deserializer
                    trigs = Some(map.next_value_seed(TrigsArrayVisitor {
                        parameter_lock_pool: self.parameter_lock_pool.clone(),
                        fx_track_ref: self.fx_track_ref.clone(),
                    })?)
                }
                "default_trig_flags" => default_trig_flags = Some(map.next_value()?),
                "default_trig_note" => default_trig_note = Some(map.next_value()?),
                "default_trig_velocity" => default_trig_velocity = Some(map.next_value()?),
                "default_trig_note_length" => default_trig_note_length = Some(map.next_value()?),
                "default_trig_probability" => default_trig_probability = Some(map.next_value()?),
                "number_of_steps" => number_of_steps = Some(map.next_value()?),
                "quantize_amount" => quantize_amount = Some(map.next_value()?),
                "sends_midi" => sends_midi = Some(map.next_value()?),
                "speed" => speed = Some(map.next_value()?),
                "euclidean_mode" => euclidean_mode = Some(map.next_value()?),
                "euclidean_pl1" => euclidean_pl1 = Some(map.next_value()?),
                "euclidean_pl2" => euclidean_pl2 = Some(map.next_value()?),
                "euclidean_ro1" => euclidean_ro1 = Some(map.next_value()?),
                "euclidean_ro2" => euclidean_ro2 = Some(map.next_value()?),
                "euclidean_tro" => euclidean_tro = Some(map.next_value()?),
                "pad_scale" => pad_scale = Some(map.next_value()?),
                "root_note" => root_note = Some(map.next_value()?),
                "__maybe_useful_flag_from_default_trig_note" => {
                    __maybe_useful_flag_from_default_trig_note = Some(map.next_value()?)
                }
                "__maybe_useful_flags_from_flags_and_speed" => {
                    __maybe_useful_flags_from_flags_and_speed = Some(map.next_value()?)
                }
                _ => return Err(de::Error::unknown_field(key, FIELDS)),
            }
        }

        Ok(Track {
            is_owner_pattern_work_buffer: is_owner_pattern_work_buffer
                .ok_or_else(|| de::Error::missing_field("is_owner_pattern_work_buffer"))?,
            owner_pattern_index: owner_pattern_index
                .ok_or_else(|| de::Error::missing_field("owner_pattern_index"))?,
            index: index.ok_or_else(|| de::Error::missing_field("index"))?,
            trigs: trigs.ok_or_else(|| de::Error::missing_field("trigs"))?,
            default_trig_flags: default_trig_flags
                .ok_or_else(|| de::Error::missing_field("default_trig_flags"))?,
            default_trig_note: default_trig_note
                .ok_or_else(|| de::Error::missing_field("default_trig_note"))?,
            default_trig_velocity: default_trig_velocity
                .ok_or_else(|| de::Error::missing_field("default_trig_velocity"))?,
            default_trig_note_length: default_trig_note_length
                .ok_or_else(|| de::Error::missing_field("default_trig_note_length"))?,
            default_trig_probability: default_trig_probability
                .ok_or_else(|| de::Error::missing_field("default_trig_probability"))?,
            number_of_steps: number_of_steps
                .ok_or_else(|| de::Error::missing_field("number_of_steps"))?,
            quantize_amount: quantize_amount
                .ok_or_else(|| de::Error::missing_field("quantize_amount"))?,
            sends_midi: sends_midi.ok_or_else(|| de::Error::missing_field("sends_midi"))?,
            speed: speed.ok_or_else(|| de::Error::missing_field("speed"))?,
            euclidean_mode: euclidean_mode
                .ok_or_else(|| de::Error::missing_field("euclidean_mode"))?,
            euclidean_pl1: euclidean_pl1
                .ok_or_else(|| de::Error::missing_field("euclidean_pl1"))?,
            euclidean_pl2: euclidean_pl2
                .ok_or_else(|| de::Error::missing_field("euclidean_pl2"))?,
            euclidean_ro1: euclidean_ro1
                .ok_or_else(|| de::Error::missing_field("euclidean_ro1"))?,
            euclidean_ro2: euclidean_ro2
                .ok_or_else(|| de::Error::missing_field("euclidean_ro2"))?,
            euclidean_tro: euclidean_tro
                .ok_or_else(|| de::Error::missing_field("euclidean_tro"))?,
            pad_scale: pad_scale.ok_or_else(|| de::Error::missing_field("pad_scale"))?,
            root_note: root_note.ok_or_else(|| de::Error::missing_field("root_note"))?,
            __maybe_useful_flag_from_default_trig_note: __maybe_useful_flag_from_default_trig_note
                .ok_or_else(|| {
                    de::Error::missing_field("__maybe_useful_flag_from_default_trig_note")
                })?,
            __maybe_useful_flags_from_flags_and_speed: __maybe_useful_flags_from_flags_and_speed
                .ok_or_else(|| {
                    de::Error::missing_field("__maybe_useful_flags_from_flags_and_speed")
                })?,
            // Inject the context to the track
            fx_track_ref: self.fx_track_ref.clone(),
            parameter_lock_pool: self.parameter_lock_pool.clone(),
        })
    }
}

const FIELDS: &[&str] = &[
    "is_owner_pattern_work_buffer",
    "owner_pattern_index",
    "index",
    "trigs",
    "default_trig_flags",
    "default_trig_note",
    "default_trig_velocity",
    "default_trig_note_length",
    "default_trig_probability",
    "number_of_steps",
    "quantize_amount",
    "sends_midi",
    "speed",
    "euclidean_mode",
    "euclidean_pl1",
    "euclidean_pl2",
    "euclidean_ro1",
    "euclidean_ro2",
    "euclidean_tro",
    "pad_scale",
    "root_note",
    "__maybe_useful_flag_from_default_trig_note",
    "__maybe_useful_flags_from_flags_and_speed",
];

// Trigs array deserializer
// Following the pattern of serde_big_array but with context
pub struct TrigsArrayVisitor {
    pub parameter_lock_pool: Option<Arc<Mutex<ParameterLockPool>>>,
    pub fx_track_ref: Option<Arc<Mutex<Track>>>,
}

impl<'de> de::DeserializeSeed<'de> for TrigsArrayVisitor {
    type Value = [Trig; 64];

    fn deserialize<D>(self, deserializer: D) -> Result<[Trig; 64], D::Error>
    where
        D: Deserializer<'de>,
    {
        struct ArrayVisitor {
            pub parameter_lock_pool: Option<Arc<Mutex<ParameterLockPool>>>,
            pub fx_track_ref: Option<Arc<Mutex<Track>>>,
        }

        impl<'de> Visitor<'de> for ArrayVisitor {
            type Value = [Trig; 64];

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("an array of 64 elements")
            }

            fn visit_seq<A>(self, mut seq: A) -> Result<[Trig; 64], A::Error>
            where
                A: SeqAccess<'de>,
            {
                unsafe {
                    let mut arr: [MaybeUninit<Trig>; 64] = MaybeUninit::uninit().assume_init();
                    for i in 0..64 {
                        // Deserialize each Trig normally
                        let mut trig: Trig = seq
                            .next_element()?
                            .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;

                        // Inject the values directly into each Trig
                        trig.parameter_lock_pool = self.parameter_lock_pool.clone();
                        trig.fx_track_ref = self.fx_track_ref.clone();

                        arr[i].as_mut_ptr().write(trig);
                    }
                    Ok(std::mem::transmute::<_, [Trig; 64]>(arr))
                }
            }
        }

        deserializer.deserialize_seq(ArrayVisitor {
            parameter_lock_pool: self.parameter_lock_pool.clone(),
            fx_track_ref: self.fx_track_ref.clone(),
        })
    }
}