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}