1use std::borrow::Borrow;
69use std::marker::PhantomData;
70use std::os::raw::c_void;
71use std::{mem, slice};
72
73use conv::ConvUtil;
74
75use super::{Address, Count};
76
77use crate::ffi;
78use crate::ffi::MPI_Datatype;
79
80use crate::raw::traits::*;
81
82use crate::with_uninitialized;
83
84pub mod traits {
86 pub use super::{
87 AsDatatype, Buffer, BufferMut, Collection, Datatype, Equivalence, Partitioned,
88 PartitionedBuffer, PartitionedBufferMut, Pointer, PointerMut, UncommittedDatatype,
89 };
90}
91
92#[derive(Copy, Clone, Debug)]
96pub struct DatatypeRef<'a> {
97 datatype: MPI_Datatype,
98 phantom: PhantomData<&'a ()>,
99}
100
101unsafe impl<'a> AsRaw for DatatypeRef<'a> {
102 type Raw = MPI_Datatype;
103 fn as_raw(&self) -> Self::Raw {
104 self.datatype
105 }
106}
107
108impl<'a> FromRaw for DatatypeRef<'a> {
109 unsafe fn from_raw(datatype: MPI_Datatype) -> Self {
110 Self {
111 datatype,
112 phantom: PhantomData,
113 }
114 }
115}
116
117unsafe impl<'a> MatchesRaw for DatatypeRef<'a> {}
118
119impl<'a> Datatype for DatatypeRef<'a> {}
120impl<'a> UncommittedDatatype for DatatypeRef<'a> {
121 type DuplicatedDatatype = UserDatatype;
122}
123
124impl<'a> From<DatatypeRef<'a>> for UncommittedDatatypeRef<'a> {
125 fn from(datatype_ref: DatatypeRef<'a>) -> Self {
126 unsafe { UncommittedDatatypeRef::from_raw(datatype_ref.as_raw()) }
127 }
128}
129
130#[derive(Copy, Clone, Debug)]
134pub struct UncommittedDatatypeRef<'a> {
135 datatype: MPI_Datatype,
136 phantom: PhantomData<&'a ()>,
137}
138
139unsafe impl<'a> AsRaw for UncommittedDatatypeRef<'a> {
140 type Raw = MPI_Datatype;
141 fn as_raw(&self) -> Self::Raw {
142 self.datatype
143 }
144}
145
146impl<'a> FromRaw for UncommittedDatatypeRef<'a> {
147 unsafe fn from_raw(datatype: MPI_Datatype) -> Self {
148 Self {
149 datatype,
150 phantom: PhantomData,
151 }
152 }
153}
154
155unsafe impl<'a> MatchesRaw for UncommittedDatatypeRef<'a> {}
156
157impl<'a> UncommittedDatatype for UncommittedDatatypeRef<'a> {
158 type DuplicatedDatatype = UncommittedUserDatatype;
159}
160
161pub type SystemDatatype = DatatypeRef<'static>;
167
168pub unsafe trait Equivalence {
174 type Out: Datatype;
176 fn equivalent_datatype() -> Self::Out;
178}
179
180macro_rules! equivalent_system_datatype {
181 ($rstype:path, $mpitype:path) => {
182 unsafe impl Equivalence for $rstype {
183 type Out = SystemDatatype;
184 fn equivalent_datatype() -> Self::Out {
185 unsafe { DatatypeRef::from_raw($mpitype) }
186 }
187 }
188 };
189}
190
191equivalent_system_datatype!(bool, ffi::RSMPI_C_BOOL);
192
193equivalent_system_datatype!(f32, ffi::RSMPI_FLOAT);
194equivalent_system_datatype!(f64, ffi::RSMPI_DOUBLE);
195
196equivalent_system_datatype!(i8, ffi::RSMPI_INT8_T);
197equivalent_system_datatype!(i16, ffi::RSMPI_INT16_T);
198equivalent_system_datatype!(i32, ffi::RSMPI_INT32_T);
199equivalent_system_datatype!(i64, ffi::RSMPI_INT64_T);
200
201equivalent_system_datatype!(u8, ffi::RSMPI_UINT8_T);
202equivalent_system_datatype!(u16, ffi::RSMPI_UINT16_T);
203equivalent_system_datatype!(u32, ffi::RSMPI_UINT32_T);
204equivalent_system_datatype!(u64, ffi::RSMPI_UINT64_T);
205
206#[cfg(target_pointer_width = "32")]
207equivalent_system_datatype!(usize, ffi::RSMPI_UINT32_T);
208#[cfg(target_pointer_width = "32")]
209equivalent_system_datatype!(isize, ffi::RSMPI_INT32_T);
210
211#[cfg(target_pointer_width = "64")]
212equivalent_system_datatype!(usize, ffi::RSMPI_UINT64_T);
213#[cfg(target_pointer_width = "64")]
214equivalent_system_datatype!(isize, ffi::RSMPI_INT64_T);
215
216#[cfg(feature = "complex")]
217pub mod complex_datatype {
219 use super::{ffi, DatatypeRef, Equivalence, FromRaw, SystemDatatype};
220 use num_complex::{Complex32, Complex64};
221 equivalent_system_datatype!(Complex32, ffi::RSMPI_FLOAT_COMPLEX);
222 equivalent_system_datatype!(Complex64, ffi::RSMPI_DOUBLE_COMPLEX);
223}
224
225pub struct UserDatatype(MPI_Datatype);
231
232impl UserDatatype {
233 pub fn contiguous<D>(count: Count, oldtype: &D) -> UserDatatype
242 where
243 D: UncommittedDatatype,
244 {
245 UncommittedUserDatatype::contiguous(count, oldtype).commit()
246 }
247
248 pub fn vector<D>(count: Count, blocklength: Count, stride: Count, oldtype: &D) -> UserDatatype
258 where
259 D: UncommittedDatatype,
260 {
261 UncommittedUserDatatype::vector(count, blocklength, stride, oldtype).commit()
262 }
263
264 pub fn heterogeneous_vector<D>(
270 count: Count,
271 blocklength: Count,
272 stride: Address,
273 oldtype: &D,
274 ) -> UserDatatype
275 where
276 D: UncommittedDatatype,
277 {
278 UncommittedUserDatatype::heterogeneous_vector(count, blocklength, stride, oldtype).commit()
279 }
280
281 pub fn indexed<D>(blocklengths: &[Count], displacements: &[Count], oldtype: &D) -> UserDatatype
289 where
290 D: UncommittedDatatype,
291 {
292 UncommittedUserDatatype::indexed(blocklengths, displacements, oldtype).commit()
293 }
294
295 pub fn heterogeneous_indexed<D>(
303 blocklengths: &[Count],
304 displacements: &[Address],
305 oldtype: &D,
306 ) -> UserDatatype
307 where
308 D: UncommittedDatatype,
309 {
310 UncommittedUserDatatype::heterogeneous_indexed(blocklengths, displacements, oldtype)
311 .commit()
312 }
313
314 pub fn indexed_block<D>(
320 blocklength: Count,
321 displacements: &[Count],
322 oldtype: &D,
323 ) -> UserDatatype
324 where
325 D: UncommittedDatatype,
326 {
327 UncommittedUserDatatype::indexed_block(blocklength, displacements, oldtype).commit()
328 }
329
330 pub fn heterogeneous_indexed_block<D>(
337 blocklength: Count,
338 displacements: &[Address],
339 oldtype: &D,
340 ) -> UserDatatype
341 where
342 D: UncommittedDatatype,
343 {
344 UncommittedUserDatatype::heterogeneous_indexed_block(blocklength, displacements, oldtype)
345 .commit()
346 }
347
348 pub fn structured<D>(
357 blocklengths: &[Count],
358 displacements: &[Address],
359 types: &[D],
360 ) -> UserDatatype
361 where
362 D: UncommittedDatatype + MatchesRaw<Raw = MPI_Datatype>,
363 {
364 UncommittedUserDatatype::structured(blocklengths, displacements, types).commit()
365 }
366
367 pub fn as_ref(&self) -> DatatypeRef<'_> {
369 unsafe { DatatypeRef::from_raw(self.as_raw()) }
370 }
371}
372
373unsafe impl Send for UserDatatype {}
379unsafe impl Sync for UserDatatype {}
380
381impl Clone for UserDatatype {
382 fn clone(&self) -> Self {
383 self.dup()
384 }
385}
386
387impl Drop for UserDatatype {
388 fn drop(&mut self) {
389 unsafe {
390 ffi::MPI_Type_free(&mut self.0);
391 }
392 assert_eq!(self.0, unsafe { ffi::RSMPI_DATATYPE_NULL });
393 }
394}
395
396unsafe impl AsRaw for UserDatatype {
397 type Raw = MPI_Datatype;
398 fn as_raw(&self) -> Self::Raw {
399 self.0
400 }
401}
402
403impl FromRaw for UserDatatype {
404 unsafe fn from_raw(handle: MPI_Datatype) -> Self {
405 assert_ne!(handle, ffi::RSMPI_DATATYPE_NULL);
406 UserDatatype(handle)
407 }
408}
409
410unsafe impl MatchesRaw for UserDatatype {}
411
412impl Datatype for UserDatatype {}
413impl UncommittedDatatype for UserDatatype {
414 type DuplicatedDatatype = UserDatatype;
415}
416
417impl<'a> From<&'a UserDatatype> for DatatypeRef<'a> {
418 fn from(datatype: &'a UserDatatype) -> Self {
419 unsafe { DatatypeRef::from_raw(datatype.as_raw()) }
420 }
421}
422
423impl<'a> From<&'a UserDatatype> for UncommittedDatatypeRef<'a> {
424 fn from(datatype: &'a UserDatatype) -> Self {
425 unsafe { UncommittedDatatypeRef::from_raw(datatype.as_raw()) }
426 }
427}
428
429pub struct UncommittedUserDatatype(MPI_Datatype);
438
439impl UncommittedUserDatatype {
440 pub fn contiguous<D>(count: Count, oldtype: &D) -> Self
449 where
450 D: UncommittedDatatype,
451 {
452 unsafe {
453 UncommittedUserDatatype(
454 with_uninitialized(|newtype| {
455 ffi::MPI_Type_contiguous(count, oldtype.as_raw(), newtype)
456 })
457 .1,
458 )
459 }
460 }
461
462 pub fn vector<D>(count: Count, blocklength: Count, stride: Count, oldtype: &D) -> Self
472 where
473 D: UncommittedDatatype,
474 {
475 unsafe {
476 UncommittedUserDatatype(
477 with_uninitialized(|newtype| {
478 ffi::MPI_Type_vector(count, blocklength, stride, oldtype.as_raw(), newtype)
479 })
480 .1,
481 )
482 }
483 }
484
485 pub fn heterogeneous_vector<D>(
491 count: Count,
492 blocklength: Count,
493 stride: Address,
494 oldtype: &D,
495 ) -> Self
496 where
497 D: UncommittedDatatype,
498 {
499 unsafe {
500 UncommittedUserDatatype(
501 with_uninitialized(|newtype| {
502 ffi::MPI_Type_create_hvector(
503 count,
504 blocklength,
505 stride,
506 oldtype.as_raw(),
507 newtype,
508 )
509 })
510 .1,
511 )
512 }
513 }
514
515 pub fn indexed<D>(blocklengths: &[Count], displacements: &[Count], oldtype: &D) -> Self
523 where
524 D: UncommittedDatatype,
525 {
526 assert_eq!(
527 blocklengths.len(),
528 displacements.len(),
529 "'blocklengths' and 'displacements' must be the same length"
530 );
531
532 unsafe {
533 UncommittedUserDatatype(
534 with_uninitialized(|newtype| {
535 ffi::MPI_Type_indexed(
536 blocklengths.count(),
537 blocklengths.as_ptr(),
538 displacements.as_ptr(),
539 oldtype.as_raw(),
540 newtype,
541 )
542 })
543 .1,
544 )
545 }
546 }
547
548 pub fn heterogeneous_indexed<D>(
556 blocklengths: &[Count],
557 displacements: &[Address],
558 oldtype: &D,
559 ) -> Self
560 where
561 D: UncommittedDatatype,
562 {
563 assert_eq!(
564 blocklengths.len(),
565 displacements.len(),
566 "'blocklengths' and 'displacements' must be the same length"
567 );
568 unsafe {
569 UncommittedUserDatatype(
570 with_uninitialized(|newtype| {
571 ffi::MPI_Type_create_hindexed(
572 blocklengths.count(),
573 blocklengths.as_ptr(),
574 displacements.as_ptr(),
575 oldtype.as_raw(),
576 newtype,
577 )
578 })
579 .1,
580 )
581 }
582 }
583
584 pub fn indexed_block<D>(blocklength: Count, displacements: &[Count], oldtype: &D) -> Self
590 where
591 D: UncommittedDatatype,
592 {
593 unsafe {
594 UncommittedUserDatatype(
595 with_uninitialized(|newtype| {
596 ffi::MPI_Type_create_indexed_block(
597 displacements.count(),
598 blocklength,
599 displacements.as_ptr(),
600 oldtype.as_raw(),
601 newtype,
602 )
603 })
604 .1,
605 )
606 }
607 }
608
609 pub fn heterogeneous_indexed_block<D>(
616 blocklength: Count,
617 displacements: &[Address],
618 oldtype: &D,
619 ) -> Self
620 where
621 D: UncommittedDatatype,
622 {
623 unsafe {
624 UncommittedUserDatatype(
625 with_uninitialized(|newtype| {
626 ffi::MPI_Type_create_hindexed_block(
627 displacements.count(),
628 blocklength,
629 displacements.as_ptr(),
630 oldtype.as_raw(),
631 newtype,
632 )
633 })
634 .1,
635 )
636 }
637 }
638
639 pub fn structured<D>(blocklengths: &[Count], displacements: &[Address], types: &[D]) -> Self
648 where
649 D: UncommittedDatatype + MatchesRaw<Raw = MPI_Datatype>,
650 {
651 assert_eq!(
652 blocklengths.len(),
653 displacements.len(),
654 "'displacements', 'blocklengths', and 'types' must be the same length"
655 );
656 assert_eq!(
657 blocklengths.len(),
658 types.len(),
659 "'displacements', 'blocklengths', and 'types' must be the same length"
660 );
661
662 unsafe {
663 UncommittedUserDatatype(
664 with_uninitialized(|newtype| {
665 ffi::MPI_Type_create_struct(
666 blocklengths.count(),
667 blocklengths.as_ptr(),
668 displacements.as_ptr(),
669 types.as_ptr() as *const _,
670 newtype,
671 )
672 })
673 .1,
674 )
675 }
676 }
677
678 pub fn commit(mut self) -> UserDatatype {
683 let handle = self.0;
684 unsafe {
685 ffi::MPI_Type_commit(&mut self.0);
686 }
687 mem::forget(self);
688 UserDatatype(handle)
689 }
690
691 pub fn as_ref(&self) -> UncommittedDatatypeRef<'_> {
693 unsafe { UncommittedDatatypeRef::from_raw(self.as_raw()) }
694 }
695}
696
697impl Clone for UncommittedUserDatatype {
698 fn clone(&self) -> Self {
699 self.dup()
700 }
701}
702
703impl Drop for UncommittedUserDatatype {
704 fn drop(&mut self) {
705 unsafe {
706 ffi::MPI_Type_free(&mut self.0);
707 }
708 assert_eq!(self.0, unsafe { ffi::RSMPI_DATATYPE_NULL });
709 }
710}
711
712unsafe impl AsRaw for UncommittedUserDatatype {
713 type Raw = MPI_Datatype;
714 fn as_raw(&self) -> Self::Raw {
715 self.0
716 }
717}
718
719impl FromRaw for UncommittedUserDatatype {
720 unsafe fn from_raw(handle: MPI_Datatype) -> Self {
721 assert_ne!(handle, ffi::RSMPI_DATATYPE_NULL);
722 UncommittedUserDatatype(handle)
723 }
724}
725
726unsafe impl MatchesRaw for UncommittedUserDatatype {}
727
728impl UncommittedDatatype for UncommittedUserDatatype {
729 type DuplicatedDatatype = UncommittedUserDatatype;
730}
731
732impl<'a> From<&'a UncommittedUserDatatype> for UncommittedDatatypeRef<'a> {
733 fn from(datatype: &'a UncommittedUserDatatype) -> Self {
734 unsafe { UncommittedDatatypeRef::from_raw(datatype.as_raw()) }
735 }
736}
737
738pub trait Datatype: UncommittedDatatype {}
743impl<'a, D> Datatype for &'a D where D: 'a + Datatype {}
744
745pub trait UncommittedDatatype: AsRaw<Raw = MPI_Datatype> {
750 type DuplicatedDatatype: FromRaw<Raw = MPI_Datatype>;
752
753 fn dup(&self) -> Self::DuplicatedDatatype {
758 unsafe {
759 Self::DuplicatedDatatype::from_raw(
760 with_uninitialized(|newtype| ffi::MPI_Type_dup(self.as_raw(), newtype)).1,
761 )
762 }
763 }
764}
765impl<'a, D> UncommittedDatatype for &'a D
766where
767 D: 'a + UncommittedDatatype,
768{
769 type DuplicatedDatatype = <D as UncommittedDatatype>::DuplicatedDatatype;
770}
771
772pub unsafe trait AsDatatype {
774 type Out: Datatype;
776 fn as_datatype(&self) -> Self::Out;
778}
779
780unsafe impl<T> AsDatatype for T
781where
782 T: Equivalence,
783{
784 type Out = <T as Equivalence>::Out;
785 fn as_datatype(&self) -> Self::Out {
786 <T as Equivalence>::equivalent_datatype()
787 }
788}
789
790unsafe impl<T> AsDatatype for [T]
791where
792 T: Equivalence,
793{
794 type Out = <T as Equivalence>::Out;
795 fn as_datatype(&self) -> Self::Out {
796 <T as Equivalence>::equivalent_datatype()
797 }
798}
799
800unsafe impl<T> AsDatatype for Vec<T>
801where
802 T: Equivalence,
803{
804 type Out = <T as Equivalence>::Out;
805 fn as_datatype(&self) -> Self::Out {
806 <T as Equivalence>::equivalent_datatype()
807 }
808}
809
810unsafe impl<T, const D: usize> AsDatatype for [T; D]
811where
812 T: Equivalence,
813{
814 type Out = <T as Equivalence>::Out;
815 fn as_datatype(&self) -> Self::Out {
816 <T as Equivalence>::equivalent_datatype()
817 }
818}
819
820#[doc(hidden)]
821pub mod internal {
822 #[cfg(feature = "derive")]
823 pub fn check_derive_equivalence_universe_state(type_name: &str) {
824 use crate::environment::UNIVERSE_STATE;
825
826 let universe_state = UNIVERSE_STATE.read().unwrap();
828
829 if !crate::environment::is_initialized() {
830 panic!(
831 "\n\
832 RSMPI PANIC: Pre-MPI_Init datatype initialization\n\
833 \n\
834 Application attempted to initialize datatype of #[derive(Equivalence)] for \
835 `{}` before initializing rsmpi. You must first initialize rsmpi before attempting \
836 to use a custom type in an MPI call.\n",
837 type_name
838 );
839 }
840
841 let universe_state = universe_state.as_ref().unwrap();
842
843 if crate::environment::is_finalized() {
844 panic!(
845 "\n\
846 RSMPI PANIC: Post-MPI_Finalize datatype initialization.\n\
847 \n\
848 Application attempted to initialize datatype of #[derive(Equivalence)] for \
849 `{0}` after finalizing rsmpi. You must not attempt to use `{0}` in an MPI context \
850 after finalizing rsmpi.\n",
851 type_name
852 );
853 }
854
855 if crate::environment::threading_support() != crate::Threading::Multiple
856 && universe_state.main_thread != std::thread::current().id()
857 {
858 panic!(
859 "\n\
860 RSMPI PANIC: Invalid threaded datatype initialization\n\
861 \n\
862 Application attempted to initialize the datatype of #[derive(Equivalence)]
863 for `{0}` from a different thread than that which initialized `rsmpi`. This \
864 is only supported when rsmpi is initialized with \
865 `mpi::Threading::Multiple`. Please explicitly call \
866 `{0}::equivalent_datatype()` at least once from the same thread as you call \
867 `rsmpi::initialize*`, or initialize MPI using \
868 `mpi::initialize_with_threading(mpi::Threading::Multiple)`.\n",
869 type_name
870 )
871 }
872 }
873}
874
875pub unsafe trait Collection {
877 fn count(&self) -> Count;
879}
880
881unsafe impl<T> Collection for T
882where
883 T: Equivalence,
884{
885 fn count(&self) -> Count {
886 1
887 }
888}
889
890unsafe impl<T> Collection for [T]
891where
892 T: Equivalence,
893{
894 fn count(&self) -> Count {
895 self.len()
896 .value_as()
897 .expect("Length of slice cannot be expressed as an MPI Count.")
898 }
899}
900
901unsafe impl<T> Collection for Vec<T>
902where
903 T: Equivalence,
904{
905 fn count(&self) -> Count {
906 self.len()
907 .value_as()
908 .expect("Length of slice cannot be expressed as an MPI Count.")
909 }
910}
911
912unsafe impl<T, const D: usize> Collection for [T; D]
913where
914 T: Equivalence,
915{
916 fn count(&self) -> Count {
917 D.value_as()
919 .expect("Length of slice cannot be expressed as an MPI Count.")
920 }
921}
922
923pub unsafe trait Pointer {
925 fn pointer(&self) -> *const c_void;
927}
928
929unsafe impl<T> Pointer for T
930where
931 T: Equivalence,
932{
933 fn pointer(&self) -> *const c_void {
934 let p: *const T = self;
935 p as *const c_void
936 }
937}
938
939unsafe impl<T> Pointer for [T]
940where
941 T: Equivalence,
942{
943 fn pointer(&self) -> *const c_void {
944 self.as_ptr() as _
945 }
946}
947
948unsafe impl<T> Pointer for Vec<T>
949where
950 T: Equivalence,
951{
952 fn pointer(&self) -> *const c_void {
953 self.as_ptr() as _
954 }
955}
956
957unsafe impl<T, const D: usize> Pointer for [T; D]
958where
959 T: Equivalence,
960{
961 fn pointer(&self) -> *const c_void {
962 self.as_ptr() as _
963 }
964}
965
966pub unsafe trait PointerMut {
968 fn pointer_mut(&mut self) -> *mut c_void;
970}
971
972unsafe impl<T> PointerMut for T
973where
974 T: Equivalence,
975{
976 fn pointer_mut(&mut self) -> *mut c_void {
977 let p: *mut T = self;
978 p as *mut c_void
979 }
980}
981
982unsafe impl<T> PointerMut for [T]
983where
984 T: Equivalence,
985{
986 fn pointer_mut(&mut self) -> *mut c_void {
987 self.as_mut_ptr() as _
988 }
989}
990
991unsafe impl<T> PointerMut for Vec<T>
992where
993 T: Equivalence,
994{
995 fn pointer_mut(&mut self) -> *mut c_void {
996 self.as_mut_ptr() as _
997 }
998}
999
1000unsafe impl<T, const D: usize> PointerMut for [T; D]
1001where
1002 T: Equivalence,
1003{
1004 fn pointer_mut(&mut self) -> *mut c_void {
1005 self.as_mut_ptr() as _
1006 }
1007}
1008
1009pub unsafe trait Buffer: Pointer + Collection + AsDatatype {}
1012unsafe impl<T> Buffer for T where T: Equivalence {}
1013unsafe impl<T> Buffer for [T] where T: Equivalence {}
1014unsafe impl<T> Buffer for Vec<T> where T: Equivalence {}
1015unsafe impl<T, const D: usize> Buffer for [T; D] where T: Equivalence {}
1016
1017pub unsafe trait BufferMut: PointerMut + Collection + AsDatatype {}
1020unsafe impl<T> BufferMut for T where T: Equivalence {}
1021unsafe impl<T> BufferMut for [T] where T: Equivalence {}
1022unsafe impl<T> BufferMut for Vec<T> where T: Equivalence {}
1023unsafe impl<T, const D: usize> BufferMut for [T; D] where T: Equivalence {}
1024
1025#[derive(Copy, Clone, Debug)]
1031pub struct DynBuffer<'a> {
1032 ptr: *const c_void,
1033 len: Count,
1034 datatype: DatatypeRef<'a>,
1035}
1036
1037unsafe impl<'a> Send for DynBuffer<'a> {}
1038
1039unsafe impl<'a> Sync for DynBuffer<'a> {}
1040
1041unsafe impl<'a> Collection for DynBuffer<'a> {
1042 fn count(&self) -> Count {
1043 self.len
1044 }
1045}
1046
1047unsafe impl<'a> Pointer for DynBuffer<'a> {
1048 fn pointer(&self) -> *const c_void {
1049 self.ptr
1050 }
1051}
1052
1053unsafe impl<'a> AsDatatype for DynBuffer<'a> {
1054 type Out = DatatypeRef<'a>;
1055 fn as_datatype(&self) -> Self::Out {
1056 self.datatype
1057 }
1058}
1059
1060unsafe impl<'a> Buffer for DynBuffer<'a> {}
1061
1062impl<'a> DynBuffer<'a> {
1063 pub fn new<T: Equivalence>(buf: &'a [T]) -> Self {
1065 unsafe {
1066 let datatype = DatatypeRef::from_raw(T::equivalent_datatype().as_raw());
1067 Self::from_raw(buf.as_ptr(), buf.count(), datatype)
1068 }
1069 }
1070
1071 pub fn is<T: Equivalence>(&self) -> bool {
1073 self.as_datatype().as_raw() == T::equivalent_datatype().as_raw()
1074 }
1075
1076 pub fn downcast<T: Equivalence>(self) -> Option<&'a [T]> {
1078 if self.is::<T>() {
1079 unsafe { Some(slice::from_raw_parts(self.as_ptr() as _, self.len())) }
1080 } else {
1081 None
1082 }
1083 }
1084
1085 pub unsafe fn from_raw<T>(ptr: *const T, len: Count, datatype: DatatypeRef<'a>) -> Self {
1093 debug_assert!(!ptr.is_null());
1094 Self {
1095 ptr: ptr as _,
1096 len,
1097 datatype,
1098 }
1099 }
1100
1101 pub fn len(&self) -> usize {
1103 self.count()
1104 .value_as()
1105 .expect("Length of DynBuffer cannot be expressed as a usize")
1106 }
1107
1108 pub fn is_empty(&self) -> bool {
1110 self.len() == 0
1111 }
1112
1113 pub fn as_ptr(&self) -> *const c_void {
1115 self.ptr
1116 }
1117}
1118
1119#[derive(Debug)]
1125pub struct DynBufferMut<'a> {
1126 ptr: *mut c_void,
1127 len: Count,
1128 datatype: DatatypeRef<'a>,
1129}
1130
1131unsafe impl<'a> Send for DynBufferMut<'a> {}
1132
1133unsafe impl<'a> Sync for DynBufferMut<'a> {}
1134
1135unsafe impl<'a> Collection for DynBufferMut<'a> {
1136 fn count(&self) -> Count {
1137 self.len
1138 }
1139}
1140
1141unsafe impl<'a> Pointer for DynBufferMut<'a> {
1142 fn pointer(&self) -> *const c_void {
1143 self.ptr
1144 }
1145}
1146
1147unsafe impl<'a> PointerMut for DynBufferMut<'a> {
1148 fn pointer_mut(&mut self) -> *mut c_void {
1149 self.ptr
1150 }
1151}
1152
1153unsafe impl<'a> Buffer for DynBufferMut<'a> {}
1154
1155unsafe impl<'a> BufferMut for DynBufferMut<'a> {}
1156
1157unsafe impl<'a> AsDatatype for DynBufferMut<'a> {
1158 type Out = DatatypeRef<'a>;
1159 fn as_datatype(&self) -> Self::Out {
1160 self.datatype
1161 }
1162}
1163
1164impl<'a> DynBufferMut<'a> {
1165 pub fn new<T: Equivalence>(buf: &'a mut [T]) -> Self {
1167 unsafe {
1168 let datatype = DatatypeRef::from_raw(T::equivalent_datatype().as_raw());
1169 Self::from_raw(buf.as_mut_ptr(), buf.count(), datatype)
1170 }
1171 }
1172
1173 pub fn is<T: Equivalence>(&self) -> bool {
1175 self.as_datatype().as_raw() == T::equivalent_datatype().as_raw()
1176 }
1177
1178 pub fn downcast<T: Equivalence>(mut self) -> Option<&'a mut [T]> {
1180 if self.is::<T>() {
1181 unsafe {
1182 Some(slice::from_raw_parts_mut(
1183 self.as_mut_ptr() as _,
1184 self.len(),
1185 ))
1186 }
1187 } else {
1188 None
1189 }
1190 }
1191
1192 pub unsafe fn from_raw<T>(ptr: *mut T, len: Count, datatype: DatatypeRef<'a>) -> Self {
1201 debug_assert!(!ptr.is_null());
1202 Self {
1203 ptr: ptr as _,
1204 len,
1205 datatype,
1206 }
1207 }
1208
1209 pub fn len(&self) -> usize {
1211 self.count()
1212 .value_as()
1213 .expect("Length of DynBufferMut cannot be expressed as a usize")
1214 }
1215
1216 pub fn is_empty(&self) -> bool {
1218 self.len() == 0
1219 }
1220
1221 pub fn as_ptr(&self) -> *const c_void {
1223 self.ptr
1224 }
1225
1226 pub fn as_mut_ptr(&mut self) -> *mut c_void {
1228 self.ptr
1229 }
1230
1231 pub fn reborrow(&self) -> DynBuffer {
1233 unsafe { DynBuffer::from_raw(self.as_ptr(), self.count(), self.as_datatype()) }
1234 }
1235
1236 pub fn reborrow_mut(&mut self) -> DynBufferMut {
1238 unsafe { DynBufferMut::from_raw(self.as_mut_ptr(), self.count(), self.as_datatype()) }
1239 }
1240
1241 pub fn downgrade(self) -> DynBuffer<'a> {
1243 unsafe { DynBuffer::from_raw(self.as_ptr(), self.count(), self.as_datatype()) }
1244 }
1245}
1246
1247pub struct View<'d, 'b, D, B: ?Sized>
1255where
1256 D: 'd + Datatype,
1257 B: 'b + Pointer,
1258{
1259 datatype: &'d D,
1260 count: Count,
1261 buffer: &'b B,
1262}
1263
1264impl<'d, 'b, D, B: ?Sized> View<'d, 'b, D, B>
1265where
1266 D: 'd + Datatype,
1267 B: 'b + Pointer,
1268{
1269 pub unsafe fn with_count_and_datatype(
1278 buffer: &'b B,
1279 count: Count,
1280 datatype: &'d D,
1281 ) -> View<'d, 'b, D, B> {
1282 View {
1283 datatype,
1284 count,
1285 buffer,
1286 }
1287 }
1288}
1289
1290unsafe impl<'d, 'b, D, B: ?Sized> AsDatatype for View<'d, 'b, D, B>
1291where
1292 D: 'd + Datatype,
1293 B: 'b + Pointer,
1294{
1295 type Out = &'d D;
1296 fn as_datatype(&self) -> Self::Out {
1297 self.datatype
1298 }
1299}
1300
1301unsafe impl<'d, 'b, D, B: ?Sized> Collection for View<'d, 'b, D, B>
1302where
1303 D: 'd + Datatype,
1304 B: 'b + Pointer,
1305{
1306 fn count(&self) -> Count {
1307 self.count
1308 }
1309}
1310
1311unsafe impl<'d, 'b, D, B: ?Sized> Pointer for View<'d, 'b, D, B>
1312where
1313 D: 'd + Datatype,
1314 B: 'b + Pointer,
1315{
1316 fn pointer(&self) -> *const c_void {
1317 self.buffer.pointer()
1318 }
1319}
1320
1321unsafe impl<'d, 'b, D, B: ?Sized> Buffer for View<'d, 'b, D, B>
1322where
1323 D: 'd + Datatype,
1324 B: 'b + Pointer,
1325{
1326}
1327
1328pub struct MutView<'d, 'b, D, B: ?Sized>
1336where
1337 D: 'd + Datatype,
1338 B: 'b + PointerMut,
1339{
1340 datatype: &'d D,
1341 count: Count,
1342 buffer: &'b mut B,
1343}
1344
1345impl<'d, 'b, D, B: ?Sized> MutView<'d, 'b, D, B>
1346where
1347 D: 'd + Datatype,
1348 B: 'b + PointerMut,
1349{
1350 pub unsafe fn with_count_and_datatype(
1359 buffer: &'b mut B,
1360 count: Count,
1361 datatype: &'d D,
1362 ) -> MutView<'d, 'b, D, B> {
1363 MutView {
1364 datatype,
1365 count,
1366 buffer,
1367 }
1368 }
1369}
1370
1371unsafe impl<'d, 'b, D, B: ?Sized> AsDatatype for MutView<'d, 'b, D, B>
1372where
1373 D: 'd + Datatype,
1374 B: 'b + PointerMut,
1375{
1376 type Out = &'d D;
1377 fn as_datatype(&self) -> Self::Out {
1378 self.datatype
1379 }
1380}
1381
1382unsafe impl<'d, 'b, D, B: ?Sized> Collection for MutView<'d, 'b, D, B>
1383where
1384 D: 'd + Datatype,
1385 B: 'b + PointerMut,
1386{
1387 fn count(&self) -> Count {
1388 self.count
1389 }
1390}
1391
1392unsafe impl<'d, 'b, D, B: ?Sized> PointerMut for MutView<'d, 'b, D, B>
1393where
1394 D: 'd + Datatype,
1395 B: 'b + PointerMut,
1396{
1397 fn pointer_mut(&mut self) -> *mut c_void {
1398 self.buffer.pointer_mut()
1399 }
1400}
1401
1402unsafe impl<'d, 'b, D, B: ?Sized> BufferMut for MutView<'d, 'b, D, B>
1403where
1404 D: 'd + Datatype,
1405 B: 'b + PointerMut,
1406{
1407}
1408
1409pub trait Partitioned {
1412 fn counts(&self) -> &[Count];
1414 fn displs(&self) -> &[Count];
1416}
1417
1418pub trait PartitionedBuffer: Partitioned + Pointer + AsDatatype {}
1420
1421pub trait PartitionedBufferMut: Partitioned + PointerMut + AsDatatype {}
1423
1424pub struct Partition<'b, B: 'b + ?Sized, C, D> {
1426 buf: &'b B,
1427 counts: C,
1428 displs: D,
1429}
1430
1431impl<'b, B: ?Sized, C, D> Partition<'b, B, C, D>
1432where
1433 B: 'b + Buffer,
1434 C: Borrow<[Count]>,
1435 D: Borrow<[Count]>,
1436{
1437 pub fn new(buf: &B, counts: C, displs: D) -> Partition<B, C, D> {
1439 let n = buf.count();
1440 assert!(counts
1441 .borrow()
1442 .iter()
1443 .zip(displs.borrow().iter())
1444 .all(|(&c, &d)| c + d <= n));
1445
1446 Partition {
1447 buf,
1448 counts,
1449 displs,
1450 }
1451 }
1452}
1453
1454unsafe impl<'b, B: ?Sized, C, D> AsDatatype for Partition<'b, B, C, D>
1455where
1456 B: 'b + AsDatatype,
1457{
1458 type Out = <B as AsDatatype>::Out;
1459 fn as_datatype(&self) -> Self::Out {
1460 self.buf.as_datatype()
1461 }
1462}
1463
1464unsafe impl<'b, B: ?Sized, C, D> Pointer for Partition<'b, B, C, D>
1465where
1466 B: 'b + Pointer,
1467{
1468 fn pointer(&self) -> *const c_void {
1469 self.buf.pointer()
1470 }
1471}
1472
1473impl<'b, B: ?Sized, C, D> Partitioned for Partition<'b, B, C, D>
1474where
1475 B: 'b,
1476 C: Borrow<[Count]>,
1477 D: Borrow<[Count]>,
1478{
1479 fn counts(&self) -> &[Count] {
1480 self.counts.borrow()
1481 }
1482 fn displs(&self) -> &[Count] {
1483 self.displs.borrow()
1484 }
1485}
1486
1487impl<'b, B: ?Sized, C, D> PartitionedBuffer for Partition<'b, B, C, D>
1488where
1489 B: 'b + Pointer + AsDatatype,
1490 C: Borrow<[Count]>,
1491 D: Borrow<[Count]>,
1492{
1493}
1494
1495pub struct PartitionMut<'b, B: 'b + ?Sized, C, D> {
1497 buf: &'b mut B,
1498 counts: C,
1499 displs: D,
1500}
1501
1502impl<'b, B: ?Sized, C, D> PartitionMut<'b, B, C, D>
1503where
1504 B: 'b + BufferMut,
1505 C: Borrow<[Count]>,
1506 D: Borrow<[Count]>,
1507{
1508 pub fn new(buf: &mut B, counts: C, displs: D) -> PartitionMut<B, C, D> {
1510 let n = buf.count();
1511 assert!(counts
1512 .borrow()
1513 .iter()
1514 .zip(displs.borrow().iter())
1515 .all(|(&c, &d)| c + d <= n));
1516
1517 PartitionMut {
1518 buf,
1519 counts,
1520 displs,
1521 }
1522 }
1523}
1524
1525unsafe impl<'b, B: ?Sized, C, D> AsDatatype for PartitionMut<'b, B, C, D>
1526where
1527 B: 'b + AsDatatype,
1528{
1529 type Out = <B as AsDatatype>::Out;
1530 fn as_datatype(&self) -> Self::Out {
1531 self.buf.as_datatype()
1532 }
1533}
1534
1535unsafe impl<'b, B: ?Sized, C, D> PointerMut for PartitionMut<'b, B, C, D>
1536where
1537 B: 'b + PointerMut,
1538{
1539 fn pointer_mut(&mut self) -> *mut c_void {
1540 self.buf.pointer_mut()
1541 }
1542}
1543
1544impl<'b, B: ?Sized, C, D> Partitioned for PartitionMut<'b, B, C, D>
1545where
1546 B: 'b,
1547 C: Borrow<[Count]>,
1548 D: Borrow<[Count]>,
1549{
1550 fn counts(&self) -> &[Count] {
1551 self.counts.borrow()
1552 }
1553 fn displs(&self) -> &[Count] {
1554 self.displs.borrow()
1555 }
1556}
1557
1558impl<'b, B: ?Sized, C, D> PartitionedBufferMut for PartitionMut<'b, B, C, D>
1559where
1560 B: 'b + PointerMut + AsDatatype,
1561 C: Borrow<[Count]>,
1562 D: Borrow<[Count]>,
1563{
1564}
1565
1566pub fn address_of<T>(x: &T) -> Address {
1575 let x: *const T = x;
1576 unsafe { with_uninitialized(|address| ffi::MPI_Get_address(x as *const c_void, address)).1 }
1577}