blob: afddb42c17954ec9fd510f5129d0e156dac0c2a7 [file] [log] [blame]
// 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<upb_Map>;
#[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::*;
use googletest::gtest;
#[gtest]
fn assert_map_linked() {
use crate::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);
}
#[gtest]
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_eq!(out.double_val, 4.0);
}
}
}