You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: keyframes.rs
    path of file: ./repos/gyroflow/src/core
    
    the code of the file until where you have to start completion: // SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2022 Adrian <adrian.eddy at gmail>

use std::{ collections::BTreeMap, collections::btree_map::Entry, str::FromStr };
use crate::gyro_source::GyroSource;
use std::sync::{ Arc, Mutex }; // parking_lot::Mutex can't be used across catch_unwind

macro_rules! define_keyframes {
    ($($name:ident, $color:literal, $text:literal, $format:expr,)*) => {
        #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, ::serde::Serialize, ::serde::Deserialize)]
        pub enum KeyframeType {
            $($name),*
        }
        pub fn keyframe_color(kf: &KeyframeType) -> &'static str {
            match kf { $(KeyframeType::$name => $color),* }
        }
        pub fn keyframe_text(kf: &KeyframeType) -> &'static str {
            match kf { $(KeyframeType::$name => $text),* }
        }
        pub fn keyframe_format_value(kf: &KeyframeType, v: f64) -> String {
            match kf { $(KeyframeType::$name => $format(v)),* }
        }
    };
}

define_keyframes! {
    Fov,                         "#8ee6ea", "FOV",                              |v| format!("{:.2}", v),
    VideoRotation,               "#eae38e", "Video rotation",                   |v| format!("{:.1}°", v),
    ZoomingSpeed,                "#32e595", "Zooming speed",                    |v| format!("{:.2}s", v),
    ZoomingCenterX,              "#6fefb6", "Zooming center offset X",          |v| format!("{:.0}%", v * 100.0),
    ZoomingCenterY,              "#5ddba2", "Zooming center offset Y",          |v| format!("{:.0}%", v * 100.0),
    AdditionalRotationX,         "#7817ef", "Additional 3D yaw",                |v| format!("{:.2}°", v),
    AdditionalRotationY,         "#9248ec", "Additional 3D pitch",              |v| format!("{:.2}°", v),
    AdditionalRotationZ,         "#ab7ce4", "Additional 3D roll",               |v| format!("{:.2}°", v),
    AdditionalTranslationX,      "#ea2487", "Additional 3D translation X",      |v| format!("{:.0}px", v),
    AdditionalTranslationY,      "#e0539a", "Additional 3D translation Y",      |v| format!("{:.0}px", v),
    AdditionalTranslationZ,      "#e98fbc", "Additional 3D translation Z",      |v| format!("{:.0}px", v),
    BackgroundMargin,            "#6e5ddb", "Background margin",                |v| format!("{:.0}%", v),
    BackgroundFeather,           "#9d93e1", "Background feather",               |v|
    
    pub fn new() -> Self { Self::default() }

    pub fn set_custom_provider(&mut self, cb: impl FnMut(&KeyframeManager, &KeyframeType, f64) -> Option<f64> + Send + 'static) {
        self.custom_provider = Some(Arc::new(Mutex::new(cb)));
    }
    pub fn set(&mut self, typ: &KeyframeType, timestamp_us: i64, value: f64) {
        let kf = Keyframe {
            value,
            easing: Easing::EaseInOut
        };
        if let Some(x) = self.keyframes.get_mut(typ) {
            match x.entry(timestamp_us) {
                Entry::Occupied(o) => { o.into_mut().value = value; }
                Entry::Vacant(v) => { v.insert(kf); }
            }
        } else {
            self.keyframes.insert(typ.clone(), BTreeMap::from([(timestamp_us, kf)]));
        }
    }
    pub fn set_easing(&mut self, typ: &KeyframeType, timestamp_us: i64, easing: Easing) {
        if let Some(x) = self.keyframes.get_mut(typ) {
            if let Some(kf) = x.get_mut(&timestamp_us) {
                kf.easing = easing;
            }
        }
    }
    pub fn easing(&self, typ: &KeyframeType, timestamp_us: i64) -> Option<Easing> {
        Some(self.keyframes.get(typ)?.get(&timestamp_us)?.easing)
    }
    pub fn remove(&mut self, typ: &KeyframeType, timestamp_us: i64) {
        if let Some(x) = self.keyframes.get_mut(typ) {
            x.remove(&timestamp_us);
        }
    }
    pub fn is_keyframed_internally(&self, typ: &KeyframeType) -> bool {
        if let Some(x) = self.keyframes.get(typ) {
            return x.len() > 0;
        }
        false
    }
    pub fn is_keyframed(&self, typ: &KeyframeType) -> bool {
        if let Some(custom) = &self.custom_provider {
            if let Ok(mut custom) = custom.lock() {
                if let Some(_) = (*custom)(self, typ, 0.0) {
                    return true;
                }
            }
        }
        self.is_keyframed_internally(typ)
    }
    pub fn value_at_video_timestamp(&self, typ: &KeyframeType, timestamp_ms: f64) -> Option<f64> {
        if let Some(custom) = &self.custom_provider {
            if let Ok(mut custom) = custom.lock() {
                if let Some(v) = (*custom)(self, typ, timestamp_ms * self.timestamp_scale.unwrap_or(1.0)) {
                    return Some(v);
                }
            }
        }
        let keyframes = self.keyframes.get(typ)?;
        match keyframes.len() {
            0 => None,
            1 => Some(keyframes.values().next().unwrap().value),
            _ => {
                if let Some(&first_ts) = keyframes.keys().next() {
                    if let Some(&last_ts) = keyframes.keys().next_back() {
                        let timestamp_us = (timestamp_ms * 1000.0 * self.timestamp_scale.unwrap_or(1.0)).round() as i64;
                        let lookup_ts = timestamp_us.min(last_ts).max(first_ts);
                        if let Some(offs1) = keyframes.range(..=lookup_ts).next_back() {
                            if *offs1.0 == lookup_ts {
                                return Some(offs1.1.value);
                            }
                            if let Some(offs2) = keyframes.range(lookup_ts..).next() {
                                let time_delta = (offs2.0 - offs1.0) as f64;
                                let alpha = (timestamp_us - offs1.0) as f64 / time_delta;
                                let e = Easing::get(&offs1.1.easing, &offs2.1.easing, alpha);
                                return Some(e.interpolate(offs1.1.value, offs2.1.value, alpha));
                            }
                        }
                    }
                }

                None
            }
        }
    }

    pub fn value_at_gyro_timestamp(&self, typ: &KeyframeType, mut timestamp_ms: f64) -> Option<f64> {
        timestamp_ms += GyroSource::offset_at_timestamp(&self.gyro_offsets, timestamp_ms);
        self.value_at_video_timestamp(typ, timestamp_ms)
    }

    pub fn get_keyframes(&self, typ: &KeyframeType) -> Option<&BTreeMap<i64, Keyframe>> {
        self.keyframes.get(typ)
    }

    pub fn get_all_keys(&self) -> Vec<&KeyframeType> {
        self.keyframes.iter().filter(|(_, v)| !v.is_empty()).map(|(k, _)| k).collect()
    }

    pub fn update_gyro(&mut self, gyro: &GyroSource) {
        self.gyro_offsets = gyro.get_offsets().clone();
    }
    pub fn clear(&mut self) {
        *self = Self::new();
    }

    pub fn clear_type(&mut self, key: &KeyframeType) {
        self.keyframes.remove(key);
    }

    pub fn serialize(&self) -> serde_json::Value {
        serde_json::to_value(&self.keyframes).unwrap_or(serde_json::Value::Null)
    }
    pub fn deserialize(&mut self, v: &serde_json::Value) {
        self.keyframes.clear();
        if let Ok(kf) = serde_json::from_value(v.clone()) {
            self.keyframes = kf;
        }
    }

    pub fn next_keyframe(&self, ts: i64, typ: Option<KeyframeType>) -> Option<(KeyframeType, i64, Keyframe)> {
        if let Some(kf) = typ {
            let res = self.keyframes.get(&kf)?.range(ts+1..).next()?;
            Some((kf, *res.0, *res.1))
        } else {
            self.keyframes
                .iter()
                .filter_map(|(&k, _)| self.next_keyframe(ts, Some(k)) )
                .min_by_key(|(_nt, nts, _nk)| (nts - ts).abs())
        }
    }
    pub fn prev_keyframe(&self, ts: i64, typ: Option<KeyframeType>) -> Option<(KeyframeType, i64, Keyframe)> {
       if let Some(kf) = typ {
            let res = self.keyframes.get(&kf)?.range(..ts).next_back()?;
            Some((kf, *res.0, *res.1))
        } else {
            self.keyframes
                .iter()
                .filter_map(|(&k, _)| self.prev_keyframe(ts, Some(k)) )
                .min_by_key(|(_nt, nts, _nk)| (nts - ts).abs())
        }
    }
}