devela/data/list/array/d2/definitions.rs
1// devela::data::list::array::d2::definitions
2//
3//! 2-dimensional array definitions
4//
5
6use crate::{Array, Bare, Storage};
7// #[cfg(feature = "dep_rkyv")] // DEP_DISABLED
8// use rkyv::{Archive, Deserialize, Serialize};
9
10#[doc = crate::TAG_DATA_STRUCTURE!()]
11/// A static 2-dimensional [`Array`].
12///
13/// It is generic in respect to its:
14/// - elements (`T`),
15/// - number of columns (`C`),
16/// - number of rows (`R`),
17/// - total capacity (`CR`),
18/// - storage order (`RMAJ`)
19/// - storage abstraction (`S`).
20///
21/// The total lenght `CR` must be equal to the product `C` * `R`.
22///
23/// The
24/// [*storage order*](https://en.wikipedia.org/wiki/Row-_and_column-major_order)
25/// is row-major by default (`RMAJ = true`). It can be column-major if set to false.
26///
27/// ## Methods
28///
29/// - Construct:
30/// [`with_cloned`][Self::with_cloned],
31/// [`with_copied`][Self::with_copied].
32/// - Deconstruct:
33/// [`as_slice`][Self::as_slice],
34/// [`as_mut_slice`][Self::as_mut_slice],
35/// [`into_array`][Self::into_array]*([`const`][Self::into_array_copy])*,
36/// [`into_slice`][Self::into_slice]*(`alloc`)*,
37/// [`into_vec`][Self::into_vec]*(`alloc`)*.
38/// - Query:
39/// [`capacity`][Self::capacity],
40/// [`cap_col`][Self::cap_col],
41/// [`cap_row`][Self::cap_row],
42/// [`contains`][Self::contains].
43/// - Indexing and coordinates (for the current order):
44/// - [`get_ref`][Self::get_ref]*([`uc`][Self::get_ref_unchecked])*,
45/// [`get_mut`][Self::get_mut]*([`uc`][Self::get_mut_unchecked])*,
46/// [`set`][Self::set]*([`uc`][Self::set_unchecked])*,
47/// [`get_index`][Self::get_index]*([`uc`][Self::get_index_unchecked])*,
48/// [`get_coords`][Self::get_coords]*([`uc`][Self::get_coords_unchecked])*.
49/// - Indexing and coordinates (specific for the **opposite** order):
50/// - row-major:
51/// [`get_ref_cmaj`][Self::get_ref_cmaj]*([`uc`][Self::get_ref_cmaj_unchecked])*,
52/// [`get_mut_cmaj`][Self::get_mut_cmaj]*([`uc`][Self::get_mut_cmaj_unchecked])*,
53/// [`set_cmaj`][Self::set_cmaj]*([`uc`][Self::set_cmaj_unchecked])*,
54/// [`get_index_cmaj`][Self::get_index_cmaj]*([`uc`][Self::get_index_cmaj_unchecked])*,
55/// [`get_coords_cmaj`][Self::get_coords_cmaj]*([`uc`][Self::get_coords_cmaj_unchecked])*.
56/// - column-major:
57/// [`get_ref_rmaj`][Self::get_ref_rmaj]*([`uc`][Self::get_ref_rmaj_unchecked])*,
58/// [`get_mut_rmaj`][Self::get_mut_rmaj]*([`uc`][Self::get_mut_rmaj_unchecked])*,
59/// [`set_rmaj`][Self::set_rmaj]*([`uc`][Self::set_rmaj_unchecked])*,
60/// [`get_index_rmaj`][Self::get_index_rmaj]*([`uc`][Self::get_index_rmaj_unchecked])*,
61/// [`get_coords_rmaj`][Self::get_coords_rmaj]*([`uc`][Self::get_coords_rmaj_unchecked])*.
62///
63/// ## Panics
64/// Note that the `Default` and `ConstDefault` constructors will panic if `C * R != CR`.
65//
66// WAIT: [adt_const_params](https://github.com/rust-lang/rust/issues/95174)
67// would allow to use enums and arrays as const-generic parameters.
68// WAIT: [generic_const_exprs](https://github.com/rust-lang/rust/issues/76560)
69// would allow calculating CR automatically from C and R.
70// #[cfg_attr(feature = "dep_rkyv", derive(Archive, Serialize, Deserialize))]
71// rkyv(archived = Array2dArchived, attr(doc = crate::TAG_RKYV![])))]
72// #[cfg_attr(
73// all(feature = "dep_rkyv", feature = "nightly_doc"),
74// rkyv(attr(doc(cfg(feature = "dep_rkiv"))))
75// )]
76pub struct Array2d<
77 T,
78 const C: usize,
79 const R: usize,
80 const CR: usize,
81 const RMAJ: bool = true,
82 S: Storage = Bare,
83> {
84 pub(super) data: Array<T, CR, S>,
85}
86
87// SEE: https://docs.rs/rkyv/latest/rkyv/trait.Archive.html
88// #[cfg(feature = "dep_rkyv")]
89// #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "dep_rkyv")))]
90// mod impl_rkyv {
91// use rkyv::{
92// access_unchecked,
93// munge::munge,
94// rancor::{Error, Fallible},
95// ser::Writer,
96// to_bytes, Archive, ArchiveUnsized, Archived, Place, Portable, RelPtr, Serialize,
97// SerializeUnsized,
98// };
99//
100// /// XXX
101// #[repr(transparent)]
102// struct Array2dArchived {
103// ptr: RelPtr<str>,
104// }
105// impl Array2dArchived {}
106//
107// /// YYY
108// struct Array2dResolver {
109// // This will be the position that the bytes of our string are stored at.
110// pos: usize,
111// }
112//
113// impl Archive for Array2d {
114// type Archived = Array2dArchived;
115// type Resolver = Array2dResolver;
116//
117// // The resolve function consumes the resolver and produces the archived
118// // value at the given position.
119// fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
120// munge!(let Array2dArchived { ptr } = out);
121// RelPtr::emplace_unsized(resolver.pos, self.inner.archived_metadata(), ptr);
122// }
123// }
124//
125// // We restrict our serializer types with Writer because we need its
126// // capabilities to serialize the inner string. For other types, we might
127// // need more or less restrictive bounds on the type of S.
128// impl<S: Fallible + Writer + ?Sized> Serialize<S> for Array2d {
129// fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
130// // This is where we want to write the bytes of our string and return
131// // a resolver that knows where those bytes were written.
132// // We also need to serialize the metadata for our str.
133// Ok(OwnedStrResolver { pos: self.inner.serialize_unsized(serializer)? })
134// }
135// }
136//
137// #[cfg(test)]
138// fn test_array2d_arkyv() {
139// let value = Array2d::<_, 2, 2, 4>::with_cloned('€');
140// let buf = to_bytes::<Error>(&value).expect("failed to serialize");
141// #[cfg(feature = "unsafe")]
142// let archived = unsafe { access_unchecked::<ArchivedOwnedStr>(buf.as_ref()) };
143// // Let's make sure our data got written correctly TODO
144// // assert_eq!(archived.as_str(), STR_VAL);
145// }
146// }