maybe_owned/
lib.rs

1//! This crate only provides the `MaybeOwned` and `MaybeOwnedMut` enums
2//!
3//! Take a look at their documentation for more information.
4//!
5#![warn(missing_docs)]
6#[cfg(feature = "serde")]
7extern crate serde;
8
9#[cfg(feature = "serde")]
10mod serde_impls;
11
12mod transitive_impl;
13
14use std::borrow::{Borrow, BorrowMut, Cow};
15use std::cmp::Ordering;
16use std::fmt;
17use std::hash::{Hash, Hasher};
18use std::ops::{Deref, DerefMut};
19use std::str::FromStr;
20
21/// This type provides a way to store data to which you either have a
22/// reference to or which you do own.
23///
24/// It provides `From<T>`, `From<&'a T>` implementations and, in difference
25/// to `Cow` does _not_ require `ToOwned` to be implemented which makes it
26/// compatible with non cloneable data, as a draw back of this it does not
27/// know about `ToOwned`. As a consequence of it can't know that `&str` should
28/// be the borrowed version of `String` and not `&String` this is especially
29/// bad wrt. `Box` as the borrowed version of `Box<T>` would be `&Box<T>`.
30///
31/// While this crate has some drawbacks compared to `Cow` is has the benefit,
32/// that it works with Types which neither implement `Clone` nor `ToOwned`.
33/// Another benefit lies in the ability to write API functions which accept
34/// a generic parameter `E: Into<MaybeOwned<'a, T>>` as the API consumer can
35/// pass `T`, `&'a T` and `MaybeOwned<'a, T>` as argument, without requiring
36/// a explicit `Cow::Owned` or a split into two functions one accepting
37/// owed and the other borrowed values.
38///
39/// # Alternatives
40///
41/// If you mainly have values implementing `ToOwned` like `&str`/`String`, `Path`/`PathBuf` or
42/// `&[T]`/`Vec<T>` using `std::borrow::Cow` might be preferable.
43///
44/// If you want to be able to treat `&T`, `&mut T`, `Box<T>` and `Arc<T>` the same
45/// consider using [`reffers::rbma::RBMA`](https://docs.rs/reffers)
46/// (through not all types/platforms are supported because
47/// as it relies on the fact that for many pointers the lowest two bits are 0, and stores
48/// the discriminant in them, nevertheless this is can only be used with 32bit-aligned data,
49/// e.g. using a &u8 _might_ fail). RBMA also allows you to recover a `&mut T` if it was created
50/// from `Box<T>`, `&mut T` or a unique `Arc`.
51///
52///
53/// # Examples
54///
55/// ```
56/// # use maybe_owned::MaybeOwned;
57/// struct PseudoBigData(u8);
58/// fn pseudo_register_fn<'a, E>(_val: E) where E: Into<MaybeOwned<'a, PseudoBigData>> { }
59///
60/// let data = PseudoBigData(12);
61/// let data2 = PseudoBigData(13);
62///
63/// pseudo_register_fn(&data);
64/// pseudo_register_fn(&data);
65/// pseudo_register_fn(data2);
66/// pseudo_register_fn(MaybeOwned::Owned(PseudoBigData(111)));
67/// ```
68///
69/// ```
70/// # use maybe_owned::MaybeOwned;
71/// #[repr(C)]
72/// struct OpaqueFFI {
73///     ref1:  * const u8
74///     //we also might want to have PhantomData etc.
75/// }
76///
77/// // does not work as it does not implement `ToOwned`
78/// // let _ = Cow::Owned(OpaqueFFI { ref1: 0 as *const u8});
79///
80/// // ok, MaybeOwned can do this (but can't do &str<->String as tread of)
81/// let _ = MaybeOwned::Owned(OpaqueFFI { ref1: 0 as *const u8 });
82/// ```
83///
84/// ```
85/// # #[macro_use]
86/// # extern crate serde_derive;
87/// # extern crate serde_json;
88/// # extern crate maybe_owned;
89/// # #[cfg(feature = "serde")]
90/// # fn main() {
91/// # use maybe_owned::MaybeOwned;
92/// use std::collections::HashMap;
93///
94/// #[derive(Serialize, Deserialize)]
95/// struct SerializedData<'a> {
96///     data: MaybeOwned<'a, HashMap<String, i32>>,
97/// }
98///
99/// let mut map = HashMap::new();
100/// map.insert("answer".to_owned(), 42);
101///
102/// // serializing can use borrowed data to avoid unnecessary copying
103/// let bytes = serde_json::to_vec(&SerializedData { data: (&map).into() }).unwrap();
104///
105/// // deserializing creates owned data
106/// let deserialized: SerializedData = serde_json::from_slice(&bytes).unwrap();
107/// assert_eq!(deserialized.data["answer"], 42);
108/// # }
109/// # #[cfg(not(feature = "serde"))] fn main() {}
110/// ```
111///
112/// # Transitive `std::ops` implementations
113///
114/// There are transitive implementations for most operator in `std::ops`.
115///
116/// A Op between a `MaybeOwned<L>` and `MaybeOwned<R>` is implemented if:
117///
118/// - L impl the Op with R
119/// - L impl the Op with &R
120/// - &L impl the Op with R
121/// - &L impl the Op with &R
122/// - the `Output` of all aboves implementations is
123///   the same type
124///
125///
126/// The `Neg` (`-` prefix) op is implemented for `V` if:
127///
128/// - `V` impl `Neg`
129/// - `&V` impl `Neg`
130/// - both have the same `Output`
131///
132///
133/// The `Not` (`!` prefix) op is implemented for `V` if:
134///
135/// - `V` impl `Not`
136/// - `&V` impl `Not`
137/// - both have the same `Output`
138///
139/// Adding implementations for Ops which add a `MaybeOwned` to
140/// a non `MaybeOwned` value (like `MaybeOwned<T> + T`) requires
141/// far reaching specialization in rust and is therefore not done
142/// for now.
143#[derive(Debug)]
144pub enum MaybeOwned<'a, T: 'a> {
145    /// owns T
146    Owned(T),
147    /// has a reference to T
148    Borrowed(&'a T),
149}
150
151/// This type is basically the same as `MaybeOwned`,
152/// but works with mutable references.
153///
154/// Note that while you can se `MaybeOwned` as a alternative
155/// implementation for a Cow (Copy-On-Write) type this isn't
156/// really the case for `MaybeOwnedMut` as changing it will
157/// potentially change the source through the given `&mut`
158/// reference. For example the transitive add assign (+=)
159/// implementation for `MaybeOwned` does (need to) convert
160/// the given instance into a owned variant before using
161/// `+=` on the contained type. But for `MaybeOwnedMut` it
162/// can directly use `+=` on the `&mut` contained in the
163/// `Borrowed` variant!
164#[derive(Debug)]
165pub enum MaybeOwnedMut<'a, T: 'a> {
166    /// owns T
167    Owned(T),
168    /// has a reference to T
169    Borrowed(&'a mut T),
170}
171
172macro_rules! common_impls {
173    ($Name:ident) => {
174        impl<T> $Name<'_, T> {
175            /// Returns true if the data is owned else false.
176            pub fn is_owned(&self) -> bool {
177                match self {
178                    Self::Owned(_) => true,
179                    Self::Borrowed(_) => false,
180                }
181            }
182        }
183
184        impl<T: Clone> $Name<'_, T> {
185
186            /// Return the contained data in it's owned form.
187            ///
188            /// If it's borrowed this will clone it.
189            pub fn into_owned(self) -> T {
190                match self {
191                    Self::Owned(v) => v,
192                    Self::Borrowed(v) => v.clone(),
193                }
194            }
195
196            /// Internally converts the type into it's owned variant.
197            ///
198            /// Conversion from a reference to the owned variant is done by cloning.
199            ///
200            /// *This returns a `&mut T` and as such can be used to "unconditionally"
201            ///  get an `&mut T`*. Be aware that while this works with both `MaybeOwned`
202            ///  and `MaybeOwnedMut` it also converts it to an owned variant in both
203            ///  cases. So while it's the best way to get a `&mut T` for `MaybeOwned`
204            ///  for `MaybeOwnedMut` it's preferable to use `as_mut` from `AsMut`.
205            ///
206            /// ## Example
207            ///
208            /// ```
209            /// use maybe_owned::MaybeOwned;
210            ///
211            /// #[derive(Clone, Debug, PartialEq, Eq)]
212            /// struct PseudoBigData(u8);
213            ///
214            /// let data = PseudoBigData(12);
215            ///
216            /// let mut maybe: MaybeOwned<PseudoBigData> = (&data).into();
217            /// assert_eq!(false, maybe.is_owned());
218            ///
219            /// {
220            ///     let reference = maybe.make_owned();
221            ///     assert_eq!(&mut PseudoBigData(12), reference);
222            /// }
223            /// assert!(maybe.is_owned());
224            /// ```
225            pub fn make_owned(&mut self) -> &mut T {
226                match self {
227                    Self::Owned(v) => v,
228                    Self::Borrowed(v) => {
229                        *self = Self::Owned(v.clone());
230                        match self {
231                            Self::Owned(v) => v,
232                            Self::Borrowed(..) => unreachable!(),
233                        }
234                    }
235                }
236            }
237        }
238
239        impl<T> Deref for $Name<'_, T> {
240            type Target = T;
241
242            fn deref(&self) -> &T {
243                match self {
244                    Self::Owned(v) => v,
245                    Self::Borrowed(v) => v,
246                }
247            }
248        }
249
250        impl<T> AsRef<T> for $Name<'_, T> {
251            fn as_ref(&self) -> &T {
252                self
253            }
254        }
255
256        impl<T> From<T> for $Name<'_, T> {
257            fn from(v: T) -> Self {
258                Self::Owned(v)
259            }
260        }
261
262        impl<T> Borrow<T> for $Name<'_, T> {
263            fn borrow(&self) -> &T {
264                self
265            }
266        }
267
268        impl<T: Default> Default for $Name<'_, T> {
269            fn default() -> Self {
270                Self::Owned(T::default())
271            }
272        }
273
274        impl<'b, A: PartialEq<B>, B> PartialEq<$Name<'b, B>> for $Name<'_, A> {
275            #[inline]
276            fn eq(&self, other: &$Name<'b, B>) -> bool {
277                PartialEq::eq(self.deref(), other.deref())
278            }
279        }
280
281        impl<'a, T: Eq> Eq for $Name<'a, T> {}
282
283        impl<T: FromStr> FromStr for $Name<'_, T> {
284            type Err = T::Err;
285
286            fn from_str(s: &str) -> Result<Self, Self::Err> {
287                Ok(Self::Owned(T::from_str(s)?))
288            }
289        }
290
291        // TODO: Specify RHS
292        impl<T: PartialOrd> PartialOrd for $Name<'_, T> {
293            #[inline]
294            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
295                PartialOrd::partial_cmp(self.deref(), other.deref())
296            }
297        }
298
299        impl<T: Ord> Ord for $Name<'_, T> {
300            #[inline]
301            fn cmp(&self, other: &Self) -> Ordering {
302                Ord::cmp(self.deref(), other.deref())
303            }
304        }
305
306        impl<T: Hash> Hash for $Name<'_, T> {
307            #[inline]
308            fn hash<H: Hasher>(&self, state: &mut H) {
309                Hash::hash(self.deref(), state)
310            }
311        }
312
313        impl<'a, T: fmt::Display> fmt::Display for $Name<'a, T> {
314            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
315                match self {
316                    Self::Owned(o) => fmt::Display::fmt(o, f),
317                    Self::Borrowed(b) => fmt::Display::fmt(b, f),
318                }
319            }
320        }
321    };
322}
323
324common_impls!(MaybeOwned);
325common_impls!(MaybeOwnedMut);
326
327impl<'a, T> From<&'a T> for MaybeOwned<'a, T> {
328    fn from(v: &'a T) -> Self {
329        Self::Borrowed(v)
330    }
331}
332
333impl<'a, T> From<&'a mut T> for MaybeOwnedMut<'a, T> {
334    fn from(v: &'a mut T) -> Self {
335        Self::Borrowed(v)
336    }
337}
338
339impl<'a, T: ToOwned<Owned = T>> From<Cow<'a, T>> for MaybeOwned<'a, T> {
340    fn from(cow: Cow<'a, T>) -> MaybeOwned<'a, T> {
341        match cow {
342            Cow::Owned(v) => MaybeOwned::Owned(v),
343            Cow::Borrowed(v) => MaybeOwned::Borrowed(v),
344        }
345    }
346}
347
348impl<'a, T: ToOwned<Owned = T>> Into<Cow<'a, T>> for MaybeOwned<'a, T> {
349    fn into(self) -> Cow<'a, T> {
350        match self {
351            MaybeOwned::Owned(v) => Cow::Owned(v),
352            MaybeOwned::Borrowed(v) => Cow::Borrowed(v),
353        }
354    }
355}
356
357impl<T: Clone> Clone for MaybeOwned<'_, T> {
358    fn clone(&self) -> Self {
359        match self {
360            Self::Owned(v) => Self::Owned(v.clone()),
361            Self::Borrowed(v) => Self::Borrowed(v),
362        }
363    }
364}
365
366impl<T> MaybeOwned<'_, T> {
367    /// Returns a `&mut` if possible.
368    ///
369    /// If the internal representation is borrowed (`&T`) then
370    /// this method will return `None`
371    pub fn as_mut(&mut self) -> Option<&mut T> {
372        match self {
373            MaybeOwned::Owned(value) => Some(value),
374            MaybeOwned::Borrowed(_) => None
375        }
376    }
377}
378
379impl<T: Clone> MaybeOwned<'_, T> {
380    /// Acquires a mutable reference to owned data.
381    ///
382    /// Clones data if it is not already owned.
383    ///
384    /// ## Example
385    ///
386    /// ```
387    /// use maybe_owned::MaybeOwned;
388    ///
389    /// #[derive(Clone, Debug, PartialEq, Eq)]
390    /// struct PseudoBigData(u8);
391    ///
392    /// let data = PseudoBigData(12);
393    ///
394    /// let mut maybe: MaybeOwned<PseudoBigData> = (&data).into();
395    /// assert_eq!(false, maybe.is_owned());
396    ///
397    /// {
398    ///     let reference = maybe.to_mut();
399    ///     assert_eq!(&mut PseudoBigData(12), reference);
400    /// }
401    /// assert!(maybe.is_owned());
402    /// ```
403    ///
404    #[deprecated = "use `make_owned` instead"]
405    pub fn to_mut(&mut self) -> &mut T {
406        match *self {
407            Self::Owned(ref mut v) => v,
408            Self::Borrowed(v) => {
409                *self = Self::Owned(v.clone());
410                match *self {
411                    Self::Owned(ref mut v) => v,
412                    Self::Borrowed(..) => unreachable!(),
413                }
414            }
415        }
416    }
417}
418
419impl<T> DerefMut for MaybeOwnedMut<'_, T> {
420    fn deref_mut(&mut self) -> &mut T {
421        match self {
422            Self::Owned(v) => v,
423            Self::Borrowed(v) => v,
424        }
425    }
426}
427
428impl<T> AsMut<T> for MaybeOwnedMut<'_, T> {
429    fn as_mut(&mut self) -> &mut T {
430        match self {
431            Self::Owned(v) => v,
432            Self::Borrowed(v) => v,
433        }
434    }
435}
436
437impl<T> BorrowMut<T> for MaybeOwnedMut<'_, T> {
438    fn borrow_mut(&mut self) -> &mut T {
439        self
440    }
441}
442
443#[cfg(test)]
444mod tests {
445    use super::*;
446
447    type TestType = Vec<()>;
448
449    fn with_into<'a, I: Into<MaybeOwned<'a, TestType>>>(v: I) -> MaybeOwned<'a, TestType> {
450        v.into()
451    }
452
453    #[test]
454    fn is_owned() {
455        let data = TestType::default();
456        assert!(MaybeOwned::Owned(data).is_owned());
457    }
458
459    #[test]
460    fn make_owned() {
461        let mut a = MaybeOwned::Borrowed(&12u8);
462        assert!(!a.is_owned());
463        a.make_owned();
464        assert!(a.is_owned());
465        assert_eq!(&*a, &12);
466    }
467
468    #[test]
469    fn into_with_owned() {
470        //ty check if it accepts references
471        let data = TestType::default();
472        assert!(with_into(data).is_owned())
473    }
474    #[test]
475    fn into_with_borrow() {
476        //ty check if it accepts references
477        let data = TestType::default();
478        assert!(!with_into(&data).is_owned());
479    }
480
481    #[test]
482    fn clone_owned() {
483        let maybe = MaybeOwned::<TestType>::default();
484        assert!(maybe.clone().is_owned());
485    }
486
487    #[test]
488    fn clone_borrow() {
489        let data = TestType::default();
490        let maybe: MaybeOwned<TestType> = (&data).into();
491        assert!(!maybe.clone().is_owned());
492    }
493
494    #[test]
495    fn to_mut() {
496        let data = TestType::default();
497        let mut maybe: MaybeOwned<TestType> = (&data).into();
498        assert!(!maybe.is_owned());
499        {
500            #[allow(deprecated)]
501            let _mut_ref = maybe.to_mut();
502        }
503        assert!(maybe.is_owned());
504    }
505
506    #[test]
507    fn into_inner() {
508        let data = vec![1u32, 2];
509        let maybe: MaybeOwned<Vec<u32>> = (&data).into();
510        assert_eq!(data, maybe.into_owned());
511    }
512
513    #[test]
514    fn has_default() {
515        #[derive(Default)]
516        struct TestType(u8);
517        let _x: MaybeOwned<TestType> = Default::default();
518    }
519
520    #[test]
521    fn has_clone() {
522        #[derive(Clone)]
523        struct TestType(u8);
524        let _x = TestType(12).clone();
525    }
526
527    #[test]
528    fn has_deref() {
529        let a = MaybeOwned::Owned(vec![1u8]);
530        let _ = a.len();
531
532        let a = MaybeOwnedMut::Owned(vec![1u8]);
533        let _ = a.len();
534    }
535
536    #[test]
537    fn has_deref_mut() {
538        let mut a = MaybeOwnedMut::Owned(vec![1u8]);
539        a[0] = 12u8;
540    }
541
542    #[test]
543    fn has_partial_eq() {
544        #[derive(PartialEq)]
545        struct TestType(f32);
546
547        let n = TestType(33.0);
548        let a = MaybeOwned::Owned(TestType(42.0));
549        let b = MaybeOwned::Borrowed(&n);
550        let c = MaybeOwned::Owned(TestType(33.0));
551
552        assert_eq!(a == b, false);
553        assert_eq!(b == c, true);
554        assert_eq!(c == a, false);
555    }
556
557    #[test]
558    fn has_eq() {
559        #[derive(PartialEq, Eq)]
560        struct TestType(i32);
561
562        let n = TestType(33);
563        let a = MaybeOwned::Owned(TestType(42));
564        let b = MaybeOwned::Borrowed(&n);
565        let c = MaybeOwned::Owned(TestType(33));
566
567        assert_eq!(a == b, false);
568        assert_eq!(b == c, true);
569        assert_eq!(c == a, false);
570    }
571
572    #[test]
573    fn has_partial_ord() {
574        #[derive(PartialEq, PartialOrd)]
575        struct TestType(f32);
576
577        let n = TestType(33.0);
578        let a = MaybeOwned::Owned(TestType(42.0));
579        let b = MaybeOwned::Borrowed(&n);
580        let c = MaybeOwned::Owned(TestType(33.0));
581
582        assert_eq!(a > b, true);
583        assert_eq!(b > c, false);
584        assert_eq!(a < c, false);
585    }
586
587    #[test]
588    fn has_ord() {
589        #[derive(PartialEq, Eq, PartialOrd, Ord)]
590        struct TestType(i32);
591
592        let n = TestType(33);
593        let a = MaybeOwned::Owned(TestType(42));
594        let b = MaybeOwned::Borrowed(&n);
595        let c = MaybeOwned::Owned(TestType(33));
596
597        assert_eq!(a > b, true);
598        assert_eq!(b > c, false);
599        assert_eq!(a < c, false);
600    }
601
602    #[test]
603    fn has_hash() {
604        use std::collections::HashMap;
605
606        let mut map = HashMap::new();
607        map.insert(MaybeOwned::Owned(42), 33);
608
609        assert_eq!(map.get(&MaybeOwned::Borrowed(&42)), Some(&33));
610    }
611
612    #[test]
613    fn has_borrow() {
614        let v = MaybeOwned::Owned(42);
615        let _ = Borrow::<u8>::borrow(&v);
616
617        let v = MaybeOwnedMut::Owned(42);
618        let _ = Borrow::<u8>::borrow(&v);
619    }
620
621    #[test]
622    fn has_borrow_mut() {
623        let mut v = MaybeOwnedMut::Owned(42);
624        let _ = BorrowMut::<u8>::borrow_mut(&mut v);
625    }
626
627    #[test]
628    fn has_as_ref() {
629        let v = MaybeOwned::Owned(42);
630        let _ = AsRef::<u8>::borrow(&v);
631
632        let v = MaybeOwnedMut::Owned(42);
633        let _ = AsRef::<u8>::borrow(&v);
634    }
635
636    #[test]
637    fn has_as_mut() {
638        // uses a as_mut method
639        let mut v: MaybeOwned<u8> = (&11).into();
640        assert_eq!(v.as_mut(), None);
641
642        let mut v: MaybeOwned<u8> = 12.into();
643        assert_eq!(v.as_mut(), Some(&mut 12));
644
645        // uses AsMut
646        let mut v = MaybeOwnedMut::Owned(42);
647        let _ = AsMut::<u8>::borrow_mut(&mut v);
648    }
649
650    #[test]
651    fn has_display() {
652        let n = 33;
653        let a = MaybeOwned::Owned(42);
654        let b = MaybeOwned::Borrowed(&n);
655
656        let s = format!("{} {}", a, b);
657
658        assert_eq!(s, "42 33");
659    }
660
661    #[test]
662    fn from_cow() {
663        use std::borrow::Cow;
664
665        fn test<'a, V: Into<MaybeOwned<'a, i32>>>(v: V, n: i32) {
666            assert_eq!(*v.into(), n)
667        }
668
669        let n = 33;
670        test(Cow::Owned(42), 42);
671        test(Cow::Borrowed(&n), n);
672    }
673
674    #[test]
675    fn into_cow() {
676        use std::borrow::Cow;
677
678        fn test<'a, V: Into<Cow<'a, i32>>>(v: V, n: i32) {
679            assert_eq!(*v.into(), n)
680        }
681
682        let n = 33;
683        test(MaybeOwned::Owned(42), 42);
684        test(MaybeOwned::Borrowed(&n), n);
685    }
686
687    #[test]
688    fn from_str() {
689        let as_string = "12";
690        //assumption as_string is convertable to u32
691        assert_eq!(12u32, as_string.parse().unwrap());
692        assert_eq!(MaybeOwned::Owned(12u32), as_string.parse().unwrap());
693    }
694
695    #[test]
696    fn as_ref() {
697        let data = TestType::default();
698        let maybe_owned = MaybeOwned::Borrowed(&data);
699        let _ref: &TestType = maybe_owned.as_ref();
700        assert_eq!(&data as *const _ as usize, _ref as *const _ as usize);
701    }
702
703    #[test]
704    fn borrow() {
705        use std::borrow::Borrow;
706
707        let data = TestType::default();
708        let maybe_owned = MaybeOwned::Borrowed(&data);
709        let _ref: &TestType = maybe_owned.borrow();
710        assert_eq!(&data as *const _ as usize, _ref as *const _ as usize);
711    }
712
713    #[test]
714    fn reborrow_mut() {
715        let value = vec![0u32];
716        let mut value = MaybeOwnedMut::Owned(value);
717        let mut reborrow = MaybeOwnedMut::Borrowed(value.deref_mut());
718        reborrow.push(1);
719        assert_eq!(&[0, 1], &value[..]);
720    }
721}