Skip to main content

refview/
lib.rs

1/* Copyright (C) 2022 Dylan Staatz - All Rights Reserved. */
2
3//! Motivation: easily generate a "Viewer" struct that has some fields that
4//! reference another struct.
5//! 
6//! Example input:
7//! ```rust
8//! #[derive(RefView)]
9//! struct DataStruct {
10//!     field0: f64,
11//!     field1: u64,
12//!     field2: isize,
13//!     field3: Vec<Box<usize>>,
14//! }
15//! ```
16//! 
17//! This would (roughly) generate the following code:
18//! ```rust
19//! pub struct DataStructViewer<'a> {
20//!     pub field0: &'a f64,
21//!     pub field1: &'a u64,
22//!     pub field2: &'a isize,
23//!     pub field3: &'a Vec<Box<usize>>,
24//! }
25//! 
26//! impl<'a> RefView<'a> for DataStruct {
27//!     type Viewer = DataStructViewer<'a>;
28//!     fn view(&'a self) -> Self::Viewer
29//!     where
30//!         Self::Viewer: 'a,
31//!     {
32//!         Self::Viewer {
33//!             field0: &self.field0,
34//!             field1: &self.field1,
35//!             field2: &self.field2,
36//!             field3: &self.field3,
37//!         }
38//!     }
39//! }
40//! ```
41//! 
42//! Mutable referenced structs can be generated with [`RefViewMut`].
43//! 
44//! ## Planned features
45//! 
46//! - Make some fields skip-able or include them though field attributes
47//! - More control over visability of generated struct
48
49pub use refview_derive::*;
50
51/// Trait to "view" into a struct
52/// 
53/// See [module-level documentation]
54/// 
55/// [module-level documentation]: crate
56pub trait RefView<'a> {
57    type Viewer;
58
59    fn view(&'a self) -> Self::Viewer
60    where
61        Self::Viewer: 'a;
62}
63
64/// Trait to mutably "view" into a struct
65/// 
66/// See [module-level documentation]
67/// 
68/// [module-level documentation]: crate
69pub trait RefViewMut<'a>: RefView<'a> {
70    type ViewerMut;
71
72    fn view_mut(&'a mut self) -> Self::ViewerMut
73    where
74        Self::ViewerMut: 'a;
75}
76
77#[cfg(test)]
78mod tests {
79
80    use super::*;
81
82    struct Data {
83        field0: f64,
84        field1: u64,
85        field2: isize,
86        field3: Vec<Box<usize>>,
87    }
88
89    struct DataViewer<'a> {
90        field0: &'a f64,
91        field1: &'a u64,
92        field2: &'a isize,
93        field3: &'a Vec<Box<usize>>,
94    }
95
96    impl<'a> RefView<'a> for Data {
97        type Viewer = DataViewer<'a>;
98
99        fn view(&'a self) -> Self::Viewer
100        where
101            Self::Viewer: 'a,
102        {
103            DataViewer {
104                field0: &self.field0,
105                field1: &self.field1,
106                field2: &self.field2,
107                field3: &self.field3,
108            }
109        }
110    }
111
112    struct DataViewerMut<'a> {
113        field1: &'a mut u64,
114        field2: &'a mut isize,
115    }
116
117    impl<'a> RefViewMut<'a> for Data {
118        type ViewerMut = DataViewerMut<'a>;
119
120        fn view_mut(&'a mut self) -> Self::ViewerMut
121        where
122            Self::ViewerMut: 'a,
123        {
124            DataViewerMut {
125                field1: &mut self.field1,
126                field2: &mut self.field2,
127            }
128        }
129    }
130
131    #[test]
132    fn test_view() {
133        let data = Data {
134            field0: 1.0,
135            field1: 2,
136            field2: -5,
137            field3: vec![],
138        };
139
140        let view = data.view();
141
142        assert_eq!(view.field0, &data.field0);
143        assert_eq!(view.field1, &data.field1);
144        assert_eq!(view.field2, &data.field2);
145        assert_eq!(view.field3, &data.field3);
146    }
147
148    #[test]
149    fn test_view_mut() {
150        let mut data = Data {
151            field0: 1.0,
152            field1: 2,
153            field2: -5,
154            field3: vec![],
155        };
156
157        // Modify data with mutable reference
158        let view = data.view_mut();
159        *view.field1 = 5;
160        *view.field2 = 5;
161
162        let view = data.view();
163
164        assert_eq!(*view.field0, data.field0);
165        assert_eq!(*view.field1, data.field1);
166        assert_eq!(*view.field2, data.field2);
167        assert_eq!(view.field3, &data.field3);
168    }
169}