refactor: implemented TryRemove as trait
This commit is contained in:
parent
230b027b59
commit
94c9a264a4
2 changed files with 76 additions and 58 deletions
|
|
@ -6,7 +6,8 @@ use crate::{
|
||||||
deobfuscate::Deobfuscator,
|
deobfuscate::Deobfuscator,
|
||||||
model::{ChannelId, Language, Paginator, Playlist, PlaylistVideo},
|
model::{ChannelId, Language, Paginator, Playlist, PlaylistVideo},
|
||||||
serializer::text::{PageType, TextLink},
|
serializer::text::{PageType, TextLink},
|
||||||
timeago, util,
|
timeago,
|
||||||
|
util::{self, TryRemove},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{response, ClientType, MapResponse, MapResult, RustyPipeQuery, YTContext};
|
use super::{response, ClientType, MapResponse, MapResult, RustyPipeQuery, YTContext};
|
||||||
|
|
@ -73,25 +74,21 @@ impl MapResponse<Playlist> for response::Playlist {
|
||||||
// TODO: think about a deserializer that deserializes only first list item
|
// TODO: think about a deserializer that deserializes only first list item
|
||||||
let mut tcbr_contents = self.contents.two_column_browse_results_renderer.contents;
|
let mut tcbr_contents = self.contents.two_column_browse_results_renderer.contents;
|
||||||
let video_items = some_or_bail!(
|
let video_items = some_or_bail!(
|
||||||
util::vec_try_swap_remove(
|
some_or_bail!(
|
||||||
&mut some_or_bail!(
|
some_or_bail!(
|
||||||
util::vec_try_swap_remove(
|
tcbr_contents.try_swap_remove(0),
|
||||||
&mut some_or_bail!(
|
Err(anyhow!("twoColumnBrowseResultsRenderer empty"))
|
||||||
util::vec_try_swap_remove(&mut tcbr_contents, 0),
|
|
||||||
Err(anyhow!("twoColumnBrowseResultsRenderer empty"))
|
|
||||||
)
|
|
||||||
.tab_renderer
|
|
||||||
.content
|
|
||||||
.section_list_renderer
|
|
||||||
.contents,
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
Err(anyhow!("sectionListRenderer empty"))
|
|
||||||
)
|
)
|
||||||
.item_section_renderer
|
.tab_renderer
|
||||||
.contents,
|
.content
|
||||||
0
|
.section_list_renderer
|
||||||
),
|
.contents
|
||||||
|
.try_swap_remove(0),
|
||||||
|
Err(anyhow!("sectionListRenderer empty"))
|
||||||
|
)
|
||||||
|
.item_section_renderer
|
||||||
|
.contents
|
||||||
|
.try_swap_remove(0),
|
||||||
Err(anyhow!("itemSectionRenderer empty"))
|
Err(anyhow!("itemSectionRenderer empty"))
|
||||||
)
|
)
|
||||||
.playlist_video_list_renderer
|
.playlist_video_list_renderer
|
||||||
|
|
@ -103,7 +100,7 @@ impl MapResponse<Playlist> for response::Playlist {
|
||||||
Some(sidebar) => {
|
Some(sidebar) => {
|
||||||
let mut sidebar_items = sidebar.playlist_sidebar_renderer.items;
|
let mut sidebar_items = sidebar.playlist_sidebar_renderer.items;
|
||||||
let mut primary = some_or_bail!(
|
let mut primary = some_or_bail!(
|
||||||
util::vec_try_swap_remove(&mut sidebar_items, 0),
|
sidebar_items.try_swap_remove(0),
|
||||||
Err(anyhow!("no primary sidebar"))
|
Err(anyhow!("no primary sidebar"))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -113,10 +110,10 @@ impl MapResponse<Playlist> for response::Playlist {
|
||||||
.thumbnail_renderer
|
.thumbnail_renderer
|
||||||
.playlist_video_thumbnail_renderer
|
.playlist_video_thumbnail_renderer
|
||||||
.thumbnail,
|
.thumbnail,
|
||||||
util::vec_try_swap_remove(
|
primary
|
||||||
&mut primary.playlist_sidebar_primary_info_renderer.stats,
|
.playlist_sidebar_primary_info_renderer
|
||||||
2,
|
.stats
|
||||||
),
|
.try_swap_remove(2),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -126,7 +123,8 @@ impl MapResponse<Playlist> for response::Playlist {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut byline = self.header.playlist_header_renderer.byline;
|
let mut byline = self.header.playlist_header_renderer.byline;
|
||||||
let last_update_txt = util::vec_try_swap_remove(&mut byline, 1)
|
let last_update_txt = byline
|
||||||
|
.try_swap_remove(1)
|
||||||
.map(|b| b.playlist_byline_renderer.text);
|
.map(|b| b.playlist_byline_renderer.text);
|
||||||
|
|
||||||
(
|
(
|
||||||
|
|
@ -207,7 +205,7 @@ impl MapResponse<Paginator<PlaylistVideo>> for response::PlaylistCont {
|
||||||
) -> Result<MapResult<Paginator<PlaylistVideo>>> {
|
) -> Result<MapResult<Paginator<PlaylistVideo>>> {
|
||||||
let mut actions = self.on_response_received_actions;
|
let mut actions = self.on_response_received_actions;
|
||||||
let action = some_or_bail!(
|
let action = some_or_bail!(
|
||||||
util::vec_try_swap_remove(&mut actions, 0),
|
actions.try_swap_remove(0),
|
||||||
Err(anyhow!("no continuation action"))
|
Err(anyhow!("no continuation action"))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -422,11 +420,7 @@ mod tests {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
playlist
|
playlist.videos.extend_limit(rp.query(), 101).await.unwrap();
|
||||||
.videos
|
|
||||||
.extend_limit(rp.query(), 101)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
assert!(playlist.videos.items.len() > 100);
|
assert!(playlist.videos.items.len() > 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
78
src/util.rs
78
src/util.rs
|
|
@ -104,35 +104,43 @@ pub fn retry_delay(
|
||||||
min_retry_interval.max(jittered_delay.min(max_retry_interval))
|
min_retry_interval.max(jittered_delay.min(max_retry_interval))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes and returns the element at position `index` within the vector,
|
pub trait TryRemove<T> {
|
||||||
/// shifting all elements after it to the left.
|
/// Removes and returns the element at position `index` within the vector,
|
||||||
///
|
/// shifting all elements after it to the left.
|
||||||
/// Returns None if the index is out of bounds.
|
///
|
||||||
///
|
/// Returns None if the index is out of bounds.
|
||||||
/// Note: Because this shifts over the remaining elements, it has a
|
///
|
||||||
/// worst-case performance of *O*(*n*). If you don't need the order of elements
|
/// Note: Because this shifts over the remaining elements, it has a
|
||||||
/// to be preserved, use [`vec_try_swap_remove`] instead.
|
/// worst-case performance of *O*(*n*). If you don't need the order of elements
|
||||||
pub fn vec_try_remove<T>(vec: &mut Vec<T>, index: usize) -> Option<T> {
|
/// to be preserved, use [`vec_try_swap_remove`] instead.
|
||||||
if index < vec.len() {
|
fn try_remove(&mut self, index: usize) -> Option<T>;
|
||||||
Some(vec.remove(index))
|
|
||||||
} else {
|
/// Removes an element from the vector and returns it.
|
||||||
None
|
///
|
||||||
}
|
/// The removed element is replaced by the last element of the vector.
|
||||||
|
///
|
||||||
|
/// Returns None if the index is out of bounds.
|
||||||
|
///
|
||||||
|
/// This does not preserve ordering, but is *O*(1).
|
||||||
|
/// If you need to preserve the element order, use [`vec_try_remove`] instead.
|
||||||
|
fn try_swap_remove(&mut self, index: usize) -> Option<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes an element from the vector and returns it.
|
impl<T> TryRemove<T> for Vec<T> {
|
||||||
///
|
fn try_remove(&mut self, index: usize) -> Option<T> {
|
||||||
/// The removed element is replaced by the last element of the vector.
|
if index < self.len() {
|
||||||
///
|
Some(self.remove(index))
|
||||||
/// Returns None if the index is out of bounds.
|
} else {
|
||||||
///
|
None
|
||||||
/// This does not preserve ordering, but is *O*(1).
|
}
|
||||||
/// If you need to preserve the element order, use [`vec_try_remove`] instead.
|
}
|
||||||
pub fn vec_try_swap_remove<T>(vec: &mut Vec<T>, index: usize) -> Option<T> {
|
|
||||||
if index < vec.len() {
|
fn try_swap_remove(&mut self, index: usize) -> Option<T> {
|
||||||
Some(vec.swap_remove(index))
|
if index < self.len() {
|
||||||
} else {
|
Some(self.swap_remove(index))
|
||||||
None
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,4 +182,20 @@ mod tests {
|
||||||
expect_max
|
expect_max
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t_vec_try_remove() {
|
||||||
|
let mut v = vec![1, 2, 3];
|
||||||
|
assert_eq!(v.try_remove(0).unwrap(), 1);
|
||||||
|
assert_eq!(v.try_remove(1).unwrap(), 3);
|
||||||
|
assert_eq!(v.try_remove(1), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn t_vec_try_swap_remove() {
|
||||||
|
let mut v = vec![1, 2, 3];
|
||||||
|
assert_eq!(v.try_swap_remove(0).unwrap(), 1);
|
||||||
|
assert_eq!(v.try_swap_remove(1).unwrap(), 2);
|
||||||
|
assert_eq!(v.try_swap_remove(1), None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Reference in a new issue