structinator_traits/lib.rs
1/*
2Copyright 2023 Benjamin Richcreek
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16//!# Struct-inator Traits
17//!This is a library for implementing a trait, [`SpecifyCreatableStruct`] - which, when implemented, alliows for quick and easy conversion between rust [`Iterators`](Iterator) and
18//! types that implement [`SpecifyCreatableStruct`].
19//!
20//! More specifically, any type implementing [`SpecifyCreatableStruct`] must implement [`create_struct`](SpecifyCreatableStruct::create_struct), a function converting directly from an [`Iterator`] over items of type [`NamedField<I>`], where
21//! `I` is the same type as [`InnerIteratorType`](SpecifyCreatableStruct)
22//!
23//! You can implement this trait yourself, or you can automatically implement it for a user-defined struct using [`structinator`](https://crates.io/crates/structinator)
24//!
25//! [structinator]: https://example.com
26//!
27//! # Example
28//!```rust
29//!use structinator_traits::*;
30//!use structinator::iter_convertable;
31//!use enum_unwrapper::unique_try_froms;
32//!#[unique_try_froms()]
33//!enum WaffleInfo {
34//! Topping(u8),
35//! Layers(u16),
36//!}
37//!#[iter_convertable(WaffleInfo)]
38//!struct Waffles {
39//! syrup_amount: u8,
40//! butter_amount: u8,
41//! layer_count: u16,
42//!}
43//!fn main() {
44//! let mut iterator = [NamedField::<WaffleInfo> {
45//! name: String::from("butter_amount"),
46//! wrapped_value: WaffleInfo::Topping(44),
47//! }, NamedField::<WaffleInfo> {
48//! name: String::from("layer_count"),
49//! wrapped_value: WaffleInfo::Layers(444),
50//! }, NamedField::<WaffleInfo> {
51//! name: String::from("syrup_amount"),
52//! wrapped_value: WaffleInfo::Topping(4),
53//! }].into_iter();
54//! let generated_struct = Waffles::create_struct(&mut iterator).unwrap();
55//! assert_eq!(4,generated_struct.syrup_amount);
56//! assert_eq!(44,generated_struct.butter_amount);
57//! assert_eq!(444,generated_struct.layer_count);
58//!}
59//!```
60/// [`SpecifyCreatableStruct`]'s original intended use case was with user-defined [`struct`](https://doc.rust-lang.org/1.58.1/std/keyword.struct.html)s, and this structure was designed for convenience, allowing the implementor to store both a [`String`]ification of the field's name,
61/// and the field's value. Note that it is also the type that the argument passed to [`create_struct`](SpecifyCreatableStruct::create_struct) must iterate over.
62#[derive(Clone,Debug)]
63pub struct NamedField<I> {
64 ///Intended to hold the name of the field `wrapped_value` should be assigned to
65 pub name: String,
66 ///Intended to hold the value to be assigned to a given field in the target [`struct`](https://doc.rust-lang.org/1.58.1/std/keyword.struct.html)
67 pub wrapped_value: I,
68}
69///Any type implementing this trait must be convertable from an [`Iterator`] over elements of type [`NamedField<I>`], where `I` is the same type assigned to [`InnerIteratorType`](SpecifyCreatableStruct::InnerIteratorType).
70pub trait SpecifyCreatableStruct: Sized {
71 ///The type contained in [`NamedField`]
72 type InnerIteratorType;
73 ///The type that should be returned if the conversion fails
74 type Error;
75 /// The function that should be called to attempt a conversion from an [`Iterator`] to the type implementing this trait.
76 fn create_struct(seed_iterator: &mut dyn Iterator<Item = NamedField<Self::InnerIteratorType>>) -> Result<Self,Self::Error>;
77}