1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//! References bundled with referee's owner, ordered by pointer address or data content.
//!
//! This crate provides the smart pointer type that bundles the data with its owner.
//! It has the folloing features:
//!
//! - The data is either a reference to a portion of the owner, or a data type that may
//! contain references to the owner.
//! - The refernce can be ordered by data content or data pointer address.
//! - The owner is contained in [Box] or [Arc](std::sync::Arc).
//!
//! The following table shows [Box]-based reference types. The generic `O` denotes the
//! owner type and `I` denotes the data type.
//!
//! | data type (`I`) \\ ordering | Content ordered | Pointer address ordered |
//! |---------------------------- | ---------------------------- | ---------------------------- |
//! | Reference | [BoxRefC<O, I>](BoxRefC) | [BoxRefA<O, I>](BoxRefA) |
//! | Owned | [BoxOwnedC<O, I>](BoxOwnedC) | [BoxOwnedA<O, I>](BoxOwnedA) |
//!
//! The following table shows [Arc](std::sync::Arc)-based reference types.
//!
//! | data type (`I`) \\ ordering | Content ordered | Pointer address ordered |
//! |---------------------------- | ---------------------------- | ---------------------------- |
//! | Reference | [ArcRefC<O, I>](ArcRefC) | [ArcRefA<O, I>](ArcRefA) |
//! | Owned | [ArcOwnedC<O, I>](ArcOwnedC) | [ArcOwnedA<O, I>](ArcOwnedA) |
//!
//! For example,
//! - `BoxRefA<Vec<str>, str>` is a reference to `str` within the owner `Vec<str>`, which is ordered by pointer address.
//! - `ArcOwnedC<Vec<str>, Option<&str>>` stores the data type `Option<&str>`, which contains a reference within the owner `Vec<str>`.
//! The reference is ordered by the data content.
//!
//! # Construction and destruction
//!
//! The smart references are built in the following ways.
//!
//! ```
//! # use std::sync::Arc;
//! use ownref::{ArcRefA, ArcRefC, BoxRefA, BoxRefC};
//!
//! struct Owner {
//! a: u8,
//! b: f32,
//! }
//!
//! // direct method
//! let _: BoxRefA<Owner, Owner> = BoxRefA::new(Owner { a: 7, b: 3.14 });
//! let _: ArcRefA<Owner, Owner> = ArcRefA::new(Owner { a: 7, b: 3.14 });
//!
//! // from boxed data
//! let boxed = Box::new(Owner { a: 7, b: 3.14 });
//! let _: BoxRefC<Owner, Owner> = BoxRefC::from(boxed);
//!
//! let boxed = Arc::new(Owner { a: 7, b: 3.14 });
//! let _: ArcRefC<Owner, Owner> = ArcRefC::from(boxed);
//! ```
//!
//! `BoxRef` is destructed by [BoxRef::into_owner()].
//!
//! ```
//! # use ownref::BoxRefA;
//! let owner = ['a', 'b'];
//! let boxref = BoxRefA::new(owner); // box the owner
//! let owner = BoxRefA::into_owner(boxref); // recover the owner
//! ```
//!
//! `ArcRef` is destructed by [ArcRef::unwrap_owner()]. It panics of the strong count is more than one.
//!
//! ```
//! # use ownref::ArcRefA;
//! let owner = ['a', 'b'];
//! let arcref = ArcRefA::new(owner); // box the owner
//! let owner = ArcRefA::unwrap_owner(arcref); // recover the owner
//! ```
//!
//! # Data type transformation
//!
//! The family of methods `map()`, `filter_map()` and `try_map()` can transform the data type.
//!
//! ```
//! # use ownref::{BoxRefA, BoxOwnedA};
//! struct Owner {
//! a: u8,
//! b: f32,
//! }
//!
//! let owner: BoxRefA<Owner, Owner> = BoxRefA::new(Owner { a: 7, b: 3.14 });
//! let inner: BoxRefA<Owner, f32> = owner.map(|data: &mut Owner| &mut data.b);
//!
//! // above is equivalent to
//! let owner: BoxOwnedA<Owner, &mut Owner> = BoxOwnedA::new(Owner { a: 7, b: 3.14 });
//! let inner: BoxOwnedA<Owner, &mut f32> = owner.map(|data: &mut Owner| &mut data.b);
//! ```
//!
//! Note that for `Owned` types. It is possible to transform the data such that the outcome
//! data does not reference to the owner.
//!
//! ```
//! # use ownref::{BoxOwnedA};
//! # struct Owner {
//! # a: u8,
//! # b: f32,
//! # }
//! let owner: BoxOwnedA<Owner, &mut Owner> = BoxOwnedA::new(Owner { a: 7, b: 3.14 });
//! let inner: BoxOwnedA<Owner, i32> = owner.map(|_| 5i32);
//! ```
//!
//! # Ordering
//!
//! [ArcRefA] is ordered by pointer address. The code below creates two references
//! pointing to distinct elements of an array, which element values are identical.
//! The references are distinguished by their pointer address.
//!
//! ```
//! # use ownref::ArcRefA;
//! let own1 = ArcRefA::new(['a', 'a']);
//! let own2 = own1.clone();
//!
//! let ref1: ArcRefA<[char; 2], char> = own1.map(|array| &array[0]);
//! let ref2: ArcRefA<[char; 2], char> = own2.map(|array| &array[1]);
//! assert!(ref1 != ref2); // differ by pointer address
//! ```
//!
//! [ArcRefC] is ordered by data content. The code below shows two references
//! pointing to distinct elements of an array, and are equalized by identical element value.
//!
//! ```
//! # use ownref::ArcRefC;
//! let own1 = ArcRefC::new(['a', 'a']);
//! let own2 = own1.clone();
//!
//! let ref1: ArcRefC<[char; 2], char> = own1.map(|array| &array[0]);
//! let ref2: ArcRefC<[char; 2], char> = own2.map(|array| &array[1]);
//! assert!(ref1 == ref2); // equalized by content
//! ```
//!
//! # Iterator flattening
//!
//! [ArcRef] is able to flatten the referenced data if the data type can be turned into an iterator.
//! For example, it can turn a reference to a vec into a vec of element references.
//!
//! ```
//! # use ownref::ArcRefC;
//! let vec: ArcRefC<Vec<char>> = ArcRefC::new(vec!['a', 'b', 'c']);
//! let collected: Vec<ArcRefC<Vec<char>, char>> = vec.flatten().collect();
//! ```
//!
//! [ArcOwned] is more versatile. It can flatten a map to references to its keys, values
//! or key-value pairs.
//!
//! ```
//! # use ownref::ArcOwnedC;
//! # use indexmap::IndexMap;
//! let map: IndexMap<_, _> = [('a', 1), ('b', 2), ('c', 3)].into_iter().collect();
//! let own: ArcOwnedC<_> = ArcOwnedC::new(map);
//!
//! let pairs: Vec<ArcOwnedC<_, (&char, &usize)>> =
//! own.clone().flat_map(|map| map.iter()).collect();
//! let keys: Vec<ArcOwnedC<_, &char>> = own.clone().flat_map(|map| map.keys()).collect();
//! let values: Vec<ArcOwnedC<_, &usize>> = own.flat_map(|map| map.values()).collect();
//! ```
//!
//!
//! # Owner erasure
//!
//! The owner type can forget the owner type and keeps the data reference.
//!
//! ```
//! # use ownref::{BoxRefC, BoxRefAnyC};
//! let letter: BoxRefC<[char; 2], char> = BoxRefC::new(['a', 'b']).map(|array| &mut array[0]);
//!
//! // erase the owner
//! let letter: BoxRefAnyC<char> = BoxRefC::into_any_owner(letter);
//!
//! // recover the owner
//! let letter: BoxRefC<[char; 2], char> = match BoxRefC::downcast_owner(letter) {
//! Ok(new_owner) => new_owner,
//! Err(_old_owner) => unreachable!(),
//! };
//! ```
//!
//! This example creates two `u64` references within distinct owner types.
//! The owner type of references are erased so that they can be placed into a `Vec`.
//!
//! ```
//! # use ownref::{BoxRefAnyC, BoxRefC};
//! struct OwnerX {
//! a: u8,
//! b: u64,
//! }
//!
//! struct OwnerY {
//! c: f32,
//! d: u64,
//! }
//!
//! let own1 = BoxRefC::new(OwnerX { a: 7, b: 314 });
//! let ref1 = own1.map(|data| &mut data.b);
//!
//! let own2 = BoxRefC::new(OwnerY { c: 0.66, d: 52 });
//! let ref2 = own2.map(|data| &mut data.d);
//!
//! // ref1 and ref2 have different owners, erase ownwer types
//! let ref1: BoxRefAnyC<u64> = BoxRefC::into_any_owner(ref1);
//! let ref2: BoxRefAnyC<u64> = BoxRefC::into_any_owner(ref2);
//!
//! // so they can be stored in a vec
//! vec![ref1, ref2];
//! ```
pub use *;
pub use *;
pub use *;
pub use *;