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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
/*!

Traits that cover interacting with and manipulating paths in a graph.

* [`GraphPaths`] has the basic interface
* [`GraphPathNames`] supports retrieving the ID of a path by name, or vice versa
* [`MutableGraphPaths`] includes creating and destroying paths, and methods for manipulating the steps on a path
* [`PathSequences`] is for going between path step indices and sequence positions
* [`GraphPathsRef`] provides a reference to a specific path, which can then be queried using the traits in [`super::path`]
* [`IntoPathIds`] provides an iterator on the paths by ID
* [`IntoNodeOccurrences`] provides an iterator on the steps that are on a given node

*/

use crate::handle::Handle;

use super::{PathBase, PathId};

/// Trait for iterating through all `PathIds` in a graph.
pub trait IntoPathIds {
    type PathIds: Iterator<Item = PathId>;

    fn path_ids(self) -> Self::PathIds;
}

/// Trait for iterating through all the path steps on a handle in a graph.
pub trait IntoNodeOccurrences: GraphPaths {
    /// An iterator through the steps on a path, by `PathId` and `StepIx`.
    type Occurrences: Iterator<Item = (PathId, Self::StepIx)>;

    fn steps_on_handle(self, handle: Handle) -> Option<Self::Occurrences>;
}

/// A handlegraph with embedded paths. The step for any given path is
/// indexed by the associated type `StepIx`.
///
/// Provides methods for basic querying of the graph's paths, and
/// steps on a path. For a more ergonomic way of iterating through the
/// steps of a path, see the traits `GraphPathsRef`, and `PathSteps`.
pub trait GraphPaths: Sized {
    type StepIx: Sized + Copy + Eq;

    /// Return the number of paths in this graph.
    fn path_count(&self) -> usize;

    /// Return the number of steps of the path `id`, if it exists.
    fn path_len(&self, id: PathId) -> Option<usize>;

    /// Return the circularity of the path `id`, if it exists.
    fn path_circular(&self, id: PathId) -> Option<bool>;

