1use crate::Count;
14
15pub mod ids {
19 pub const BOOL: u32 = 1;
21 pub const I8: u32 = 2;
23 pub const U8: u32 = 3;
25 pub const I16: u32 = 4;
27 pub const U16: u32 = 5;
29 pub const I32: u32 = 6;
31 pub const U32: u32 = 7;
33 pub const I64: u32 = 8;
35 pub const U64: u32 = 9;
37 pub const I128: u32 = 10;
39 pub const U128: u32 = 11;
41 pub const ISIZE: u32 = 12;
43 pub const USIZE: u32 = 13;
45 pub const F32: u32 = 14;
47 pub const F64: u32 = 15;
49 pub const CHAR: u32 = 16;
51 pub const USER_BASE: u32 = 1024;
53}
54
55#[cfg(target_endian = "big")]
59pub(crate) fn wire_elem_size(id: u32) -> usize {
60 match id {
61 ids::BOOL | ids::I8 | ids::U8 => 1,
62 ids::I16 | ids::U16 => 2,
63 ids::I32 | ids::U32 | ids::F32 | ids::CHAR => 4,
64 ids::I64 | ids::U64 | ids::ISIZE | ids::USIZE | ids::F64 => 8,
65 ids::I128 | ids::U128 => 16,
66 _ => 1,
67 }
68}
69
70#[derive(Clone, Copy, Debug, PartialEq, Eq)]
73pub struct DatatypeRef {
74 pub id: u32,
76 pub size: usize,
78}
79
80pub unsafe trait Equivalence: Copy + 'static {
90 fn equivalent_datatype() -> DatatypeRef;
92}
93
94macro_rules! impl_equivalence {
95 ($($t:ty => $id:expr),+ $(,)?) => {$(
96 unsafe impl Equivalence for $t {
98 fn equivalent_datatype() -> DatatypeRef {
99 DatatypeRef { id: $id, size: ::core::mem::size_of::<$t>() }
100 }
101 }
102 )+};
103}
104
105impl_equivalence! {
106 bool => ids::BOOL,
107 i8 => ids::I8,
108 u8 => ids::U8,
109 i16 => ids::I16,
110 u16 => ids::U16,
111 i32 => ids::I32,
112 u32 => ids::U32,
113 i64 => ids::I64,
114 u64 => ids::U64,
115 i128 => ids::I128,
116 u128 => ids::U128,
117 isize => ids::ISIZE,
118 usize => ids::USIZE,
119 f32 => ids::F32,
120 f64 => ids::F64,
121 char => ids::CHAR,
122}
123
124pub trait Collection {
127 fn count(&self) -> Count;
129 fn as_datatype(&self) -> DatatypeRef;
131}
132
133pub unsafe trait Buffer: Collection {
140 fn as_bytes(&self) -> &[u8];
142}
143
144pub unsafe trait BufferMut: Collection {
152 fn as_bytes_mut(&mut self) -> &mut [u8];
154
155 fn scatter_from(&mut self, bytes: &[u8]) {
162 let dst = self.as_bytes_mut();
163 let n = dst.len().min(bytes.len());
164 dst[..n].copy_from_slice(&bytes[..n]);
165 }
166}
167
168#[inline]
169fn as_byte_slice<T: Equivalence>(s: &[T]) -> &[u8] {
170 unsafe { core::slice::from_raw_parts(s.as_ptr() as *const u8, core::mem::size_of_val(s)) }
173}
174
175#[inline]
176fn as_byte_slice_mut<T: Equivalence>(s: &mut [T]) -> &mut [u8] {
177 unsafe { core::slice::from_raw_parts_mut(s.as_mut_ptr() as *mut u8, core::mem::size_of_val(s)) }
179}
180
181impl<T: Equivalence> Collection for T {
184 fn count(&self) -> Count {
185 1
186 }
187 fn as_datatype(&self) -> DatatypeRef {
188 T::equivalent_datatype()
189 }
190}
191
192unsafe impl<T: Equivalence> Buffer for T {
193 fn as_bytes(&self) -> &[u8] {
194 as_byte_slice(core::slice::from_ref(self))
195 }
196}
197
198unsafe impl<T: Equivalence> BufferMut for T {
199 fn as_bytes_mut(&mut self) -> &mut [u8] {
200 as_byte_slice_mut(core::slice::from_mut(self))
201 }
202}
203
204impl<T: Equivalence> Collection for [T] {
207 fn count(&self) -> Count {
208 self.len() as Count
209 }
210 fn as_datatype(&self) -> DatatypeRef {
211 T::equivalent_datatype()
212 }
213}
214
215unsafe impl<T: Equivalence> Buffer for [T] {
216 fn as_bytes(&self) -> &[u8] {
217 as_byte_slice(self)
218 }
219}
220
221unsafe impl<T: Equivalence> BufferMut for [T] {
222 fn as_bytes_mut(&mut self) -> &mut [u8] {
223 as_byte_slice_mut(self)
224 }
225}
226
227impl<T: Equivalence, const N: usize> Collection for [T; N] {
230 fn count(&self) -> Count {
231 N as Count
232 }
233 fn as_datatype(&self) -> DatatypeRef {
234 T::equivalent_datatype()
235 }
236}
237
238unsafe impl<T: Equivalence, const N: usize> Buffer for [T; N] {
239 fn as_bytes(&self) -> &[u8] {
240 as_byte_slice(self.as_slice())
241 }
242}
243
244unsafe impl<T: Equivalence, const N: usize> BufferMut for [T; N] {
245 fn as_bytes_mut(&mut self) -> &mut [u8] {
246 as_byte_slice_mut(self.as_mut_slice())
247 }
248}
249
250pub unsafe trait Partitioned {
259 fn as_datatype(&self) -> DatatypeRef;
261 fn counts(&self) -> &[Count];
263 fn displs(&self) -> &[Count];
265}
266
267pub unsafe trait PartitionedBuffer: Partitioned {
274 fn as_bytes(&self) -> &[u8];
276}
277
278pub unsafe trait PartitionedBufferMut: Partitioned {
284 fn as_bytes_mut(&mut self) -> &mut [u8];
286}
287
288pub struct Partition<'a, T: Equivalence> {
290 buf: &'a [T],
291 counts: Vec<Count>,
292 displs: Vec<Count>,
293}
294
295impl<'a, T: Equivalence> Partition<'a, T> {
296 pub fn new<C, D>(buf: &'a [T], counts: C, displs: D) -> Partition<'a, T>
299 where
300 C: Into<Vec<Count>>,
301 D: Into<Vec<Count>>,
302 {
303 Partition {
304 buf,
305 counts: counts.into(),
306 displs: displs.into(),
307 }
308 }
309}
310
311unsafe impl<T: Equivalence> Partitioned for Partition<'_, T> {
312 fn as_datatype(&self) -> DatatypeRef {
313 T::equivalent_datatype()
314 }
315 fn counts(&self) -> &[Count] {
316 &self.counts
317 }
318 fn displs(&self) -> &[Count] {
319 &self.displs
320 }
321}
322
323unsafe impl<T: Equivalence> PartitionedBuffer for Partition<'_, T> {
324 fn as_bytes(&self) -> &[u8] {
325 as_byte_slice(self.buf)
326 }
327}
328
329pub struct PartitionMut<'a, T: Equivalence> {
331 buf: &'a mut [T],
332 counts: Vec<Count>,
333 displs: Vec<Count>,
334}
335
336impl<'a, T: Equivalence> PartitionMut<'a, T> {
337 pub fn new<C, D>(buf: &'a mut [T], counts: C, displs: D) -> PartitionMut<'a, T>
340 where
341 C: Into<Vec<Count>>,
342 D: Into<Vec<Count>>,
343 {
344 PartitionMut {
345 buf,
346 counts: counts.into(),
347 displs: displs.into(),
348 }
349 }
350}
351
352unsafe impl<T: Equivalence> Partitioned for PartitionMut<'_, T> {
353 fn as_datatype(&self) -> DatatypeRef {
354 T::equivalent_datatype()
355 }
356 fn counts(&self) -> &[Count] {
357 &self.counts
358 }
359 fn displs(&self) -> &[Count] {
360 &self.displs
361 }
362}
363
364unsafe impl<T: Equivalence> PartitionedBufferMut for PartitionMut<'_, T> {
365 fn as_bytes_mut(&mut self) -> &mut [u8] {
366 as_byte_slice_mut(self.buf)
367 }
368}
369
370#[derive(Clone, Debug)]
383pub struct UserDatatype {
384 id: u32,
385 base: DatatypeRef,
386 blocks: Vec<(usize, usize)>,
388 extent: usize,
390 base_count: Count,
392}
393
394impl UserDatatype {
395 fn from_blocks(base: DatatypeRef, blocks: Vec<(usize, usize)>, extent: usize) -> UserDatatype {
396 let bytes: usize = blocks.iter().map(|(_, l)| *l).sum();
397 let base_count = (bytes / base.size.max(1)) as Count;
398 UserDatatype {
399 id: ids::USER_BASE + base.id,
400 base,
401 blocks,
402 extent,
403 base_count,
404 }
405 }
406
407 pub fn contiguous(count: Count, base: DatatypeRef) -> UserDatatype {
409 let len = count as usize * base.size;
410 UserDatatype::from_blocks(base, vec![(0, len)], len)
411 }
412
413 pub fn vector(
416 count: Count,
417 blocklength: Count,
418 stride: Count,
419 base: DatatypeRef,
420 ) -> UserDatatype {
421 let bl = blocklength as usize * base.size;
422 let mut blocks = Vec::with_capacity(count as usize);
423 for i in 0..count as usize {
424 blocks.push((i * stride as usize * base.size, bl));
425 }
426 let extent = if count == 0 {
427 0
428 } else {
429 ((count as usize - 1) * stride as usize + blocklength as usize) * base.size
430 };
431 UserDatatype::from_blocks(base, blocks, extent)
432 }
433
434 pub fn indexed(
437 blocklengths: &[Count],
438 displacements: &[Count],
439 base: DatatypeRef,
440 ) -> UserDatatype {
441 assert_eq!(blocklengths.len(), displacements.len());
442 let mut blocks = Vec::with_capacity(blocklengths.len());
443 let mut extent = 0usize;
444 for (bl, d) in blocklengths.iter().zip(displacements) {
445 let off = *d as usize * base.size;
446 let len = *bl as usize * base.size;
447 blocks.push((off, len));
448 extent = extent.max(off + len);
449 }
450 UserDatatype::from_blocks(base, blocks, extent)
451 }
452
453 pub fn structured(
456 blocklengths: &[Count],
457 byte_displacements: &[isize],
458 base: DatatypeRef,
459 ) -> UserDatatype {
460 assert_eq!(blocklengths.len(), byte_displacements.len());
461 let mut blocks = Vec::with_capacity(blocklengths.len());
462 let mut extent = 0usize;
463 for (bl, d) in blocklengths.iter().zip(byte_displacements) {
464 let off = *d as usize;
465 let len = *bl as usize * base.size;
466 blocks.push((off, len));
467 extent = extent.max(off + len);
468 }
469 UserDatatype::from_blocks(base, blocks, extent)
470 }
471
472 pub fn id(&self) -> u32 {
474 self.id
475 }
476
477 pub fn extent(&self) -> usize {
479 self.extent
480 }
481
482 pub fn base_count(&self) -> Count {
484 self.base_count
485 }
486
487 pub fn pack(&self, base: &[u8], count: Count) -> Vec<u8> {
490 let mut out =
491 Vec::with_capacity(count as usize * self.base_count as usize * self.base.size);
492 for e in 0..count as usize {
493 let elem = e * self.extent;
494 for &(off, len) in &self.blocks {
495 out.extend_from_slice(&base[elem + off..elem + off + len]);
496 }
497 }
498 out
499 }
500
501 pub fn unpack(&self, packed: &[u8], base: &mut [u8], count: Count) {
504 let mut pos = 0usize;
505 for e in 0..count as usize {
506 let elem = e * self.extent;
507 for &(off, len) in &self.blocks {
508 let end = (pos + len).min(packed.len());
509 let take = end - pos;
510 base[elem + off..elem + off + take].copy_from_slice(&packed[pos..pos + take]);
511 pos += take;
512 }
513 }
514 }
515}
516
517pub struct View {
520 packed: Vec<u8>,
521 base: DatatypeRef,
522}
523
524impl View {
525 pub fn with_count<B: Buffer + ?Sized>(buf: &B, datatype: &UserDatatype, count: Count) -> View {
527 View {
528 packed: datatype.pack(buf.as_bytes(), count),
529 base: datatype.base,
530 }
531 }
532}
533
534impl Collection for View {
535 fn count(&self) -> Count {
536 (self.packed.len() / self.base.size.max(1)) as Count
537 }
538 fn as_datatype(&self) -> DatatypeRef {
539 self.base
540 }
541}
542
543unsafe impl Buffer for View {
545 fn as_bytes(&self) -> &[u8] {
546 &self.packed
547 }
548}
549
550pub struct MutView<'a, B: BufferMut + ?Sized> {
553 base: &'a mut B,
554 datatype: UserDatatype,
555 count: Count,
556}
557
558impl<'a, B: BufferMut + ?Sized> MutView<'a, B> {
559 pub fn with_count(buf: &'a mut B, datatype: UserDatatype, count: Count) -> MutView<'a, B> {
561 MutView {
562 base: buf,
563 datatype,
564 count,
565 }
566 }
567}
568
569impl<B: BufferMut + ?Sized> Collection for MutView<'_, B> {
570 fn count(&self) -> Count {
571 self.datatype.base_count * self.count
572 }
573 fn as_datatype(&self) -> DatatypeRef {
574 self.datatype.base
575 }
576}
577
578unsafe impl<B: BufferMut + ?Sized> BufferMut for MutView<'_, B> {
581 fn as_bytes_mut(&mut self) -> &mut [u8] {
582 self.base.as_bytes_mut()
583 }
584 fn scatter_from(&mut self, bytes: &[u8]) {
585 self.datatype
586 .unpack(bytes, self.base.as_bytes_mut(), self.count);
587 }
588}
589
590#[cfg(test)]
591mod tests {
592 use super::*;
593
594 #[test]
595 fn datatype_ids_and_sizes() {
596 assert_eq!(i32::equivalent_datatype().id, ids::I32);
597 assert_eq!(i32::equivalent_datatype().size, 4);
598 assert_eq!(f64::equivalent_datatype().size, 8);
599 assert_eq!(u8::equivalent_datatype().size, 1);
600 }
601
602 #[test]
603 fn slice_byte_view_roundtrips() {
604 let data: [i32; 3] = [1, 2, 0x0102_0304];
605 let bytes = data.as_slice().as_bytes();
606 assert_eq!(bytes.len(), 12);
607 assert_eq!(<[i32] as Collection>::count(&data[..]), 3);
608 let mut out = [0i32; 3];
610 out.as_mut_slice().as_bytes_mut().copy_from_slice(bytes);
611 assert_eq!(out, data);
612 }
613
614 #[test]
615 fn scalar_is_a_buffer_of_one() {
616 let x = 7u64;
617 assert_eq!(Collection::count(&x), 1);
618 assert_eq!(x.as_bytes().len(), 8);
619 }
620
621 #[test]
622 fn vector_datatype_pack_unpack() {
623 let dt = UserDatatype::vector(3, 1, 2, i32::equivalent_datatype());
625 let base = [10i32, 11, 20, 21, 30, 31];
626 let packed = dt.pack(base.as_slice().as_bytes(), 1);
627 let got: Vec<i32> = crate::point_to_point::vec_from_bytes(&packed);
628 assert_eq!(got, vec![10, 20, 30]);
629
630 let mut out = [0i32; 6];
632 dt.unpack(&packed, out.as_mut_slice().as_bytes_mut(), 1);
633 assert_eq!(out, [10, 0, 20, 0, 30, 0]);
634 }
635
636 #[test]
637 fn contiguous_and_indexed() {
638 let c = UserDatatype::contiguous(4, f64::equivalent_datatype());
639 assert_eq!(c.base_count(), 4);
640 assert_eq!(c.extent(), 32);
641
642 let idx = UserDatatype::indexed(&[2, 1], &[0, 4], i32::equivalent_datatype());
643 let base = [1i32, 2, 3, 4, 5, 6];
644 let packed = idx.pack(base.as_slice().as_bytes(), 1);
645 let got: Vec<i32> = crate::point_to_point::vec_from_bytes(&packed);
646 assert_eq!(got, vec![1, 2, 5]);
647 }
648
649 #[test]
652 fn vector_pack_unpack_roundtrips() {
653 let mut state: u64 = 0xdead_beef_0000_0001;
654 let mut rng = || {
655 state ^= state << 13;
656 state ^= state >> 7;
657 state ^= state << 17;
658 state
659 };
660 for _ in 0..300 {
661 let count = (rng() % 4) as i32 + 1;
662 let blocklen = (rng() % 3) as i32 + 1;
663 let stride = blocklen + (rng() % 3) as i32; let dt = UserDatatype::vector(count, blocklen, stride, i32::equivalent_datatype());
665 let n_elems = dt.extent() / 4;
667 let base: Vec<i32> = (0..n_elems as i32).collect();
668 let packed = dt.pack(base.as_slice().as_bytes(), 1);
669 let got: Vec<i32> = crate::point_to_point::vec_from_bytes(&packed);
670
671 let mut expected = Vec::new();
673 for c in 0..count {
674 for k in 0..blocklen {
675 expected.push(c * stride + k);
676 }
677 }
678 assert_eq!(got, expected, "vector pack mismatch");
679
680 let mut out = vec![0i32; n_elems];
682 dt.unpack(&packed, out.as_mut_slice().as_bytes_mut(), 1);
683 for c in 0..count {
684 for k in 0..blocklen {
685 let idx = (c * stride + k) as usize;
686 assert_eq!(out[idx], idx as i32, "vector unpack mismatch");
687 }
688 }
689 }
690 }
691}