@@ -211,6 +211,44 @@ pub type Pager<P, F = JsonFormat> = ItemIterator<Response<P, F>>;
211211pub struct PagerOptions < ' a > {
212212 /// Context for HTTP requests made by the [`Pager`].
213213 pub context : Context < ' a > ,
214+
215+ /// Optional continuation token or next link to resume paging.
216+ ///
217+ /// # Examples
218+ ///
219+ /// ``` no_run
220+ /// use azure_core::http::pager::PagerOptions;
221+ /// use azure_identity::DeveloperToolsCredential;
222+ /// use azure_security_keyvault_secrets::{
223+ /// models::SecretClientListSecretPropertiesOptions,
224+ /// SecretClient,
225+ /// };
226+ /// use futures::stream::TryStreamExt as _;
227+ ///
228+ /// # #[tokio::main]
229+ /// # async fn main() -> azure_core::Result<()> {
230+ /// let client = SecretClient::new("https://my-vault.vault.azure.net", DeveloperToolsCredential::new(None)?, None)?;
231+ ///
232+ /// // Start the first pager at the first page.
233+ /// let mut pager = client.list_secret_properties(None)?;
234+ ///
235+ /// // Continue the second pager from where the first pager left off,
236+ /// // which is the first page in this example.
237+ /// let options = SecretClientListSecretPropertiesOptions {
238+ /// method_options: PagerOptions {
239+ /// continuation_token: pager.continuation_token(),
240+ /// ..Default::default()
241+ /// },
242+ /// ..Default::default()
243+ /// };
244+ /// let mut pager = client.list_secret_properties(Some(options))?;
245+ /// while let Some(secret) = pager.try_next().await? {
246+ /// println!("{:?}", secret.id);
247+ /// }
248+ /// # Ok(())
249+ /// # }
250+ /// ```
251+ pub continuation_token : Option < String > ,
214252}
215253
216254#[ cfg( not( target_arch = "wasm32" ) ) ]
@@ -405,12 +443,15 @@ impl<P: Page> ItemIterator<P> {
405443 <C as FromStr >:: Err : std:: error:: Error ,
406444 {
407445 let options = options. unwrap_or_default ( ) ;
408- let next_token = Arc :: new ( Mutex :: new ( None :: < String > ) ) ;
446+
447+ // Start from the optional `PagerOptions::continuation_token`.
448+ let continuation_token = options. continuation_token . clone ( ) ;
449+ let next_token = Arc :: new ( Mutex :: new ( continuation_token. clone ( ) ) ) ;
409450 let stream = iter_from_callback ( make_request, options, next_token. clone ( ) ) ;
410451
411452 Self {
412453 stream : Box :: pin ( stream) ,
413- continuation_token : None ,
454+ continuation_token,
414455 next_token,
415456 current : None ,
416457 }
@@ -456,52 +497,9 @@ impl<P: Page> ItemIterator<P> {
456497 }
457498 }
458499
459- /// Start the `ItemIterator` at the page referenced by `continuation_token`.
460- ///
461- /// You should call this before iterating the [`Stream`] or results may be unpredictable.
462- /// Iteration of items will start from the beginning on the current page until _after_ all items are iterated.
463- /// It does not continue on the next page until you call `next()` after the last item in the current page
464- /// because of how iterators are implemented. This may yield duplicates but will reduce the likelihood of skipping items instead.
465- ///
466- /// # Examples
467- ///
468- /// Using a result of a call to [`ItemIterator::continuation_token`] in another process, you can create a new `ItemIterator`
469- /// that, when first iterated, will get the next page of results.
470- ///
471- /// ``` no_run
472- /// use azure_identity::DeveloperToolsCredential;
473- /// use azure_security_keyvault_secrets::SecretClient;
474- /// use futures::stream::TryStreamExt as _;
475- ///
476- /// # #[tokio::main]
477- /// # async fn main() -> azure_core::Result<()> {
478- /// let client = SecretClient::new("https://my-vault.vault.azure.net", DeveloperToolsCredential::new(None)?, None)?;
479- ///
480- /// // Start the first pager at the first page.
481- /// let mut pager = client.list_secret_properties(None)?;
482- ///
483- /// // Continue the second pager from where the first pager left off,
484- /// // which is the first page in this example.
485- /// let mut pager = client.list_secret_properties(None)?
486- /// .with_continuation_token(Some("continuation_token_from_another_pager".into()));
487- ///
488- /// while let Some(secret) = pager.try_next().await? {
489- /// println!("{:?}", secret.id);
490- /// }
491- /// # Ok(())
492- /// # }
493- /// ```
494- pub fn with_continuation_token ( self , continuation_token : Option < String > ) -> Self {
495- // Set the next_token because that's what is passed to iter_from_callback to get the initial page.
496- if let Ok ( mut token) = self . next_token . lock ( ) {
497- * token = continuation_token;
498- }
499- self
500- }
501-
502500 /// Gets the continuation token for the current page.
503501 ///
504- /// Pass this to [`ItemIterator::with_continuation_token `] to create a `ItemIterator` that, when first iterated,
502+ /// Pass this in [`PagerOptions::continuation_token `] to create a `ItemIterator` that, when first iterated,
505503 /// will return the current page until _after_ all items are iterated.
506504 /// It does not continue on the next page until you call `next()` after the last item in the current page
507505 /// because of how iterators are implemented. This may yield duplicates but will reduce the likelihood of skipping items instead.
@@ -560,7 +558,9 @@ impl<P: Page> futures::Stream for ItemIterator<P> {
560558
561559impl < P : Page > fmt:: Debug for ItemIterator < P > {
562560 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
563- f. debug_struct ( "ItemIterator" ) . finish_non_exhaustive ( )
561+ f. debug_struct ( "ItemIterator" )
562+ . field ( "continuation_token" , & self . continuation_token )
563+ . finish_non_exhaustive ( )
564564 }
565565}
566566
@@ -707,7 +707,9 @@ impl<P> PageIterator<P> {
707707 <C as FromStr >:: Err : std:: error:: Error ,
708708 {
709709 let options = options. unwrap_or_default ( ) ;
710- let continuation_token = Arc :: new ( Mutex :: new ( None :: < String > ) ) ;
710+
711+ // Start from the optional `PagerOptions::continuation_token`.
712+ let continuation_token = Arc :: new ( Mutex :: new ( options. continuation_token . clone ( ) ) ) ;
711713 let stream = iter_from_callback ( make_request, options, continuation_token. clone ( ) ) ;
712714
713715 Self {
@@ -732,54 +734,9 @@ impl<P> PageIterator<P> {
732734 }
733735 }
734736
735- /// Start the `PageIterator` at the page referenced by `continuation_token`.
736- ///
737- /// You should call this before iterating the [`Stream`] or results may be unpredictable.
738- ///
739- /// # Examples
740- ///
741- /// Using a result of a call to [`PageIterator::continuation_token`] in another process, you can create a new `PageIterator`
742- /// that, when first iterated, will get the next page of results.
743- ///
744- /// ``` no_run
745- /// use azure_identity::DeveloperToolsCredential;
746- /// use azure_security_keyvault_secrets::SecretClient;
747- /// use futures::stream::TryStreamExt as _;
748- ///
749- /// # #[tokio::main]
750- /// # async fn main() -> azure_core::Result<()> {
751- /// let client = SecretClient::new("https://my-vault.vault.azure.net", DeveloperToolsCredential::new(None)?, None)?;
752- ///
753- /// // Start the first pager at the first page.
754- /// let mut pager = client.list_secret_properties(None)?
755- /// .into_pages();
756- ///
757- /// // Continue the second pager from where the first pager left off,
758- /// // which is the first page in this example.
759- /// let mut pager = client.list_secret_properties(None)?
760- /// .into_pages()
761- /// .with_continuation_token("continuation_token_from_another_pager".to_string());
762- ///
763- /// while let Some(secrets) = pager.try_next().await? {
764- /// let secrets = secrets.into_model()?;
765- /// for secret in secrets.value {
766- /// println!("{:?}", secret.id);
767- /// }
768- /// }
769- /// # Ok(())
770- /// # }
771- /// ```
772- pub fn with_continuation_token ( self , continuation_token : String ) -> Self {
773- if let Ok ( mut token_guard) = self . continuation_token . lock ( ) {
774- * token_guard = Some ( continuation_token) ;
775- }
776-
777- self
778- }
779-
780737 /// Gets the continuation token for the current page.
781738 ///
782- /// Pass this to [`PageIterator::with_continuation_token `] to create a `PageIterator` that, when first iterated,
739+ /// Pass this to [`PagerOptions::continuation_token `] to create a `PageIterator` that, when first iterated,
783740 /// will return the next page. You can use this to page results across separate processes.
784741 pub fn continuation_token ( & self ) -> Option < String > {
785742 if let Ok ( token) = self . continuation_token . lock ( ) {
@@ -1165,9 +1122,13 @@ mod tests {
11651122 assert_eq ! ( continuation_token, "next-token-1" ) ;
11661123
11671124 // Create the second PageIterator.
1168- let mut second_pager: PageIterator < Response < Page > > =
1169- PageIterator :: from_callback ( make_three_page_callback ( ) , None )
1170- . with_continuation_token ( continuation_token) ;
1125+ let mut second_pager: PageIterator < Response < Page > > = PageIterator :: from_callback (
1126+ make_three_page_callback ( ) ,
1127+ Some ( PagerOptions {
1128+ continuation_token : Some ( continuation_token) ,
1129+ ..Default :: default ( )
1130+ } ) ,
1131+ ) ;
11711132
11721133 // Should start with link to second page.
11731134 assert_eq ! (
@@ -1348,8 +1309,13 @@ mod tests {
13481309 assert_eq ! ( continuation_token, None ) ;
13491310
13501311 // Create the second ItemIterator with continuation token.
1351- let mut second_pager: Pager < Page > = Pager :: from_callback ( make_three_page_callback ( ) , None )
1352- . with_continuation_token ( continuation_token) ;
1312+ let mut second_pager: Pager < Page > = Pager :: from_callback (
1313+ make_three_page_callback ( ) ,
1314+ Some ( PagerOptions {
1315+ continuation_token,
1316+ ..Default :: default ( )
1317+ } ) ,
1318+ ) ;
13531319
13541320 // Should start with link to first page.
13551321 assert_eq ! ( second_pager. continuation_token( ) , None ) ;
@@ -1422,8 +1388,13 @@ mod tests {
14221388 assert_eq ! ( continuation_token. as_deref( ) , Some ( "next-token-1" ) ) ;
14231389
14241390 // Create the second ItemIterator with continuation token.
1425- let mut second_pager: Pager < Page > = Pager :: from_callback ( make_three_page_callback ( ) , None )
1426- . with_continuation_token ( continuation_token) ;
1391+ let mut second_pager: Pager < Page > = Pager :: from_callback (
1392+ make_three_page_callback ( ) ,
1393+ Some ( PagerOptions {
1394+ continuation_token,
1395+ ..Default :: default ( )
1396+ } ) ,
1397+ ) ;
14271398
14281399 // When continuing with a continuation token, we should start over from the
14291400 // beginning of the current page (second page), not where we left off.
@@ -1475,8 +1446,13 @@ mod tests {
14751446 assert_eq ! ( continuation_token, None ) ;
14761447
14771448 // Create the second ItemIterator with continuation token.
1478- let mut second_pager: Pager < Page > = Pager :: from_callback ( make_three_page_callback ( ) , None )
1479- . with_continuation_token ( continuation_token) ;
1449+ let mut second_pager: Pager < Page > = Pager :: from_callback (
1450+ make_three_page_callback ( ) ,
1451+ Some ( PagerOptions {
1452+ continuation_token,
1453+ ..Default :: default ( )
1454+ } ) ,
1455+ ) ;
14801456
14811457 // When continuing with a continuation token after finishing a page, we should
14821458 // start from the beginning of the current page.
0 commit comments