Skip to content

Commit cbea66b

Browse files
Created NestedTupleOptionWith
1 parent c4f3e84 commit cbea66b

5 files changed

Lines changed: 104 additions & 86 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929
- `NestedTupleIndex<Idx>` and `NestedTupleIndexMut<Idx>` traits for compile-time indexing into nested tuples using flat indices
3030
- `NestedTupleOption` trait for transposing nested tuples of options into options of nested tuples
3131
- `IntoNestedTupleOption` trait for converting nested tuples into nested tuples of options
32+
- `NestedTupleOptionWith<H>` trait providing `first_none_with`, `first_some_with`, and `transpose_or` helpers that work with a parallel homogeneous nested tuple `H` for result/error mapping
3233
- `NestedTupleReplicate<T>` trait for creating nested tuples by replicating a single value across all positions
3334
- `NestedTuplePopFront`, `NestedTuplePopBack`, `NestedTuplePushFront`, `NestedTuplePushBack` traits for manipulating nested tuples by popping/pushing elements at the front or back while preserving nested structure
3435
- `NestedTuplePopFront`, `NestedTuplePopBack`, `NestedTuplePushFront`, `NestedTuplePushBack` traits for manipulating nested tuples by popping/pushing elements at the front or back while preserving nested structure

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ The library provides several traits for working with tuples:
3131
- [`IntoTupleOption`](https://docs.rs/tuplities-option/latest/tuplities_option/trait.IntoTupleOption.html): Provides an [`into_options()`](https://docs.rs/tuplities-option/latest/tuplities_option/trait.IntoTupleOption.html#tymethod.into_options) method to convert a tuple into a tuple of options.
3232
- [`NestedTupleOption`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleOption.html): Provides a [`transpose()`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleOption.html#tymethod.transpose) method to transpose nested tuples of options into options of nested tuples.
3333
- [`IntoNestedTupleOption`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.IntoNestedTupleOption.html): Provides an [`into_options()`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.IntoNestedTupleOption.html#tymethod.into_options) method to convert nested tuples into nested tuples of options.
34+
- [`NestedTupleOptionWith<H>`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleOptionWith.html): Provides `first_none_with`, `first_some_with`, and `transpose_or` helpers which operate with a parallel homogeneous nested tuple of `H` used for result/error mapping.
3435
- [`NestedTupleTryFrom<T, E>`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleTryFrom.html): Provides a [`nested_tuple_try_from()`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleTryFrom.html#tymethod.nested_tuple_try_from) method to fallibly convert nested tuple types element-wise using `TryFrom` conversions.
3536
- [`NestedTupleTryInto<T, E>`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleTryInto.html): Provides a [`nested_tuple_try_into()`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleTryInto.html#tymethod.nested_tuple_try_into) convenience method to perform fallible conversions using `NestedTupleTryFrom`.
3637
- [`NestedTupleReplicate<T>`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleReplicate.html): Provides a [`nested_tuple_replicate(value)`](https://docs.rs/tuplities-flatten-nest/latest/tuplities_flatten_nest/trait.NestedTupleReplicate.html#tymethod.nested_tuple_replicate) method to create nested tuples by replicating a single value across all positions.
@@ -91,7 +92,7 @@ The following features enable individual trait crates:
9192
- `debug`: Enables `TupleDebug` trait
9293
- `tuple-default`: Enables `TupleDefault` trait
9394
- `eq`: Enables `TupleEq` trait
94-
- `flatten-nest`: Enables `FlattenNestedTuple`, `NestTuple`, `NestedTupleIndex`, `NestedTupleIndexMut`, `NestedTupleTryFrom`, `NestedTupleTryInto`, `NestTupleMatrix`, and `FlattenNestedTupleMatrix` traits
95+
- `flatten-nest`: Enables `FlattenNestedTuple`, `NestTuple`, `NestedTupleIndex`, `NestedTupleIndexMut`, `NestedTupleTryFrom`, `NestedTupleTryInto`, `NestTupleMatrix`, `FlattenNestedTupleMatrix`, `NestedTupleOption`, `IntoNestedTupleOption`, and `NestedTupleOptionWith` traits
9596
- `from`: Enables `TupleFrom` and `TupleInto` traits
9697
- `hash`: Enables `TupleHash` trait
9798
- `mut`: Enables `TupleMut` and `TupleMutMap` traits

tuplities-flatten-nest/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub use matrix::{
2020
};
2121
pub use nest::NestTuple;
2222
pub use nested_index::{NestedTupleIndex, NestedTupleIndexMut};
23-
pub use nested_option::{IntoNestedTupleOption, NestedTupleOption};
23+
pub use nested_option::{IntoNestedTupleOption, NestedTupleOption, NestedTupleOptionWith};
2424
pub use nested_push_pop::{
2525
NestedTuplePopBack, NestedTuplePopFront, NestedTuplePushBack, NestedTuplePushFront,
2626
};

tuplities-flatten-nest/src/nested_option.rs

Lines changed: 96 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -25,35 +25,38 @@ pub trait NestedTupleOption {
2525
/// The transposed type: an option of the nested tuple of the inner types.
2626
type Transposed: IntoNestedTupleOption<IntoOptions = Self>;
2727

28-
/// A nested homogeneous tuple type with the same shape as `Self` where each element is `H`.
29-
///
30-
/// Example: for `Self = (Option<T>, (Option<U>,))` then
31-
/// `Self::SameDepth<H>` == `(H, (H,))`.
32-
type SameDepth<H>;
33-
3428
/// Transposes the nested tuple of options into an option of the nested tuple.
3529
///
3630
/// Returns `Some(nested_tuple)` if all elements are `Some`, otherwise `None`.
3731
fn transpose(self) -> Option<Self::Transposed>;
3832

39-
/// Given a parallel homogeneous nested tuple `xs` (same shape as `self`),
40-
/// returns the first `H` that corresponds to the first `None` in `self`,
41-
/// or `None` if no elements are `None`.
42-
fn first_none_with<H>(self, xs: Self::SameDepth<H>) -> Option<H>;
33+
// Note: the `first_none_with`, `first_some_with`, and `transpose_or` helpers were moved
34+
// to the `NestedTupleOptionWith<H>` trait to keep `NestedTupleOption` focused on
35+
// transposition behavior.
36+
}
37+
38+
/// Helper trait for operating on nested `Option` structures with a parallel homogeneous
39+
/// nested tuple type `SameDepth` carrying elements of type `H`.
40+
pub trait NestedTupleOptionWith<H>: NestedTupleOption {
41+
/// The parallel homogeneous nested tuple type for `H` which has the same shape as `Self`.
42+
type SameDepth;
4343

44-
/// Given a parallel homogeneous nested tuple `xs` (same shape as `self`),
45-
/// returns the first `H` that corresponds to the first `Some` in `self`,
46-
/// or `None` if no elements are `Some`.
47-
fn first_some_with<H>(self, xs: Self::SameDepth<H>) -> Option<H>;
44+
/// Returns the first `H` corresponding to the first `None` in `self`.
45+
fn first_none_with(self, xs: Self::SameDepth) -> Option<H>;
46+
47+
/// Returns the first `H` corresponding to the first `Some` in `self`.
48+
fn first_some_with(self, xs: Self::SameDepth) -> Option<H>;
4849

4950
/// Like `transpose`, but returns a `Result` with `Ok(Transposed)` when all elements
5051
/// are `Some`, or `Err(H)` with the first `H` corresponding to the first `None`.
5152
///
5253
/// # Errors
5354
///
54-
/// Returns `Err(H)` if any element is `None`, where `H` is from the parallel
55-
/// homogeneous nested tuple `xs`.
56-
fn transpose_or<H>(self, xs: Self::SameDepth<H>) -> Result<Self::Transposed, H>;
55+
/// Returns `Err(h)` when any element in `self` is `None`. The `h` returned is the
56+
/// corresponding element of the parallel homogeneous nested tuple `xs` for the first
57+
/// `None` encountered (traversed left-to-right, depth-first in the nested pair
58+
/// representation).
59+
fn transpose_or(self, xs: Self::SameDepth) -> Result<Self::Transposed, H>;
5760
}
5861

5962
/// A trait for converting nested tuples into nested tuples of options.
@@ -81,41 +84,95 @@ pub trait IntoNestedTupleOption {
8184

8285
impl NestedTupleOption for () {
8386
type Transposed = ();
84-
type SameDepth<H> = ();
8587

8688
#[inline]
8789
fn transpose(self) -> Option<Self::Transposed> {
8890
Some(())
8991
}
92+
}
93+
94+
impl<T> NestedTupleOption for (Option<T>,) {
95+
type Transposed = (T,);
9096

9197
#[inline]
92-
fn first_none_with<H>(self, _xs: Self::SameDepth<H>) -> Option<H> {
93-
None
98+
fn transpose(self) -> Option<Self::Transposed> {
99+
let (opt,) = self;
100+
opt.map(|t| (t,))
94101
}
102+
}
103+
104+
impl<Head, Tail> NestedTupleOption for (Option<Head>, Tail)
105+
where
106+
Tail: NestedTupleOption,
107+
{
108+
type Transposed = (Head, Tail::Transposed);
95109

96110
#[inline]
97-
fn first_some_with<H>(self, _xs: Self::SameDepth<H>) -> Option<H> {
98-
None
111+
fn transpose(self) -> Option<Self::Transposed> {
112+
let (head_opt, tail) = self;
113+
match (head_opt, tail.transpose()) {
114+
(Some(head), Some(tail_transposed)) => Some((head, tail_transposed)),
115+
_ => None,
116+
}
99117
}
118+
}
119+
120+
// Implementations for IntoNestedTupleOption
121+
122+
impl IntoNestedTupleOption for () {
123+
type IntoOptions = ();
100124

101125
#[inline]
102-
fn transpose_or<H>(self, _xs: Self::SameDepth<H>) -> Result<Self::Transposed, H> {
103-
Ok(())
126+
fn into_options(self) -> Self::IntoOptions {}
127+
}
128+
129+
impl<T> IntoNestedTupleOption for (T,) {
130+
type IntoOptions = (Option<T>,);
131+
132+
#[inline]
133+
fn into_options(self) -> Self::IntoOptions {
134+
let (t,) = self;
135+
(Some(t),)
104136
}
105137
}
106138

107-
impl<T> NestedTupleOption for (Option<T>,) {
108-
type Transposed = (T,);
109-
type SameDepth<H> = (H,);
139+
impl<Head, Tail> IntoNestedTupleOption for (Head, Tail)
140+
where
141+
Tail: IntoNestedTupleOption,
142+
{
143+
type IntoOptions = (Option<Head>, Tail::IntoOptions);
110144

111145
#[inline]
112-
fn transpose(self) -> Option<Self::Transposed> {
113-
let (opt,) = self;
114-
opt.map(|t| (t,))
146+
fn into_options(self) -> Self::IntoOptions {
147+
let (head, tail) = self;
148+
(Some(head), tail.into_options())
115149
}
150+
}
151+
152+
impl<H> NestedTupleOptionWith<H> for () {
153+
type SameDepth = ();
116154

117155
#[inline]
118-
fn first_none_with<H>(self, xs: Self::SameDepth<H>) -> Option<H> {
156+
fn first_none_with(self, _xs: Self::SameDepth) -> Option<H> {
157+
None
158+
}
159+
160+
#[inline]
161+
fn first_some_with(self, _xs: Self::SameDepth) -> Option<H> {
162+
None
163+
}
164+
165+
#[inline]
166+
fn transpose_or(self, _xs: Self::SameDepth) -> Result<Self::Transposed, H> {
167+
Ok(())
168+
}
169+
}
170+
171+
impl<T, H> NestedTupleOptionWith<H> for (Option<T>,) {
172+
type SameDepth = (H,);
173+
174+
#[inline]
175+
fn first_none_with(self, xs: Self::SameDepth) -> Option<H> {
119176
let (opt,) = self;
120177
let (h,) = xs;
121178
match opt {
@@ -125,14 +182,14 @@ impl<T> NestedTupleOption for (Option<T>,) {
125182
}
126183

127184
#[inline]
128-
fn first_some_with<H>(self, xs: Self::SameDepth<H>) -> Option<H> {
185+
fn first_some_with(self, xs: Self::SameDepth) -> Option<H> {
129186
let (opt,) = self;
130187
let (h,) = xs;
131188
opt.map(|_| h)
132189
}
133190

134191
#[inline]
135-
fn transpose_or<H>(self, xs: Self::SameDepth<H>) -> Result<Self::Transposed, H> {
192+
fn transpose_or(self, xs: Self::SameDepth) -> Result<Self::Transposed, H> {
136193
let (opt,) = self;
137194
let (h,) = xs;
138195
match opt {
@@ -142,24 +199,14 @@ impl<T> NestedTupleOption for (Option<T>,) {
142199
}
143200
}
144201

145-
impl<Head, Tail> NestedTupleOption for (Option<Head>, Tail)
202+
impl<Head, Tail, H> NestedTupleOptionWith<H> for (Option<Head>, Tail)
146203
where
147-
Tail: NestedTupleOption,
204+
Tail: NestedTupleOptionWith<H>,
148205
{
149-
type Transposed = (Head, Tail::Transposed);
150-
type SameDepth<H> = (H, Tail::SameDepth<H>);
151-
152-
#[inline]
153-
fn transpose(self) -> Option<Self::Transposed> {
154-
let (head_opt, tail) = self;
155-
match (head_opt, tail.transpose()) {
156-
(Some(head), Some(tail_transposed)) => Some((head, tail_transposed)),
157-
_ => None,
158-
}
159-
}
206+
type SameDepth = (H, Tail::SameDepth);
160207

161208
#[inline]
162-
fn first_none_with<H>(self, xs: Self::SameDepth<H>) -> Option<H> {
209+
fn first_none_with(self, xs: Self::SameDepth) -> Option<H> {
163210
let (head_opt, tail) = self;
164211
let (h_head, h_tail) = xs;
165212
match head_opt {
@@ -169,7 +216,7 @@ where
169216
}
170217

171218
#[inline]
172-
fn first_some_with<H>(self, xs: Self::SameDepth<H>) -> Option<H> {
219+
fn first_some_with(self, xs: Self::SameDepth) -> Option<H> {
173220
let (head_opt, tail) = self;
174221
let (h_head, h_tail) = xs;
175222
match head_opt {
@@ -179,7 +226,7 @@ where
179226
}
180227

181228
#[inline]
182-
fn transpose_or<H>(self, xs: Self::SameDepth<H>) -> Result<Self::Transposed, H> {
229+
fn transpose_or(self, xs: Self::SameDepth) -> Result<Self::Transposed, H> {
183230
let (head_opt, tail) = self;
184231
let (h_head, h_tail) = xs;
185232
match head_opt {
@@ -192,38 +239,6 @@ where
192239
}
193240
}
194241

195-
// Implementations for IntoNestedTupleOption
196-
197-
impl IntoNestedTupleOption for () {
198-
type IntoOptions = ();
199-
200-
#[inline]
201-
fn into_options(self) -> Self::IntoOptions {}
202-
}
203-
204-
impl<T> IntoNestedTupleOption for (T,) {
205-
type IntoOptions = (Option<T>,);
206-
207-
#[inline]
208-
fn into_options(self) -> Self::IntoOptions {
209-
let (t,) = self;
210-
(Some(t),)
211-
}
212-
}
213-
214-
impl<Head, Tail> IntoNestedTupleOption for (Head, Tail)
215-
where
216-
Tail: IntoNestedTupleOption,
217-
{
218-
type IntoOptions = (Option<Head>, Tail::IntoOptions);
219-
220-
#[inline]
221-
fn into_options(self) -> Self::IntoOptions {
222-
let (head, tail) = self;
223-
(Some(head), tail.into_options())
224-
}
225-
}
226-
227242
#[cfg(test)]
228243
mod tests {
229244
use super::*;

tuplities/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ pub mod prelude {
1717
pub use tuplities_flatten_nest::{
1818
FlattenMatrixElements, FlattenNestedTuple, FlattenNestedTupleMatrix, IntoNestedTupleOption,
1919
NestMatrixElements, NestTuple, NestTupleMatrix, NestedTupleIndex, NestedTupleIndexMut,
20-
NestedTupleMut, NestedTupleOption, NestedTuplePopBack, NestedTuplePopFront,
21-
NestedTuplePushBack, NestedTuplePushFront, NestedTupleRef, NestedTupleReplicate,
22-
NestedTupleRow, NestedTupleRowMut, NestedTupleTryFrom, NestedTupleTryInto,
20+
NestedTupleMut, NestedTupleOption, NestedTupleOptionWith, NestedTuplePopBack,
21+
NestedTuplePopFront, NestedTuplePushBack, NestedTuplePushFront, NestedTupleRef,
22+
NestedTupleReplicate, NestedTupleRow, NestedTupleRowMut, NestedTupleTryFrom,
23+
NestedTupleTryInto,
2324
};
2425
#[cfg(feature = "from")]
2526
pub use tuplities_from::{TupleFrom, TupleInto};

0 commit comments

Comments
 (0)