1use std::fmt::Debug;
33use std::marker::PhantomData;
34use std::ops::Deref;
35
36use crate::any::TryFromTemp;
37use crate::derive::Object;
38use crate::function::Function;
39use crate::object::{Object, ObjectArc};
40use crate::type_traits::ContainerElement;
41use crate::{Any, AnyCompatible, AnyView, Error, ObjectRefCore, Result};
42use tvm_ffi_sys::TVMFFITypeIndex as TypeIndex;
43use tvm_ffi_sys::{TVMFFIAny, TVMFFIObject};
44
45#[inline]
46fn element_view<T: ContainerElement>(value: &T) -> AnyView<'_> {
47 unsafe {
48 let mut data = TVMFFIAny::new();
49 T::container_copy_to_any_view(value, &mut data);
50 AnyView::from_raw_ffi_any(data)
51 }
52}
53
54fn element_from_any<T: ContainerElement>(value: Any) -> Result<T> {
55 unsafe {
56 if T::container_check_any_strict(value.as_raw_ffi_any()) {
57 let mut value = std::mem::ManuallyDrop::new(value);
58 return Ok(T::container_move_from_any_after_check(
59 &mut *value.as_data_ptr(),
60 ));
61 }
62 T::container_try_cast_from_any_view(value.as_raw_ffi_any()).map_err(|()| {
63 let message = format!(
64 "Cannot convert from type `{}` to `{}`",
65 T::container_get_mismatch_type_info(value.as_raw_ffi_any()),
66 T::container_type_str()
67 );
68 Error::new(crate::error::TYPE_ERROR, &message, "")
69 })
70 }
71}
72
73#[repr(C)]
86#[derive(Object)]
87#[type_key = "ffi.Map"]
88#[type_index(TypeIndex::kTVMFFIMap)]
89pub struct MapObj {
90 pub object: Object,
91 pub data: *mut core::ffi::c_void,
93 pub size: u64,
95 pub slots: u64,
97}
98
99#[repr(C)]
102pub struct Map<K, V> {
103 data: ObjectArc<MapObj>,
104 _marker: PhantomData<(K, V)>,
105}
106
107impl<K, V> Clone for Map<K, V> {
110 fn clone(&self) -> Self {
111 Self {
112 data: self.data.clone(),
113 _marker: PhantomData,
114 }
115 }
116}
117
118unsafe impl<K, V> ObjectRefCore for Map<K, V> {
119 type ContainerType = MapObj;
120
121 fn data(this: &Self) -> &ObjectArc<MapObj> {
122 &this.data
123 }
124
125 fn into_data(this: Self) -> ObjectArc<MapObj> {
126 this.data
127 }
128
129 unsafe fn from_data(data: ObjectArc<MapObj>) -> Self {
130 Self {
131 data,
132 _marker: PhantomData,
133 }
134 }
135}
136
137impl<K, V> Deref for Map<K, V> {
141 type Target = MapObj;
142 #[inline]
143 fn deref(&self) -> &MapObj {
144 &self.data
145 }
146}
147
148impl<K, V> Map<K, V>
149where
150 K: ContainerElement,
151 V: ContainerElement,
152{
153 pub fn new() -> Self {
155 Self::from_pairs(&[]).expect("ffi.Map() failed to construct an empty map")
156 }
157
158 fn from_pairs(pairs: &[(K, V)]) -> Result<Self> {
161 let mut args: Vec<AnyView<'_>> = Vec::with_capacity(pairs.len() * 2);
162 for (k, v) in pairs {
163 args.push(element_view(k));
164 args.push(element_view(v));
165 }
166 let result = crate::cached_global_func!("ffi.Map").call_packed(&args)?;
167 Self::try_from(result)
168 }
169
170 pub fn len(&self) -> usize {
173 self.size as usize
174 }
175
176 pub fn is_empty(&self) -> bool {
178 self.len() == 0
179 }
180
181 fn try_contains_key(&self, key: &K) -> Result<bool> {
185 let result = crate::cached_global_func!("ffi.MapCount")
186 .call_packed(&[AnyView::from(self), element_view(key)])?;
187 Ok(i64::try_from(result)? != 0)
188 }
189
190 #[inline]
200 fn debug_assert_key_type(&self) {
201 #[cfg(debug_assertions)]
202 {
203 if !self.is_empty() {
204 let functor = self.iter_functor();
205 let first_key = functor
206 .call_packed(&[AnyView::from(&0i64)])
207 .expect("map iterator: reading current key failed");
208 assert!(
209 unsafe { K::container_check_any_strict(first_key.as_raw_ffi_any()) },
210 "Map lookup: key type `{}` does not match the map's stored key type",
211 std::any::type_name::<K>(),
212 );
213 }
214 }
215 }
216
217 pub fn contains_key(&self, key: &K) -> bool {
225 let present = self
226 .try_contains_key(key)
227 .expect("ffi.MapCount call failed");
228 if !present {
229 self.debug_assert_key_type();
230 }
231 present
232 }
233
234 pub fn get(&self, key: &K) -> Result<Option<V>> {
246 if !self.try_contains_key(key)? {
247 self.debug_assert_key_type();
248 return Ok(None);
249 }
250 let result = crate::cached_global_func!("ffi.MapGetItem")
251 .call_packed(&[AnyView::from(self), element_view(key)])?;
252 let value = element_from_any(result)?;
253 Ok(Some(value))
254 }
255
256 pub fn iter(&self) -> MapItems<K, V> {
258 self.make_iter(|f| (iter_read::<K>(f, 0, "key"), iter_read::<V>(f, 1, "value")))
259 }
260
261 pub fn keys(&self) -> MapKeys<K> {
263 self.make_iter(|f| iter_read::<K>(f, 0, "key"))
264 }
265
266 pub fn values(&self) -> MapValues<V> {
268 self.make_iter(|f| iter_read::<V>(f, 1, "value"))
269 }
270
271 fn make_iter<T>(&self, read: fn(&Function) -> T) -> MapIter<T> {
275 let remaining = self.len();
276 MapIter {
277 functor: (remaining != 0).then(|| self.iter_functor()),
278 remaining,
279 _keepalive: self.data.clone(),
280 read,
281 }
282 }
283
284 fn iter_functor(&self) -> Function {
286 let result = crate::cached_global_func!("ffi.MapForwardIterFunctor")
287 .call_packed(&[AnyView::from(self)])
288 .expect("ffi.MapForwardIterFunctor call failed");
289 Function::try_from(result).expect("ffi.MapForwardIterFunctor returned a non-function")
290 }
291
292 fn try_raw_entries(&self) -> Result<Vec<(Any, Any)>> {
298 let mut entries = Vec::with_capacity(self.len());
299 let mut remaining = self.len();
300 if remaining == 0 {
301 return Ok(entries);
302 }
303 let functor = crate::cached_global_func!("ffi.MapForwardIterFunctor")
304 .call_packed(&[AnyView::from(self)])
305 .and_then(Function::try_from)?;
306 loop {
307 let k = functor.call_packed(&[AnyView::from(&0i64)])?;
308 let v = functor.call_packed(&[AnyView::from(&1i64)])?;
309 entries.push((k, v));
310 remaining -= 1;
311 if remaining == 0 {
312 return Ok(entries);
313 }
314 functor.call_packed(&[AnyView::from(&2i64)])?;
315 }
316 }
317}
318
319impl<K, V> Default for Map<K, V>
320where
321 K: ContainerElement,
322 V: ContainerElement,
323{
324 fn default() -> Self {
325 Self::new()
326 }
327}
328
329impl<K, V> Debug for Map<K, V>
330where
331 K: ContainerElement,
332 V: ContainerElement,
333{
334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
335 fn short(name: &str) -> &str {
336 name.split("::").last().unwrap_or(name)
337 }
338 write!(
339 f,
340 "Map<{}, {}>[{}]",
341 short(std::any::type_name::<K>()),
342 short(std::any::type_name::<V>()),
343 self.len()
344 )
345 }
346}
347
348impl<K, V> FromIterator<(K, V)> for Map<K, V>
349where
350 K: ContainerElement,
351 V: ContainerElement,
352{
353 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
356 let pairs: Vec<(K, V)> = iter.into_iter().collect();
357 Self::from_pairs(&pairs).expect("ffi.Map() failed to construct a map")
358 }
359}
360
361fn iter_read<T: ContainerElement>(functor: &Function, command: i64, kind: &str) -> T {
375 let any = functor
376 .call_packed(&[AnyView::from(&command)])
377 .expect("map iterator: reading current element failed");
378 element_from_any(any)
379 .unwrap_or_else(|_| panic!("map iterator: {kind} does not match the map's {kind} type"))
380}
381
382fn iter_advance(functor: &Function, remaining: &mut usize) {
386 debug_assert!(
387 *remaining > 0,
388 "iter_advance called with no remaining entries"
389 );
390 *remaining -= 1;
391 if *remaining > 0 {
392 functor
393 .call_packed(&[AnyView::from(&2i64)])
394 .expect("map iterator: advancing failed");
395 }
396}
397
398pub struct MapIter<T> {
403 functor: Option<Function>,
406 remaining: usize,
407 _keepalive: ObjectArc<MapObj>,
408 read: fn(&Function) -> T,
409}
410
411impl<T> Iterator for MapIter<T> {
412 type Item = T;
413
414 fn next(&mut self) -> Option<T> {
415 if self.remaining == 0 {
416 return None;
417 }
418 let functor = self
420 .functor
421 .as_ref()
422 .expect("non-empty map iterator has a functor");
423 let item = (self.read)(functor);
424 iter_advance(functor, &mut self.remaining);
425 Some(item)
426 }
427
428 fn size_hint(&self) -> (usize, Option<usize>) {
429 (self.remaining, Some(self.remaining))
430 }
431}
432
433impl<T> ExactSizeIterator for MapIter<T> {}
434
435pub type MapItems<K, V> = MapIter<(K, V)>;
437pub type MapKeys<K> = MapIter<K>;
439pub type MapValues<V> = MapIter<V>;
441
442impl<K, V> IntoIterator for &Map<K, V>
443where
444 K: ContainerElement,
445 V: ContainerElement,
446{
447 type Item = (K, V);
448 type IntoIter = MapItems<K, V>;
449
450 fn into_iter(self) -> Self::IntoIter {
451 self.iter()
452 }
453}
454
455unsafe impl<K, V> AnyCompatible for Map<K, V>
458where
459 K: ContainerElement,
460 V: ContainerElement,
461{
462 fn type_str() -> String {
463 format!(
464 "Map<{}, {}>",
465 K::container_type_str(),
466 V::container_type_str()
467 )
468 }
469
470 unsafe fn check_any_strict(data: &TVMFFIAny) -> bool {
471 if data.type_index != TypeIndex::kTVMFFIMap as i32 {
475 return false;
476 }
477 let map = <Self as AnyCompatible>::copy_from_any_view_after_check(data);
478 match map.try_raw_entries() {
479 Ok(entries) => entries.iter().all(|(k, v)| unsafe {
480 K::container_check_any_strict(k.as_raw_ffi_any())
481 && V::container_check_any_strict(v.as_raw_ffi_any())
482 }),
483 Err(_) => false,
484 }
485 }
486
487 unsafe fn copy_to_any_view(src: &Self, data: &mut TVMFFIAny) {
488 data.type_index = TypeIndex::kTVMFFIMap as i32;
489 data.data_union.v_obj = ObjectArc::as_raw(Self::data(src)) as *mut TVMFFIObject;
490 data.small_str_len = 0;
491 }
492
493 unsafe fn move_to_any(src: Self, data: &mut TVMFFIAny) {
494 data.type_index = TypeIndex::kTVMFFIMap as i32;
495 data.data_union.v_obj = ObjectArc::into_raw(Self::into_data(src)) as *mut TVMFFIObject;
496 data.small_str_len = 0;
497 }
498
499 unsafe fn copy_from_any_view_after_check(data: &TVMFFIAny) -> Self {
500 let ptr = data.data_union.v_obj as *const MapObj;
501 crate::object::unsafe_::inc_ref(ptr as *mut TVMFFIObject);
502 Self::from_data(ObjectArc::from_raw(ptr))
503 }
504
505 unsafe fn move_from_any_after_check(data: &mut TVMFFIAny) -> Self {
506 let ptr = data.data_union.v_obj as *const MapObj;
507 let obj = Self::from_data(ObjectArc::from_raw(ptr));
508 data.type_index = TypeIndex::kTVMFFINone as i32;
509 data.data_union.v_int64 = 0;
510 obj
511 }
512
513 unsafe fn try_cast_from_any_view(data: &TVMFFIAny) -> Result<Self, ()> {
514 if data.type_index != TypeIndex::kTVMFFIMap as i32 {
515 return Err(());
516 }
517
518 if <Self as AnyCompatible>::check_any_strict(data) {
520 return Ok(<Self as AnyCompatible>::copy_from_any_view_after_check(
521 data,
522 ));
523 }
524
525 let src = <Self as AnyCompatible>::copy_from_any_view_after_check(data);
528 let mut pairs = Vec::with_capacity(src.len());
529 for (k, v) in src.try_raw_entries().map_err(|_| ())? {
530 let k = element_from_any::<K>(k).map_err(|_| ())?;
531 let v = element_from_any::<V>(v).map_err(|_| ())?;
532 pairs.push((k, v));
533 }
534 Self::from_pairs(&pairs).map_err(|_| ())
535 }
536}
537
538impl<K, V> TryFrom<Any> for Map<K, V>
539where
540 K: ContainerElement,
541 V: ContainerElement,
542{
543 type Error = Error;
544
545 fn try_from(value: Any) -> Result<Self> {
546 let temp: TryFromTemp<Self> = TryFromTemp::try_from(value)?;
547 Ok(TryFromTemp::into_value(temp))
548 }
549}
550
551impl<'a, K, V> TryFrom<AnyView<'a>> for Map<K, V>
552where
553 K: ContainerElement,
554 V: ContainerElement,
555{
556 type Error = Error;
557
558 fn try_from(value: AnyView<'a>) -> Result<Self> {
559 let temp: TryFromTemp<Self> = TryFromTemp::try_from(value)?;
560 Ok(TryFromTemp::into_value(temp))
561 }
562}