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
//! These are traits that are implemented for the types of cyclers.
//! `CyclerWriter` has many sub-traits that contain the functions allowing the writer to move to the next block,
//! while `CyclerReader` is a single trait that allows the reader to move to the latest block.
//! `WriteAccess` and `ReadAccess` are traits that should be implemented for any type that goes into a cycler.

/// Trait that can be implemented to ensure a type is send
pub trait EnsureSend: Send {}
/// Trait that can be implemented to ensure a type is sync
pub trait EnsureSync: Sync {}

/// This trait should be implemented for any type that can be written to by a cycler.
/// This specifically allows for the separation of read and write data from the cycler readers and writers.
/// If this functionality is not needed then `WriteAccess::Write` can be set to `Self` for no runtime cost.
pub trait WriteAccess {
    /// The type of write data that can be accessed.
    /// Will default to `Self` when https://github.com/rust-lang/rust/issues/29661 is resolved.
    type Write;

    /// Gets shared access to the write data contained
    fn write_data(&self) -> &Self::Write;
    /// Gets exclusive access to the write data contained
    fn write_data_mut(&mut self) -> &mut Self::Write;
}
/// Ensure `WriteAccess` can be trait object
impl<W> dyn WriteAccess<Write = W> {}

/// This trait should be implemented for any type that can be read from by a cycler.
/// This specifically allows for the separation of read and write data from the cycler readers and writers.
/// If this functionality is not needed then `ReadAccess::Read` can be set to `Self` for no runtime cost.
pub trait ReadAccess {
    /// The type of read data that can be accessed.
    /// Will default to `Self` when https://github.com/rust-lang/rust/issues/29661 is resolved.
    type Read;

    /// Gets shared access to the read data contained
    fn read_data(&self) -> &Self::Read;
}
/// Ensure `ReadAccess` can be trait object
impl<R> dyn ReadAccess<Read = R> {}

/// This trait is implemented for the write half of a cycler.
pub trait CyclerWriter<T>: WriteAccess<Write = T::Write>
where
    T: WriteAccess,
{
}
/// Ensure `CyclerWriter` can be trait object
impl<T> dyn CyclerWriter<T> where T: WriteAccess {}

/// This trait enables the write half of the cycler to be moved to the next chunk by a default copy function.
/// Usually this function is `Clone::clone_from` but that is not a strict requirement.
pub trait CyclerWriterDefault<T>: CyclerWriter<T>
where
    T: WriteAccess,
{
    /// Moves the writer to the next block cloning the previously written block using a default function.
    fn write_next(&mut self);
}
/// Ensure `CyclerWriterDefault` can be trait object
impl<T> dyn CyclerWriterDefault<T> where T: WriteAccess {}

/// This trait enables the write half of the cycler to move to the next block using a given clone function.
/// This function follows the signature of `Clone::clone_from`, meaning the arguments are (to, from).
pub trait CyclerWriterFn<T>: CyclerWriter<T>
where
    T: WriteAccess,
{
    /// Moves the writer to the next block cloning using an `fn` pointer.
    /// Arguments are (to, from)
    /// This function uses an `fn` pointer so has no additional runtime cost and can be called on a trait object.
    fn write_next_fn(&mut self, clone_fn: fn(&mut T, &T));
    /// Moves the writer to the next block cloning using an `FnOnce` impl
    /// Arguments are (to, from)
    /// This function is generic over the function reducing runtime cost but cannot be called on trait objects.
    fn write_next_fn_impl(&mut self, clone_fn: impl FnOnce(&mut T, &T))
    where
        Self: Sized;
    /// Moves the writer to the next block cloning using an `FnMut` dynamic reference.
    /// Arguments are (to, from)
    /// This function takes a dyn pointer so a v-table lookup is necessary.
    /// `write_next_fn` is preferred if the function can be an `fn` pointer or `write_next_fn_impl` is preferred if self is sized.
    fn write_next_fn_dyn(&mut self, clone_fn: &mut dyn FnMut(&mut T, &T));
    /// Moves the writer to the next block cloning using a boxed `FnOnce`
    /// Arguments are (to, from)
    /// This function takes a boxed dyn pointer so a v-table lookup is necessary.
    /// `write_next_fn_dyn` is preferred if the function can be coerced into an `FnMut` as no heap allocation will be necessary.
    fn write_next_fn_dyn_boxed(&mut self, clone_fn: Box<dyn FnOnce(&mut T, &T)>);
}
/// Ensure `CyclerWriterFn` can be trait object
impl<T> dyn CyclerWriterFn<T> where T: WriteAccess {}

