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
//! # Multireferences (aka _the inverse distributive law_)
//!
//! Ever wanted to get `&[T]` from `[&T]` without cloning anything?
//!
//! Semantically, it doesn't make sense (because a slice wraps a block of 
//! _contiguous_ elements). But sometimes it's very convenient to be 
//! able to “algebraically” extract a common lifetime 
//! from a bunch of references.
//!
//! This crate provides two helper types 
//! [`Slice`](struct.Slice.html) and [`Pair`](struct.Pair.html) 
//! that allow the following conversions:
//!
//! * [`&'a [&'x T] -> &'a Slice<T>`](struct.Slice.html#method.new) (and a mutable equivalent)
//! * [`&'a (&'x A, &'x B) -> &'a Pair<A, B>`](struct.Pair.html#method.new) (and a mutable equivalent)
//!
//! Moreover, each of these types provides `.as_ref()` and `.as_mut()` 
//! methods (with signatures different from the ones used by the `AsRef` and 
//! `AsMut` traits) implementing the forward distributive law:
//!
//! * [`&'a Slice<T> -> &'a [&'a T]`](struct.Slice.html#method.as_ref) (and a mutable equivalent)
//! * [`&'a Pair<A, B> -> &'a (&'a A, &'a B)`](struct.Pair.html#method.as_ref) (and a mutable equivalent)
//!
// //! Also there is a macro `declare_named_tuple!` that introduces 
// //! a user-defined helper type which allows to name 
// //! the individual wrapped references.
//!
//! ## Motivation
//!
//! _The following text is somewhat long. Unfortunately, I do not 
//! know any realistic uses of the inverse distributive law in situations 
//! not involving a formal argument in a contra-contravariant position._
//!
//! ### Preliminaries
//!
//! Suppose you have the following trait:
//!
//! ```
//! trait Info {
//!     type RelevantPart: ?Sized;
//!
//!     fn info<E, Info>(&self, extractor: E) -> Info where
//!         E: FnOnce(&Self::RelevantPart) -> Info;
//! }
//! ```
//!
//! I.e. a type implementing `Info` can temporarily give access to 
//! some its part. For example:
//!
//! ```
//! # trait Info { type RelevantPart: ?Sized; 
//! #     fn info<E, Info>(&self, extractor: E) -> Info where
//! #     E: FnOnce(&Self::RelevantPart) -> Info; }
//! # use std::collections::HashMap;
//! struct Configuration {
//!     fields: HashMap<String, String>,
//! }
//!
//! impl Info for Configuration {
//!     type RelevantPart = str;
//!     
//!     fn info<E, Info>(&self, extractor: E) -> Info where
//!         E: FnOnce(&str) -> Info 
//!     {
//!         match self.fields.get("name") {
//!             Some(name) => extractor(name),
//!             None       => extractor("UNKNOWN"),
//!         }
//!     }
//! }
//! ```
//! 
//! If you are interested whether the continuation-passing style is necessary, 
//! try to write a non-cps equivalent
//!
//! ```
//! # struct Foo; impl Foo {
//! fn info<'a>(&'a self) -> &'a str 
//! # { todo!() } }
//! ```
//!
//! for some dynamically generated string (e.g. the current timestamp) instead 
//! of static `"UNKNOWN"`.
//!
//! The only safe way to get the `&'a str` from such a string seems to be 
//! to embed this string directly in the `Configuration`. But it can't be done 
//! through a shared reference (and if it could, it would be a rather 
//! strange-looking solution, because this string has nothing to do with 
//! the configuration).
//!
//! ### The problem
//!
//! Now suppose that you want to give two fields to the extractor. 
//! What the `RelevantPart` would be?
//!
//! The laziest solution is to define
//! 
//! ```
//! type RelevantPart = (String, String);
//! ```
//!
//! But such a type requires cloning the strings. It would be better to have
//!
//! ``` 
//! # trait Foo { type RelevantPart; } impl<'a> Foo for &'a () {
//! type RelevantPart = (&'a str, &'a str);
//! # }
//! ```
//!
//! but our trait doesn't have the `'a` parameter. And if it had it 
//! would not work either. E.g. a `&str` borrowed from a dynamically 
//! generated analogue of `"UNKNOWN"` must have its lifetime fully 
//! contained in the `info` method. But the `'a` lifetime is external
//! to this method.
//!
//! ### A solution
//!
//! ```
//! # trait Info { type RelevantPart: ?Sized; 
//! #     fn info<E, Info>(&self, extractor: E) -> Info where
//! #     E: FnOnce(&Self::RelevantPart) -> Info; }
//! # use std::collections::HashMap;
//! # struct Configuration { fields: HashMap<String, String> }
//! fn make_error_string() -> String { unimplemented!() }
//!
//! use multiref::Pair; // a wrapper around (&'a A, &'a B)
//!
//! impl Info for Configuration {
//!     type RelevantPart = Pair<str, str>; // now this type supports any lifetime
//!     
//!     fn info<E, Info>(&self, extractor: E) -> Info where
//!         E: FnOnce(&Pair<str,str>) -> Info 
//!     {
//!         let error_string = make_error_string();
//!         // for simplicity we generate an error string unconditionally
//!
//!         let foo: &str = match self.fields.get("foo") {
//!             Some(foo) => &foo,
//!             None      => &error_string,
//!         };
//!
//!         let bar: &str = match self.fields.get("bar") {
//!             Some(bar) => &bar,
//!             None      => &error_string,
//!         };
//!
//!         extractor( (&(foo, bar)).into() )
//!         // Pair::new(&(foo, bar)) also can be used
//!     }
//! }
//! ```
//!
//!
//! ## Warning
//!
//! This crate uses some `unsafe` code with questionable soundness. It seems 
//! that this code is sound if DST are sound, but it may not be the case.


#![no_std]

mod slice;
mod pair;
mod named_tuple;

pub use pair::Pair;
pub use slice::Slice;