Skip to main content

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