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
/// Sod stands for Static or Dynamic. An enum to encapsulate values which
/// are either dynamically, heap-allocated values, or statics.
///
/// This allows us to define default primitives which are used throughout
/// without the overhead of reference counting, while still supporting the
/// flexibility to create primitives dynamically.
///
/// Thanks to the `Deref` implementation, either variants are treated like
/// the inner type without needing to worry about which it is.
///
/// Many thanks to [panicbit](https://github.com/panicbit) for helping to
/// get the `Deref` implementation working to make all the magic happen.

use std::ops::Deref;
use std::sync::Arc;

#[derive(Debug, PartialEq, PartialOrd)]
/// Enum to hold either static references or reference-counted owned objects.
/// Implements `Deref` to `T` for ease of use.
/// Since internal data is either a static reference, or an `Arc`, cloning
/// is a cheap operation.
pub enum Sod<T: ?Sized + 'static> {
    /// Static reference to T
    Static(&'static T),
    /// Dynamically allocated T, on the heap, atomically reference-counted.
    Dynamic(Arc<Box<T>>),
}

impl<T: ?Sized> Deref for Sod<T> {
    type Target = T;
    fn deref(&self) -> &T {
        match *self {
            Sod::Static(t) => t,
            Sod::Dynamic(ref t) => t,
        }
    }
}

impl<T: ?Sized> Clone for Sod<T> {
    fn clone(&self) -> Self {
        match *self {
            Sod::Static(t) => Sod::Static(t),
            Sod::Dynamic(ref t) => Sod::Dynamic(Arc::clone(t)),
        }
    }
}