diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d667c05e..ab81afe48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ * nostr: manually impl eq and cmp traits for `RelayUrl` ([Yuki Kishimoto]) * nostr: use `Cow` in `ClientMessage` and `RelayMessage` ([Yuki Kishimoto]) * nostr: derive `PartialOrd`, `Ord`, and `Hash` traits in `Nip21` enum ([Yuki Kishimoto]) +* nostr: add `push`, `pop`, `insert` and `remove` methods to `Tags` struct ([Yuki Kishimoto]) * pool: take event reference in `send_event` methods ([Yuki Kishimoto]) * pool: use the relay ingester to perform actions ([Yuki Kishimoto]) * pool: avoid spawning a task for every authentication request ([Yuki Kishimoto]) diff --git a/crates/nostr/src/event/tag/list.rs b/crates/nostr/src/event/tag/list.rs index 0b9a5c03e..d3cc21dfc 100644 --- a/crates/nostr/src/event/tag/list.rs +++ b/crates/nostr/src/event/tag/list.rs @@ -87,6 +87,76 @@ impl Tags { self.list.is_empty() } + /// Appends a [`Tag`] to the back of the collection. + /// + /// Check [`Vec::push`] doc to learn more. + /// + /// This erases the [`TagsIndexes`]. + pub fn push(&mut self, tag: Tag) { + // Erase indexes + self.erase_indexes(); + + // Append + self.list.push(tag); + } + + /// Removes the last [`Tag`] and returns it, or `None` if it's empty. + /// + /// Check [`Vec::pop`] doc to learn more. + /// + /// This erases the [`TagsIndexes`]. + pub fn pop(&mut self) -> Option { + // Erase indexes + self.erase_indexes(); + + // Pop last item + self.list.pop() + } + + /// Inserts a [`Tag`] at position `index` within the vector, + /// shifting all tags after it to the right. + /// + /// Returns `true` if the [`Tag`] is inserted successfully. + /// Returns `false` if `index > len`. + /// + /// Check [`Vec::insert`] doc to learn more. + /// + /// This erases the [`TagsIndexes`]. + pub fn insert(&mut self, index: usize, tag: Tag) -> bool { + // Check if `index` is bigger than collection len + if index > self.list.len() { + return false; + } + + // Erase indexes + self.erase_indexes(); + + // Insert at position + self.list.insert(index, tag); + + // Inserted successfully + true + } + + /// Removes and returns the [`Tag`] at position `index` within the vector, + /// shifting all tags after it to the left. + /// + /// Check [`Vec::remove`] doc to learn more. + /// + /// This erases the [`TagsIndexes`]. + pub fn remove(&mut self, index: usize) -> Option { + // Check if `index` is bigger than collection len + if index > self.list.len() { + return None; + } + + // Erase indexes + self.erase_indexes(); + + // Remove from collection + Some(self.list.remove(index)) + } + /// Get first tag #[inline] pub fn first(&self) -> Option<&Tag> { @@ -242,6 +312,13 @@ impl Tags { idx } + #[inline] + fn erase_indexes(&mut self) { + if self.indexes.get().is_some() { + self.indexes = OnceCell::new(); + } + } + /// Get indexes #[inline] pub fn indexes(&self) -> &TagsIndexes {