// Protocol Buffers - Google's data interchange format // Copyright 2024 Google LLC. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd use super::opaque_pointee::opaque_pointee; use super::{upb_MessageValue, CType, RawArena}; use core::ptr::NonNull; opaque_pointee!(upb_Map); pub type RawMap = NonNull; #[repr(C)] #[allow(dead_code)] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum MapInsertStatus { Inserted = 0, Replaced = 1, OutOfMemory = 2, } pub const UPB_MAP_BEGIN: usize = usize::MAX; extern "C" { pub fn upb_Map_New(arena: RawArena, key_type: CType, value_type: CType) -> RawMap; pub fn upb_Map_Size(map: RawMap) -> usize; pub fn upb_Map_Insert( map: RawMap, key: upb_MessageValue, value: upb_MessageValue, arena: RawArena, ) -> MapInsertStatus; pub fn upb_Map_Get(map: RawMap, key: upb_MessageValue, value: *mut upb_MessageValue) -> bool; pub fn upb_Map_Delete( map: RawMap, key: upb_MessageValue, removed_value: *mut upb_MessageValue, ) -> bool; pub fn upb_Map_Clear(map: RawMap); pub fn upb_Map_Next( map: RawMap, key: *mut upb_MessageValue, value: *mut upb_MessageValue, iter: &mut usize, ) -> bool; } #[cfg(test)] mod tests { use super::super::Arena; use super::*; #[test] fn assert_map_linked() { use super::super::assert_linked; assert_linked!(upb_Map_New); assert_linked!(upb_Map_Size); assert_linked!(upb_Map_Insert); assert_linked!(upb_Map_Get); assert_linked!(upb_Map_Delete); assert_linked!(upb_Map_Clear); assert_linked!(upb_Map_Next); } #[test] fn map_ffi_test() { // SAFETY: FFI unit test uses C API under expected patterns. unsafe { let arena = Arena::new(); let raw_arena = arena.raw(); let map = upb_Map_New(raw_arena, CType::Bool, CType::Double); assert_eq!(upb_Map_Size(map), 0); assert_eq!( upb_Map_Insert( map, upb_MessageValue { bool_val: true }, upb_MessageValue { double_val: 2.0 }, raw_arena ), MapInsertStatus::Inserted ); assert_eq!( upb_Map_Insert( map, upb_MessageValue { bool_val: true }, upb_MessageValue { double_val: 3.0 }, raw_arena, ), MapInsertStatus::Replaced, ); assert_eq!(upb_Map_Size(map), 1); upb_Map_Clear(map); assert_eq!(upb_Map_Size(map), 0); assert_eq!( upb_Map_Insert( map, upb_MessageValue { bool_val: true }, upb_MessageValue { double_val: 4.0 }, raw_arena ), MapInsertStatus::Inserted ); let mut out = upb_MessageValue::zeroed(); assert!(upb_Map_Get(map, upb_MessageValue { bool_val: true }, &mut out)); assert!(matches!(out, upb_MessageValue { double_val: 4.0 })); } } }