/// This trait enables the write half of the cycler to move to the next block using a clone function that takes a mutable reference to the previous block.
/// This is not preferable as optimizations where the reader can read the previous block while it's being cloned are not possible.
/// The function arguments are (from, to)
pub trait CyclerWriterMutFn<T>: CyclerWriter<T>
where
    T: WriteAccess,
{
    /// Moves the writer to the next block cloning using an `fn` pointer.
    /// Arguments are (to, from)
    /// This function uses an `fn` pointer so has no additional runtime cost and can be called on a trait object.
    fn write_next_mut_fn(&mut self, clone_fn: fn(&mut T, &mut T));
    /// Moves the writer to the next block cloning using an `FnOnce` impl
    /// Arguments are (to, from)
    /// This function is generic over the function reducing runtime cost but cannot be called on trait objects.
    fn write_next_mut_fn_impl(&mut self, clone_fn: impl FnOnce(&mut T, &mut T))
    where
        Self: Sized;
    /// Moves the writer to the next block cloning using an `FnMut` dynamic reference.
    /// Arguments are (to, from)
    /// This function takes a dyn pointer so a v-table lookup is necessary.
    /// `write_next_mut_fn` is preferred if the function can be an `fn` pointer or `write_next_mut_fn_impl` is preferred if self is sized.
    fn write_next_mut_fn_dyn(&mut self, clone_fn: &mut dyn FnMut(&mut T, &mut T));
    /// Moves the writer to the next block cloning using a boxed `FnOnce`
    /// Arguments are (to, from)
    /// This function takes a boxed dyn pointer so a v-table lookup is necessary.
    /// `write_next_mut_fn_dyn` is preferred if the function can be coerced into an `FnMut` as no heap allocation will be necessary.
    fn write_next_mut_fn_dyn_boxed(&mut self, clone_fn: Box<dyn FnOnce(&mut T, &mut T)>);
}
/// Ensure `CyclerWriterMutClone` can be trait object
impl<T> dyn CyclerWriterMutFn<T> where T: WriteAccess {}

/// This trait is a collection of all the primarily supported writer traits.
/// Other traits may be added to this in the future but none will be taken away without a major version bump.
/// Other traits may also be added that do not fall under this for more specific functionality (ex: `CyclerWriterMutFn`).
pub trait UniversalCyclerWriter<T>: CyclerWriterFn<T> + CyclerWriterDefault<T>
where
    T: WriteAccess + Clone,
{
}
/// Ensure `UniversalCyclerWriter` can be trait object
impl<T> dyn UniversalCyclerWriter<T> where T: WriteAccess {}

/// This trait is implemented for the read half of a cycler.
pub trait CyclerReader<T>: ReadAccess<Read = T::Read>
where
    T: ReadAccess,
{
    /// Moves the reader to the most up-to-date block at the time of call.
    /// This may be the same block as previously read which means the writer has not published a new block in the time since the last call.
    fn read_latest(&mut self);
}
/// Ensure `CyclerReader` can be trait object
impl<T> dyn CyclerReader<T> where T: ReadAccess {}

/// This trait is a collection of all the primarily supported reader traits.
/// Other traits may be added to this in the future but none will be taken away without a major version bump.
/// Other traits may also be added that do not fall under this for more specific functionality.
pub trait UniversalCyclerReader<T>:
    CyclerWriterFn<T> + CyclerWriterMutFn<T> + CyclerWriterDefault<T>
where
    T: WriteAccess,
{
}
/// Ensure `UniversalCyclerReader` can be trait object
impl<T> dyn UniversalCyclerReader<T> where T: WriteAccess {}