vapoursynth4_rs/
map.rs

1use std::{
2    ffi::{CStr, c_char, c_int},
3    mem::ManuallyDrop,
4    ops::{Deref, DerefMut},
5};
6
7use thiserror::Error;
8
9use crate::{
10    api::Api,
11    ffi,
12    frame::{AudioFrame, Frame, VideoFrame, internal::FrameFromPtr},
13    function::Function,
14    node::{AudioNode, Node, VideoNode},
15};
16
17mod key;
18pub use key::*;
19
20// MARK: MapRef
21
22/// A borrowed reference to a [`ffi::VSMap`].
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub struct MapRef<'m> {
25    handle: *const ffi::VSMap,
26    api: Api,
27    marker: std::marker::PhantomData<&'m ()>,
28}
29
30impl MapRef<'_> {
31    // Safety: `ptr` must be valid
32    #[inline]
33    pub(crate) unsafe fn from_ptr(ptr: *const ffi::VSMap, api: Api) -> Self {
34        debug_assert!(!ptr.is_null());
35        Self {
36            handle: ptr,
37            api,
38            marker: std::marker::PhantomData,
39        }
40    }
41
42    /// Returns a raw pointer to the wrapped value.
43    #[inline]
44    pub(crate) fn as_ptr(&self) -> *mut ffi::VSMap {
45        self.handle.cast_mut()
46    }
47}
48
49impl Deref for MapRef<'_> {
50    type Target = Map;
51
52    fn deref(&self) -> &Self::Target {
53        unsafe { &*std::ptr::from_ref(self).cast() }
54    }
55}
56
57impl DerefMut for MapRef<'_> {
58    fn deref_mut(&mut self) -> &mut Self::Target {
59        unsafe { &mut *std::ptr::from_mut(self).cast() }
60    }
61}
62
63// MARK: Map
64
65/// An owned [`ffi::VSMap`].
66#[derive(Debug, PartialEq, Eq, Hash)]
67pub struct Map {
68    handle: *const ffi::VSMap,
69    api: Api,
70}
71
72impl Map {
73    // Safety: `ptr` must be a valid, owned instance created by `api`.
74    #[must_use]
75    pub(crate) unsafe fn from_ptr(ptr: *mut ffi::VSMap, api: Api) -> Self {
76        debug_assert!(!ptr.is_null());
77        Self { handle: ptr, api }
78    }
79
80    /// Returns a raw pointer to the wrapped value.
81    #[must_use]
82    pub fn as_ptr(&self) -> *mut ffi::VSMap {
83        self.handle.cast_mut()
84    }
85}
86
87impl Map {
88    pub fn clear(&mut self) {
89        // safety: `self.handle` is a valid pointer
90        unsafe { (self.api.clearMap)(self.as_ptr()) }
91    }
92
93    pub fn set_error(&mut self, msg: &CStr) {
94        // safety: `self.handle` and `msg` are valid pointers
95        unsafe { (self.api.mapSetError)(self.as_ptr(), msg.as_ptr()) }
96    }
97
98    #[must_use]
99    pub fn get_error(&self) -> Option<&CStr> {
100        let ptr = unsafe { (self.api.mapGetError)(self.as_ptr()) };
101        if ptr.is_null() {
102            None
103        } else {
104            Some(unsafe { CStr::from_ptr(ptr) })
105        }
106    }
107
108    #[must_use]
109    pub fn len(&self) -> i32 {
110        // safety: `self.handle` is a valid pointer
111        unsafe { (self.api.mapNumKeys)(self.as_ptr()) }
112    }
113
114    #[must_use]
115    pub fn is_empty(&self) -> bool {
116        self.len() == 0
117    }
118
119    // MARK: Get
120
121    /// # Panics
122    ///
123    /// Panics if `index` is out of bounds.
124    #[must_use]
125    pub fn get_key(&self, index: i32) -> &KeyStr {
126        assert!(!(index < 0 || index >= self.len()), "index out of bounds");
127
128        // safety: `self.handle` is a valid pointer
129        unsafe { KeyStr::from_ptr((self.api.mapGetKey)(self.as_ptr(), index)) }
130    }
131
132    pub fn delete_key(&mut self, key: &KeyStr) {
133        // safety: `self.handle` and `key` are valid pointers
134        unsafe { (self.api.mapDeleteKey)(self.as_ptr(), key.as_ptr()) };
135    }
136
137    #[must_use]
138    pub fn num_elements(&self, key: &KeyStr) -> Option<i32> {
139        // safety: `self.handle` is a valid pointer
140        let res = unsafe { (self.api.mapNumElements)(self.as_ptr(), key.as_ptr()) };
141        if res == -1 { None } else { Some(res) }
142    }
143
144    unsafe fn get_internal<T>(
145        &self,
146        func: unsafe extern "system-unwind" fn(
147            *const ffi::VSMap,
148            *const c_char,
149            c_int,
150            *mut ffi::VSMapPropertyError,
151        ) -> T,
152        key: &KeyStr,
153        index: i32,
154    ) -> Result<T, MapPropertyError> {
155        let mut error = ffi::VSMapPropertyError::Success;
156        handle_get_error(
157            unsafe { func(self.as_ptr(), key.as_ptr(), index, &mut error) },
158            error,
159        )
160    }
161
162    /// # Errors
163    ///
164    /// Return [`MapPropertyError`] if the underlying API does not success
165    pub fn get_int(&self, key: &KeyStr, index: i32) -> Result<i64, MapPropertyError> {
166        unsafe { self.get_internal(self.api.mapGetInt, key, index) }
167    }
168
169    /// # Errors
170    ///
171    /// Return [`MapPropertyError`] if the underlying API does not success
172    pub fn get_float(&self, key: &KeyStr, index: i32) -> Result<f64, MapPropertyError> {
173        unsafe { self.get_internal(self.api.mapGetFloat, key, index) }
174    }
175
176    /// # Errors
177    ///
178    /// Return [`MapPropertyError`] if the underlying API does not success
179    #[allow(clippy::cast_sign_loss)]
180    pub fn get_binary(&self, key: &KeyStr, index: i32) -> Result<&[u8], MapPropertyError> {
181        use ffi::VSDataTypeHint as dt;
182
183        unsafe {
184            if let dt::Unknown | dt::Binary =
185                self.get_internal(self.api.mapGetDataTypeHint, key, index)?
186            {
187                let size = self.get_internal(self.api.mapGetDataSize, key, index)?;
188                let ptr = self.get_internal(self.api.mapGetData, key, index)?;
189
190                Ok(std::slice::from_raw_parts(ptr.cast(), size as _))
191            } else {
192                Err(MapPropertyError::InvalidType)
193            }
194        }
195    }
196
197    /// # Errors
198    ///
199    /// Return [`MapPropertyError`] if the underlying API does not success
200    #[allow(clippy::cast_sign_loss)]
201    pub fn get_utf8(&self, key: &KeyStr, index: i32) -> Result<&str, MapPropertyError> {
202        unsafe {
203            if let ffi::VSDataTypeHint::Utf8 =
204                self.get_internal(self.api.mapGetDataTypeHint, key, index)?
205            {
206                let size = self.get_internal(self.api.mapGetDataSize, key, index)?;
207                let ptr = self.get_internal(self.api.mapGetData, key, index)?;
208
209                Ok(std::str::from_utf8_unchecked(std::slice::from_raw_parts(
210                    ptr.cast(),
211                    size as _,
212                )))
213            } else {
214                Err(MapPropertyError::InvalidType)
215            }
216        }
217    }
218
219    /// # Errors
220    ///
221    /// Return [`MapPropertyError`] if the underlying API does not success
222    pub fn get_function(&self, key: &KeyStr, index: i32) -> Result<Function, MapPropertyError> {
223        unsafe {
224            self.get_internal(self.api.mapGetFunction, key, index)
225                .map(|p| Function::from_ptr(p, self.api))
226        }
227    }
228
229    /// # Errors
230    ///
231    /// Return [`MapPropertyError`] if the underlying API does not success
232    pub fn get_video_node(&self, key: &KeyStr, index: i32) -> Result<VideoNode, MapPropertyError> {
233        unsafe {
234            self.get_internal(self.api.mapGetNode, key, index)
235                .map(|p| VideoNode::from_ptr(p, self.api))
236        }
237    }
238
239    /// # Errors
240    ///
241    /// Return [`MapPropertyError`] if the underlying API does not success
242    pub fn get_audio_node(&self, key: &KeyStr, index: i32) -> Result<AudioNode, MapPropertyError> {
243        unsafe {
244            self.get_internal(self.api.mapGetNode, key, index)
245                .map(|p| AudioNode::from_ptr(p, self.api))
246        }
247    }
248
249    /// # Errors
250    ///
251    /// Return [`MapPropertyError`] if the underlying API does not success
252    pub fn get_video_frame(
253        &self,
254        key: &KeyStr,
255        index: i32,
256    ) -> Result<VideoFrame, MapPropertyError> {
257        unsafe {
258            self.get_internal(self.api.mapGetFrame, key, index)
259                .map(|p| VideoFrame::from_ptr(p, self.api))
260        }
261    }
262
263    /// # Errors
264    ///
265    /// Return [`MapPropertyError`] if the underlying API does not success
266    pub fn get_audio_frame(
267        &self,
268        key: &KeyStr,
269        index: i32,
270    ) -> Result<AudioFrame, MapPropertyError> {
271        unsafe {
272            self.get_internal(self.api.mapGetFrame, key, index)
273                .map(|p| AudioFrame::from_ptr(p, self.api))
274        }
275    }
276
277    /// # Errors
278    ///
279    /// Return [`MapPropertyError`] if the underlying API does not success
280    pub fn get(&self, key: &KeyStr, index: i32) -> Result<Value, MapPropertyError> {
281        use ffi::VSPropertyType as t;
282
283        unsafe {
284            match (self.api.mapGetType)(self.as_ptr(), key.as_ptr()) {
285                t::Unset => Err(MapPropertyError::KeyNotFound),
286                t::Int => self.get_int(key, index).map(Value::Int),
287                t::Float => self.get_float(key, index).map(Value::Float),
288                t::Data => {
289                    use ffi::VSDataTypeHint as dt;
290
291                    let size = self.get_internal(self.api.mapGetDataSize, key, index)?;
292                    #[allow(clippy::cast_sign_loss)]
293                    match self.get_internal(self.api.mapGetDataTypeHint, key, index)? {
294                        dt::Unknown | dt::Binary => {
295                            let ptr = self.get_internal(self.api.mapGetData, key, index)?;
296                            Ok(Value::Data(std::slice::from_raw_parts(
297                                ptr.cast(),
298                                size as _,
299                            )))
300                        }
301                        dt::Utf8 => {
302                            let ptr = self.get_internal(self.api.mapGetData, key, index)?;
303                            Ok(Value::Utf8(std::str::from_utf8_unchecked(
304                                std::slice::from_raw_parts(ptr.cast(), size as _),
305                            )))
306                        }
307                    }
308                }
309                t::Function => self.get_function(key, index).map(Value::Function),
310                t::VideoNode => self.get_video_node(key, index).map(Value::VideoNode),
311                t::AudioNode => self.get_audio_node(key, index).map(Value::AudioNode),
312                t::VideoFrame => self.get_video_frame(key, index).map(Value::VideoFrame),
313                t::AudioFrame => self.get_audio_frame(key, index).map(Value::AudioFrame),
314            }
315        }
316    }
317
318    /// # Errors
319    ///
320    /// Return [`MapPropertyError`] if the underlying API does not success
321    pub fn get_int_saturated(&self, key: &KeyStr, index: i32) -> Result<i32, MapPropertyError> {
322        unsafe { self.get_internal(self.api.mapGetIntSaturated, key, index) }
323    }
324
325    /// # Errors
326    ///
327    /// Return [`MapPropertyError`] if the underlying API does not success
328    pub fn get_int_array(&self, key: &KeyStr) -> Result<&[i64], MapPropertyError> {
329        let mut error = ffi::VSMapPropertyError::Success;
330        unsafe {
331            let size = self
332                .num_elements(key)
333                .ok_or(MapPropertyError::KeyNotFound)?;
334            let ptr = handle_get_error(
335                (self.api.mapGetIntArray)(self.as_ptr(), key.as_ptr(), &mut error),
336                error,
337            )?;
338
339            #[allow(clippy::cast_sign_loss)]
340            Ok(std::slice::from_raw_parts(ptr, size as _))
341        }
342    }
343
344    /// # Errors
345    ///
346    /// Return [`MapPropertyError`] if the underlying API does not success
347    pub fn get_float_saturated(&self, key: &KeyStr, index: i32) -> Result<f32, MapPropertyError> {
348        // safety: `self.handle` is a valid pointer
349        unsafe { self.get_internal(self.api.mapGetFloatSaturated, key, index) }
350    }
351
352    /// # Errors
353    ///
354    /// Return [`MapPropertyError`] if the underlying API does not success
355    pub fn get_float_array(&self, key: &KeyStr) -> Result<&[f64], MapPropertyError> {
356        let mut error = ffi::VSMapPropertyError::Success;
357        unsafe {
358            let size = self
359                .num_elements(key)
360                .ok_or(MapPropertyError::KeyNotFound)?;
361            let ptr = handle_get_error(
362                (self.api.mapGetFloatArray)(self.as_ptr(), key.as_ptr(), &mut error),
363                error,
364            )?;
365
366            #[allow(clippy::cast_sign_loss)]
367            Ok(std::slice::from_raw_parts(ptr, size as _))
368        }
369    }
370
371    // MARK: Set
372
373    /// # Panics
374    ///
375    /// Panics if the key exists or is invalid
376    pub fn set_empty(&mut self, key: &KeyStr, type_: ffi::VSPropertyType) {
377        // safety: `self.handle` is a valid pointer
378        let res = unsafe { (self.api.mapSetEmpty)(self.as_ptr(), key.as_ptr(), type_) };
379        assert!(res != 0);
380    }
381
382    unsafe fn set_internal<T>(
383        &mut self,
384        func: unsafe extern "system-unwind" fn(
385            *mut ffi::VSMap,
386            *const c_char,
387            T,
388            ffi::VSMapAppendMode,
389        ) -> c_int,
390        key: &KeyStr,
391        val: T,
392        append: ffi::VSMapAppendMode,
393    ) -> Result<(), MapPropertyError> {
394        handle_set_error(unsafe { func(self.as_ptr(), key.as_ptr(), val, append) })
395    }
396
397    /// # Errors
398    ///
399    /// Return [`MapPropertyError::InvalidType`] if the `key`'s type is not the same with `val`
400    ///
401    /// # Panics
402    ///
403    /// Panic if the [`Value::Data`]'s or [`Value::Utf8`]'s len is larger than [`i32::MAX`]
404    pub fn set(
405        &mut self,
406        key: &KeyStr,
407        val: Value,
408        append: AppendMode,
409    ) -> Result<(), MapPropertyError> {
410        unsafe {
411            match val {
412                Value::Int(val) => self.set_internal(self.api.mapSetInt, key, val, append),
413                Value::Float(val) => self.set_internal(self.api.mapSetFloat, key, val, append),
414                Value::Data(val) => handle_set_error((self.api.mapSetData)(
415                    self.as_ptr(),
416                    key.as_ptr(),
417                    val.as_ptr().cast(),
418                    val.len().try_into().unwrap(),
419                    ffi::VSDataTypeHint::Binary,
420                    append,
421                )),
422                Value::Utf8(val) => handle_set_error((self.api.mapSetData)(
423                    self.as_ptr(),
424                    key.as_ptr(),
425                    val.as_ptr().cast(),
426                    val.len().try_into().unwrap(),
427                    ffi::VSDataTypeHint::Utf8,
428                    append,
429                )),
430                Value::VideoNode(val) => {
431                    self.set_internal(self.api.mapSetNode, key, val.as_ptr(), append)
432                }
433                Value::AudioNode(val) => {
434                    self.set_internal(self.api.mapSetNode, key, val.as_ptr(), append)
435                }
436                Value::VideoFrame(val) => {
437                    self.set_internal(self.api.mapSetFrame, key, val.as_ptr(), append)
438                }
439                Value::AudioFrame(val) => {
440                    self.set_internal(self.api.mapSetFrame, key, val.as_ptr(), append)
441                }
442                Value::Function(val) => {
443                    self.set_internal(self.api.mapSetFunction, key, val.as_ptr(), append)
444                }
445            }
446        }
447    }
448
449    /// # Errors
450    ///
451    /// Return [`MapPropertyError`] if the underlying API does not success
452    ///
453    /// # Panics
454    ///
455    /// Panic if the `val.len()` is larger than [`i32::MAX`]
456    pub fn set_int_array(&mut self, key: &KeyStr, val: &[i64]) -> Result<(), MapPropertyError> {
457        unsafe {
458            handle_set_error((self.api.mapSetIntArray)(
459                self.as_ptr(),
460                key.as_ptr(),
461                val.as_ptr(),
462                val.len().try_into().unwrap(),
463            ))
464        }
465    }
466
467    /// # Errors
468    ///
469    /// Return [`MapPropertyError`] if the underlying API does not success
470    ///
471    /// # Panics
472    ///
473    /// Panic if the `val.len()` is larger than [`i32::MAX`]
474    pub fn set_float_array(&mut self, key: &KeyStr, val: &[f64]) -> Result<(), MapPropertyError> {
475        unsafe {
476            handle_set_error((self.api.mapSetFloatArray)(
477                self.as_ptr(),
478                key.as_ptr(),
479                val.as_ptr(),
480                val.len().try_into().unwrap(),
481            ))
482        }
483    }
484
485    /// # Errors
486    ///
487    /// Return [`MapPropertyError`] if the underlying API does not success
488    pub fn consume_node(
489        &mut self,
490        key: &KeyStr,
491        node: impl Node,
492        append: AppendMode,
493    ) -> Result<(), MapPropertyError> {
494        let node = ManuallyDrop::new(node);
495        unsafe {
496            handle_set_error((self.api.mapConsumeNode)(
497                self.as_ptr(),
498                key.as_ptr(),
499                node.as_ptr(),
500                append,
501            ))
502        }
503    }
504
505    /// # Errors
506    ///
507    /// Return [`MapPropertyError`] if the underlying API does not success
508    pub fn consume_frame(
509        &mut self,
510        key: &KeyStr,
511        frame: impl Frame,
512        append: AppendMode,
513    ) -> Result<(), MapPropertyError> {
514        let frame = ManuallyDrop::new(frame);
515        unsafe {
516            handle_set_error((self.api.mapConsumeFrame)(
517                self.as_ptr(),
518                key.as_ptr(),
519                frame.as_ptr(),
520                append,
521            ))
522        }
523    }
524
525    /// # Errors
526    ///
527    /// Return [`MapPropertyError`] if the underlying API does not success
528    pub fn consume_function(
529        &mut self,
530        key: &KeyStr,
531        function: Function,
532        append: AppendMode,
533    ) -> Result<(), MapPropertyError> {
534        let function = ManuallyDrop::new(function);
535        unsafe {
536            handle_set_error((self.api.mapConsumeFunction)(
537                self.as_ptr(),
538                key.as_ptr(),
539                function.as_ptr(),
540                append,
541            ))
542        }
543    }
544}
545
546impl Drop for Map {
547    fn drop(&mut self) {
548        // safety: `self.handle` is a valid pointer
549        unsafe { (self.api.freeMap)(self.as_ptr()) }
550    }
551}
552
553impl Clone for Map {
554    fn clone(&self) -> Self {
555        // safety: `self` and `map` are both valid
556        unsafe {
557            let ptr = (self.api.createMap)();
558            (self.api.copyMap)(self.as_ptr(), ptr);
559            Self::from_ptr(ptr, self.api)
560        }
561    }
562}
563
564#[cfg(feature = "link-library")]
565impl Default for Map {
566    fn default() -> Self {
567        unsafe {
568            let api = Api::default();
569            let ptr = (api.createMap)();
570            Self::from_ptr(ptr, api)
571        }
572    }
573}
574
575// MARK: Helper
576
577fn handle_get_error<T>(res: T, error: ffi::VSMapPropertyError) -> Result<T, MapPropertyError> {
578    use MapPropertyError as pe;
579    use ffi::VSMapPropertyError as e;
580
581    match error {
582        e::Success => Ok(res),
583        e::Unset => Err(pe::KeyNotFound),
584        e::Type => Err(pe::InvalidType),
585        e::Index => Err(pe::IndexOutOfBound),
586        e::Error => Err(pe::MapError),
587    }
588}
589
590fn handle_set_error(res: i32) -> Result<(), MapPropertyError> {
591    if res == 0 {
592        Ok(())
593    } else {
594        Err(MapPropertyError::InvalidType)
595    }
596}
597
598// MARK: Types
599
600#[derive(Clone, Debug)]
601pub enum Value<'m> {
602    Int(i64),
603    Float(f64),
604    /// Arbitrary binary data
605    ///
606    /// # Notes
607    ///
608    /// Could still be UTF-8 strings because of the API3 compatibility
609    Data(&'m [u8]),
610    Utf8(&'m str),
611    VideoNode(VideoNode),
612    AudioNode(AudioNode),
613    VideoFrame(VideoFrame),
614    AudioFrame(AudioFrame),
615    Function(Function),
616}
617
618#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Error)]
619pub enum MapPropertyError {
620    #[error("The requested key was not found in the map")]
621    KeyNotFound,
622    #[error("The wrong function was used to retrieve the property")]
623    InvalidType,
624    #[error("The requested index was out of bound")]
625    IndexOutOfBound,
626    #[error("The map has errors. Use [`Map::get_error`] to retrieve the message")]
627    MapError,
628}
629
630pub type AppendMode = ffi::VSMapAppendMode;
631
632// MARK: Tests
633
634#[cfg(test)]
635#[cfg(feature = "link-library")]
636mod tests {
637    use core::panic;
638
639    use const_str::cstr;
640    use testresult::TestResult;
641
642    use super::*;
643
644    #[test]
645    fn clear() -> TestResult {
646        let mut map = Map::default();
647        let key = crate::key!(c"what");
648        map.set(key, Value::Int(42), AppendMode::Replace)?;
649
650        map.clear();
651        match map.get(key, 0) {
652            Err(MapPropertyError::KeyNotFound) => Ok(()),
653            _ => panic!("Map is not cleared"),
654        }
655    }
656
657    #[test]
658    fn error() -> TestResult {
659        let mut map = Map::default();
660        let key = crate::key!(c"what");
661        map.set(key, Value::Float(42.0), AppendMode::Replace)?;
662
663        map.set_error(cstr!("Yes"));
664        match map.get_error() {
665            Some(msg) => assert_eq!(msg, cstr!("Yes"), "Error message is not match"),
666            None => panic!("Error is not set"),
667        }
668        let res = map.get(key, 0);
669        match res {
670            Err(MapPropertyError::KeyNotFound) => {}
671            _ => panic!("Map is not cleared after setting error"),
672        }
673
674        map.set(key, Value::Float(42.0), AppendMode::Replace)?;
675        let res = map.get(key, 0);
676        match res {
677            Err(MapPropertyError::MapError) => {}
678            _ => panic!(
679                "Map after setting error can only be freed, \
680                cleared, or queried for error"
681            ),
682        }
683
684        Ok(())
685    }
686
687    #[test]
688    fn len() -> TestResult {
689        let mut map = Map::default();
690        let key = crate::key!(c"what");
691
692        map.set(key, Value::Data(&[42, 43, 44, 45]), AppendMode::Replace)?;
693        assert_eq!(1, map.len(), "Number of keys is not correct");
694
695        assert!(!map.is_empty(), "Map is not empty");
696
697        Ok(())
698    }
699
700    #[test]
701    fn key() -> TestResult {
702        let mut map = Map::default();
703        let key = crate::key!(c"what");
704
705        map.set(key, Value::Float(42.0), AppendMode::Append)?;
706
707        assert_eq!(key, map.get_key(0), "Key is not correct");
708
709        match map.num_elements(key) {
710            Some(num) => assert_eq!(1, num),
711            None => panic!("Key `{key}` not found "),
712        }
713
714        map.delete_key(key);
715        assert_eq!(
716            0,
717            map.len(),
718            "Number of keys is not correct after deleting `{key}`"
719        );
720
721        Ok(())
722    }
723
724    #[test]
725    #[allow(clippy::float_cmp)]
726    fn get_set() -> TestResult {
727        let mut map = Map::default();
728        let key = crate::key!(c"what");
729
730        let source = i64::from(i32::MAX) + 1;
731        map.set(key, Value::Int(source), AppendMode::Replace)?;
732        let res = map.get(key, 0)?;
733        match res {
734            Value::Int(val) => assert_eq!(val, source, "Value of `{key}` is not correct"),
735            _ => panic!("Invalid type of `{key}`"),
736        }
737        let res = map.get_int_saturated(key, 0)?;
738        assert_eq!(res, i32::MAX, "Value of `{key}` is not correct");
739        map.set(key, Value::Int(source), AppendMode::Append)?;
740        assert_eq!(&[source, source], map.get_int_array(key)?);
741        map.set_int_array(key, &[1, 2, 3])?;
742        assert_eq!(&[1, 2, 3], map.get_int_array(key)?);
743
744        map.set(key, Value::Float(1e25), AppendMode::Replace)?;
745        let res = map.get(key, 0)?;
746        match res {
747            Value::Float(val) => {
748                assert_eq!(val, 1e25, "Value of `{key}` is not correct");
749            }
750            _ => panic!("Invalid type of `{key}`"),
751        }
752        let res = map.get_float_saturated(key, 0)?;
753        assert_eq!(
754            res, 9_999_999_562_023_526_247_432_192.0,
755            "Value of `{key}` is not correct"
756        );
757        map.set(key, Value::Float(f64::MAX), AppendMode::Append)?;
758        assert_eq!(&[1e25, f64::MAX], map.get_float_array(key)?);
759        map.set_float_array(key, &[1.0, 2.0, 3.0])?;
760        assert_eq!(&[1.0, 2.0, 3.0], map.get_float_array(key)?);
761
762        map.set(key, Value::Data(&[42, 43]), AppendMode::Replace)?;
763        let res = map.get(key, 0)?;
764        match res {
765            Value::Data(val) => {
766                assert_eq!(val, &[42, 43], "Value of `{key}` is not correct");
767            }
768            _ => panic!("Invalid type of `{key}`"),
769        }
770
771        map.set(key, Value::Utf8("good"), AppendMode::Replace)?;
772        let res = map.get(key, 0)?;
773        match res {
774            Value::Utf8(val) => {
775                assert_eq!(val, "good", "Value of `{key}` is not correct");
776            }
777            _ => panic!("Invalid type of `{key}`"),
778        }
779
780        Ok(())
781    }
782}