diff options
author | SoniEx2 <endermoneymod@gmail.com> | 2021-11-14 14:38:57 -0300 |
---|---|---|
committer | SoniEx2 <endermoneymod@gmail.com> | 2021-11-14 14:38:57 -0300 |
commit | be4c770a7c65bb1eb3d8b96128abfc5fa89d63d1 (patch) | |
tree | 89de310d5fb28072cbdc507b2c6ede0749d09cf9 /src/suggestion.rs | |
parent | 26ae2d9a528e3f97a7f46e4b7aa4b1ec58fea127 (diff) |
Add Suggestion
Diffstat (limited to 'src/suggestion.rs')
-rw-r--r-- | src/suggestion.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/suggestion.rs b/src/suggestion.rs new file mode 100644 index 0000000..bad9793 --- /dev/null +++ b/src/suggestion.rs @@ -0,0 +1,81 @@ +// Copyright (c) 2021 Soni L. +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//! A Suggestion. + +use ::std::ops::Range; + +/// A suggested editing operation. +/// +/// # Examples +/// +/// ```rust +/// use iosonism::suggestion::Suggestion; +/// +/// let s = Suggestion::new(3..3, "home".into()); +/// assert_eq!(s.apply("Go ".into()), "Go home"); +/// ``` +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct Suggestion { + range: Range<usize>, + text: String, +} + +impl Suggestion { + /// Creates a new `Suggestion` for `text` for the given `range`. + pub fn new(range: Range<usize>, text: String) -> Self { + Self { + range: range, + text: text, + } + } + + /// Returns the range associated with this suggestion. + pub fn get_range(&self) -> Range<usize> { + self.range.clone() + } + + /// Returns the replacement text associated with this suggestion. + pub fn get_text(&self) -> &str { + &self.text + } + + /// Applies this suggestion on the `input`. + /// + /// # Panics + /// + /// Panics if the range is outside the `input`'s bounds, or not on an UTF-8 + /// boundary. + pub fn apply(&self, mut input: String) -> String { + // the use of String here actually has a performance reason: + // either you already have a String, in which case this is fast, + // or you need a String anyway, in which case it's your responsibility + // to make your &str into one. + input.replace_range(self.range.clone(), &self.text); + input + } + + /// Creates a new `Suggestion` by applying this `Suggestion` on the + /// `range` part of the given `input`. + /// + /// # Panics + /// + /// May panic if this suggestion's range is outside the bounds given by + /// `range`. Panics if the given `range` is outside `input`'s bounds, or any + /// range is not on an UTF-8 boundary. + // FIXME: This function could really use a better description. + pub fn expand(&self, mut input: String, range: Range<usize>) -> Self { + // It is our understanding that both ranges must be within input. + // It's also our understanding that self.range must be within the passed + // range. + // So we just do our best to enforce those. + input.truncate(range.end); + input.drain(..range.start); + input.replace_range( + (self.range.start-range.start)..(self.range.end-range.start), + &self.text, + ); + Self::new(range, input) + } +} |