    /// Find the handle at step `index` in path `id`, if both the path
    /// exists, and the step in the path.
    fn path_handle_at_step(
        &self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<Handle>;

    /// Return the index to the first step of path `id`, if the path
    /// exists and is not empty.
    ///
    /// The resulting `StepIx` should point to the first step of the
    /// path's `Steps` iterator.
    fn path_first_step(&self, id: PathId) -> Option<Self::StepIx>;

    /// Return the index to the last step of path `id`, if the path
    /// exists and is not empty.
    ///
    /// The resulting `StepIx` should point to the last step of the
    /// path's `Steps` iterator.
    fn path_last_step(&self, id: PathId) -> Option<Self::StepIx>;

    /// Return the index to the step after `index` on path `id`, if
    /// the path exists and `index` both exists on the path, and is
    /// not the last step of the path.
    ///
    /// The resulting `StepIx` should point to the same step as would
    /// calling `next` on the path's corresponding `Steps` iterator,
    /// if `index` was the last produced step.
    fn path_next_step(
        &self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<Self::StepIx>;

    /// Return the index to the step before `index` on path `id`, if
    /// the path exists and `index` both exists on the path, and is
    /// not the first step of the path.
    ///
    /// The resulting `StepIx` should point to the same step as would
    /// calling `next_back` on the path's corresponding `Steps` iterator,
    /// if `index` was the last produced step.
    fn path_prev_step(
        &self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<Self::StepIx>;
}

/// Trait for retrieving the `PathId` for a path by name, and vice
/// versa.
///
/// Names are represented as an iterator over `u8`s for flexibility in
/// underlying storage.
pub trait GraphPathNames: Sized {
    /// The iterator on the name of a path.
    type PathName: Iterator<Item = u8>;

    /// Returns the `PathId` that the provided `name` points to, if
    /// there exists a path with that name.
    fn get_path_id(self, name: &[u8]) -> Option<PathId>;

    /// Returns an iterator that produced the name of the path `id`,
    /// if that path exists in the graph.
    fn get_path_name(self, id: PathId) -> Option<Self::PathName>;

    /// Convenience method for retrieving a path name as a `Vec<u8>`.
    #[inline]
    fn get_path_name_vec(self, id: PathId) -> Option<Vec<u8>> {
        self.get_path_name(id).map(|name| name.collect())
    }

    /// Convenience method for checking whether a path exists by name.
    #[inline]
    fn has_path(self, name: &[u8]) -> bool {
        self.get_path_id(name).is_some()
    }
}

/// A handlegraph with embedded paths that can be created, destroyed,
/// and otherwise manipulated.
pub trait MutableGraphPaths: GraphPaths {
    /// Create a new path with the given name and return its `PathId`.
    /// Returns `None` if the path already exists in the graph.
    fn create_path(&mut self, name: &[u8], circular: bool) -> Option<PathId>;

    /// Destroy the path with the given `id`. Returns `true` if the
    /// path was destroyed, `false` if the path did not exist or
    /// couldn't be destroyed.
    fn destroy_path(&mut self, id: PathId) -> bool;

    /// Append a step on the given `handle` to the end of path `id`,
    /// if the path exists. Returns the index of the new step.
    fn path_append_step(
        &mut self,
        id: PathId,
        handle: Handle,
    ) -> Option<Self::StepIx>;

    /// Prepend a step on the given `handle` to the beginning of path
    /// `id`, if the path exists. Returns the index of the new step.
    fn path_prepend_step(
        &mut self,
        id: PathId,
        handle: Handle,
    ) -> Option<Self::StepIx>;

    /// Insert a step on the given `handle` into path `id`, after the
    /// step at `index`. Returns the index of the new step if it was
    /// successfully inserted, or `None` if either the path or the
    /// step does not exist.
    fn path_insert_step_after(
        &mut self,
        id: PathId,
        index: Self::StepIx,
        handle: Handle,
    ) -> Option<Self::StepIx>;

    /// Remove the step at `index` from path `id`. Returns the index
    /// of the removed step if it existed and was removed.
    fn path_remove_step(
        &mut self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<Self::StepIx>;

    /// Flip the orientation of the handle on step at `index` on path
    /// `id`, if it exists.
    fn path_flip_step(
        &mut self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<Self::StepIx>;

    /// Replace the steps starting from the step at `from` (inclusive)
    /// until the step `to` (exclusive) with steps on the `Handle`s in
    /// `new_segment`. Returns a pair where the first entry is the
    /// pointer to the step corresponding to the first handle in
    /// `new_segment`, and the second entry, the step corresponding to
    /// the last handle.
    ///
    /// Depending on the graph implementation, if `to` denotes a step
    /// beyond the path, all steps beginning at `from` will be removed
    /// and replaced. If `new_segment` is empty, the range will simply
    /// be deleted, contracting the path. In that case, which pointers
    /// are returned depend on the implementation.
    ///
    /// The step `from` must come before `to` in the path, but it's up
    /// to implementations to choose how to handle it if that's not
    /// the case -- potentially panicking.
    fn path_rewrite_segment(
        &mut self,
        id: PathId,
        from: Self::StepIx,
        to: Self::StepIx,
        new_segment: &[Handle],
    ) -> Option<(Self::StepIx, Self::StepIx)>;

    /// Set the circularity of path `id`.
    fn path_set_circularity(
        &mut self,
        id: PathId,
        circular: bool,
    ) -> Option<()>;
}

/// A handlegraph with embedded paths whose steps are associated with
/// the sequence positions and lengths of their nodes.
pub trait PathSequences: GraphPaths {
    /// Return the length of path `id` in nucleotides, if it exists.
    fn path_bases_len(&self, id: PathId) -> Option<usize>;

    /// Return the index of the step at sequence position `pos` along
    /// path `id`, or `None` if either the path doesn't exist, or if
    /// the path is shorter than `pos` bases.
    fn path_step_at_base(&self, id: PathId, pos: usize)
        -> Option<Self::StepIx>;

    /// Return the sequence offset of the step at `index` in path
    /// `id`, if it exists.
    fn path_step_base_offset(
        &self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<usize>;
}

/// A handlegraph that can produce references to specific paths.
pub trait GraphPathsRef: GraphPaths {
    type PathRef: PathBase<StepIx = Self::StepIx>;
    fn get_path_ref(self, id: PathId) -> Option<Self::PathRef>;
}

pub trait GraphPathsSteps: GraphPathsRef {
    type Step: super::path::PathStep;
    type Steps: DoubleEndedIterator<Item = Self::Step>;

    fn path_steps(self, id: PathId) -> Option<Self::Steps>;

    fn path_steps_range(
        self,
        id: PathId,
        from: Self::StepIx,
        to: Self::StepIx,
    ) -> Option<Self::Steps>;
}

pub trait GraphPathsRefMut: GraphPaths {
    type PathMut: PathBase<StepIx = Self::StepIx>;

    fn get_path_mut_ref<'a>(
        &'a mut self,
        id: PathId,
    ) -> Option<&'a mut Self::PathMut>;
}

impl<'a, T> GraphPaths for &'a T
where
    T: GraphPaths,
{
    type StepIx = T::StepIx;

    fn path_count(&self) -> usize {
        T::path_count(self)
    }

    fn path_len(&self, id: PathId) -> Option<usize> {
        T::path_len(self, id)
    }

    fn path_circular(&self, id: PathId) -> Option<bool> {
        T::path_circular(self, id)
    }

    fn path_handle_at_step(
        &self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<Handle> {
        T::path_handle_at_step(self, id, index)
    }

    fn path_first_step(&self, id: PathId) -> Option<Self::StepIx> {
        T::path_first_step(self, id)
    }

    fn path_last_step(&self, id: PathId) -> Option<Self::StepIx> {
        T::path_last_step(self, id)
    }

    fn path_next_step(
        &self,
        id: PathId,
        step: Self::StepIx,
    ) -> Option<Self::StepIx> {
        T::path_next_step(self, id, step)
    }

    fn path_prev_step(
        &self,
        id: PathId,
        step: Self::StepIx,
    ) -> Option<Self::StepIx> {
        T::path_prev_step(self, id, step)
    }
}

impl<'a, T> GraphPaths for &'a mut T
where
    T: GraphPaths,
{
    // type Step = T::Step;
    type StepIx = T::StepIx;

    fn path_count(&self) -> usize {
        T::path_count(self)
    }

    fn path_len(&self, id: PathId) -> Option<usize> {
        T::path_len(self, id)
    }

    fn path_circular(&self, id: PathId) -> Option<bool> {
        T::path_circular(self, id)
    }

    fn path_handle_at_step(
        &self,
        id: PathId,
        index: Self::StepIx,
    ) -> Option<Handle> {
        T::path_handle_at_step(self, id, index)
    }

    fn path_first_step(&self, id: PathId) -> Option<Self::StepIx> {
        T::path_first_step(self, id)
    }

    fn path_last_step(&self, id: PathId) -> Option<Self::StepIx> {
        T::path_last_step(self, id)
    }

    fn path_next_step(
        &self,
        id: PathId,
        step: Self::StepIx,
    ) -> Option<Self::StepIx> {
        T::path_next_step(self, id, step)
    }

    fn path_prev_step(
        &self,
        id: PathId,
        step: Self::StepIx,
    ) -> Option<Self::StepIx> {
        T::path_prev_step(self, id, step)
    }
}